(count_blanks): Leave argument r constant, and increment p.
[bpt/emacs.git] / src / sysdep.c
CommitLineData
86a5659e 1/* Interfaces to system-dependent kernel and library entries.
91bac16a 2 Copyright (C) 1985, 1986, 1987, 1988, 1992 Free Software Foundation, Inc.
86a5659e
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include <signal.h>
22#include <setjmp.h>
23
24#include "config.h"
25#include "lisp.h"
26#undef NULL
27
28#define min(x,y) ((x) > (y) ? (y) : (x))
29
30/* In this file, open, read and write refer to the system calls,
31 not our sugared interfaces sys_open, sys_read and sys_write.
32 Contrariwise, for systems where we use the system calls directly,
33 define sys_read, etc. here as aliases for them. */
34#ifndef read
35#define sys_read read
36#define sys_write write
37#endif /* `read' is not a macro */
38
39#undef read
40#undef write
41
42#ifndef close
43#define sys_close close
44#else
45#undef close
46#endif
47
48#ifndef open
49#define sys_open open
50#else /* `open' is a macro */
51#undef open
52#endif /* `open' is a macro */
53
54#include <stdio.h>
55#include <sys/types.h>
56#include <sys/stat.h>
57#include <errno.h>
58
59extern int errno;
60#ifndef VMS
61extern char *sys_errlist[];
62#endif
63
64#ifdef VMS
65#include <rms.h>
66#include <ttdef.h>
67#include <tt2def.h>
68#include <iodef.h>
69#include <ssdef.h>
70#include <descrip.h>
71#include <fibdef.h>
72#include <atrdef.h>
73#include <ctype.h>
74#include <string.h>
75#ifdef __GNUC__
76#include <sys/file.h>
77#else
78#include <file.h>
79#endif
80#undef F_SETFL
81#ifndef RAB$C_BID
82#include <rab.h>
83#endif
84#define MAXIOSIZE ( 32 * PAGESIZE ) /* Don't I/O more than 32 blocks at a time */
85#endif /* VMS */
86
87#ifndef BSD4_1
88#ifdef BSD /* this is done this way to avoid defined (BSD) || defined (USG)
89 because the vms compiler doesn't grok `defined' */
90#include <fcntl.h>
91#endif
92#ifdef USG
34567704 93#ifndef USG5
86a5659e
JB
94#include <fcntl.h>
95#endif
34567704 96#endif
86a5659e
JB
97#endif /* not 4.1 bsd */
98
99/* Get DGUX definition for FASYNC - DJB */
100#ifdef DGUX
101#include <sys/file.h>
102#endif /* DGUX */
103
104#include <sys/ioctl.h>
e04a4e0d 105#include "systty.h"
86a5659e
JB
106
107#ifdef BSD
108#ifdef BSD4_1
109#include <wait.h>
110#else /* not 4.1 */
111#include <sys/wait.h>
112#endif /* not 4.1 */
113#endif /* BSD */
114
86a5659e
JB
115#ifdef BROKEN_TIOCGWINSZ
116#undef TIOCGWINSZ
117#endif
118
86a5659e
JB
119#ifdef USG
120#include <sys/utsname.h>
121#include <string.h>
122#ifndef MEMORY_IN_STRING_H
123#include <memory.h>
124#endif
125#ifdef TIOCGWINSZ
126#ifdef NEED_SIOCTL
127#include <sys/sioctl.h>
128#endif
129#ifdef NEED_PTEM_H
130#include <sys/stream.h>
131#include <sys/ptem.h>
132#endif
133#endif /* TIOCGWINSZ */
86a5659e
JB
134#endif /* USG */
135
86a5659e
JB
136extern int quit_char;
137
0137dbf7 138#include "frame.h"
86a5659e
JB
139#include "window.h"
140#include "termhooks.h"
141#include "termchar.h"
142#include "termopts.h"
143#include "dispextern.h"
144#include "process.h"
145
146#ifdef NONSYSTEM_DIR_LIBRARY
147#include "ndir.h"
148#endif /* NONSYSTEM_DIR_LIBRARY */
149
91bac16a
JB
150#include "syssignal.h"
151#include "systime.h"
86a5659e
JB
152
153static int baud_convert[] =
154#ifdef BAUD_CONVERT
155 BAUD_CONVERT;
156#else
157 {
158 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
159 1800, 2400, 4800, 9600, 19200, 38400
160 };
161#endif
162
163extern short ospeed;
164
91bac16a
JB
165/* The file descriptor for Emacs's input terminal.
166 Under Unix, this is always left zero;
167 under VMS, we place the input channel number here.
168 This allows us to write more code that works for both VMS and Unix. */
169static int input_fd;
170
86a5659e
JB
171#ifdef VMS
172static struct iosb
173{
174 short status;
175 short offset;
176 short termlen;
177 short term;
178} input_iosb;
179
180int kbd_input_ast ();
181
182int waiting_for_ast;
183int stop_input;
184int input_ef = 0;
185int timer_ef = 0;
186int process_ef = 0;
187int input_eflist;
188int timer_eflist;
189
86a5659e
JB
190static $DESCRIPTOR (input_dsc, "TT");
191static int terminator_mask[2] = { 0, 0 };
192
193static struct sensemode {
194 short status;
195 unsigned char xmit_baud;
196 unsigned char rcv_baud;
197 unsigned char crfill;
198 unsigned char lffill;
199 unsigned char parity;
200 unsigned char unused;
201 char class;
202 char type;
203 short scr_wid;
204 unsigned long tt_char : 24, scr_len : 8;
205 unsigned long tt2_char;
206} sensemode_iosb;
86a5659e
JB
207#endif /* VMS */
208
209discard_tty_input ()
210{
91bac16a 211 struct emacs_tty buf;
86a5659e
JB
212
213 if (noninteractive)
214 return;
215
216 /* Discarding input is not safe when the input could contain
217 replies from the X server. So don't do it. */
218 if (read_socket_hook)
219 return;
220
221#ifdef VMS
222 end_kbd_input ();
91bac16a
JB
223 SYS$QIOW (0, input_fd, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
224 &buf.main, 0, 0, terminator_mask, 0, 0);
86a5659e
JB
225 queue_kbd_input ();
226#else /* not VMS */
227#ifdef APOLLO
228 {
229 int zero = 0;
230 ioctl (0, TIOCFLUSH, &zero);
231 }
232#else /* not Apollo */
91bac16a
JB
233 EMACS_GET_TTY (input_fd, &buf);
234 EMACS_SET_TTY (input_fd, &buf, 0);
86a5659e
JB
235#endif /* not Apollo */
236#endif /* not VMS */
237}
238
239#ifdef SIGTSTP
240
241stuff_char (c)
242 char c;
243{
244/* Should perhaps error if in batch mode */
245#ifdef TIOCSTI
246 ioctl (0, TIOCSTI, &c);
247#else /* no TIOCSTI */
248 error ("Cannot stuff terminal input characters in this version of Unix.");
249#endif /* no TIOCSTI */
250}
251
252#endif /* SIGTSTP */
253
254init_baud_rate ()
255{
86a5659e
JB
256 if (noninteractive)
257 ospeed = 0;
258 else
259 {
260#ifdef VMS
91bac16a
JB
261 struct sensemode sg;
262
263 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &sg, 0, 0,
86a5659e 264 &sg.class, 12, 0, 0, 0, 0 );
91bac16a
JB
265 ospeed = sg.xmit_baud;
266#else /* not VMS */
e04a4e0d
JB
267#ifdef HAVE_TERMIOS
268 struct termios sg;
91bac16a
JB
269
270 sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
271 tcgetattr (0, &sg);
272 ospeed = sg.c_cflag & CBAUD;
e04a4e0d
JB
273#else /* neither VMS nor TERMIOS */
274#ifdef HAVE_TERMIO
275 struct termio sg;
91bac16a
JB
276
277 sg.c_cflag = (sg.c_cflag & ~CBAUD) | B9600;
e04a4e0d 278#ifdef HAVE_TCATTR
86a5659e 279 tcgetattr (0, &sg);
e04a4e0d
JB
280#else
281 ioctl (fd, TIOCGETP, &sg);
282#endif
91bac16a 283 ospeed = sg.c_cflag & CBAUD;
e04a4e0d 284#else /* neither VMS nor TERMIOS nor TERMIO */
91bac16a
JB
285 struct sgttyb sg;
286
287 sg.sg_ospeed = B9600;
288 ioctl (0, TIOCGETP, &sg);
289 ospeed = sg.sg_ospeed;
91bac16a 290#endif /* not HAVE_TERMIO */
e04a4e0d 291#endif /* not HAVE_TERMIOS */
86a5659e 292#endif /* not VMS */
86a5659e
JB
293 }
294
295 baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
296 ? baud_convert[ospeed] : 9600);
297 if (baud_rate == 0)
298 baud_rate = 1200;
299}
300
301/*ARGSUSED*/
302set_exclusive_use (fd)
303 int fd;
304{
305#ifdef FIOCLEX
306 ioctl (fd, FIOCLEX, 0);
307#endif
308 /* Ok to do nothing if this feature does not exist */
309}
310
311#ifndef subprocesses
312
313wait_without_blocking ()
314{
315#ifdef BSD
316 wait3 (0, WNOHANG | WUNTRACED, 0);
317#else
318 croak ("wait_without_blocking");
319#endif
320 synch_process_alive = 0;
321}
322
323#endif /* not subprocesses */
324
325int wait_debugging; /* Set nonzero to make following function work under dbx
326 (at least for bsd). */
327
328SIGTYPE
329wait_for_termination_signal ()
330{}
331
332/* Wait for subprocess with process id `pid' to terminate and
333 make sure it will get eliminated (not remain forever as a zombie) */
334
335wait_for_termination (pid)
336 int pid;
337{
338 while (1)
339 {
340#ifdef subprocesses
341#ifdef VMS
342 int status;
343
344 status = sys$forcex (&pid, 0, 0);
345 break;
346#else /* not VMS */
347
348 /* Exit if the process has terminated. */
349 if (!synch_process_alive)
350 break;
351 /* Otherwise wait 1 second or until a signal comes in. */
352 signal (SIGALRM, wait_for_termination_signal);
353 alarm (1);
354 pause ();
355 alarm (0);
356 signal (SIGALRM, SIG_IGN);
357#endif /* not VMS */
358#else /* not subprocesses */
359#ifndef BSD4_1
360 if (kill (pid, 0) < 0)
361 break;
362 wait (0);
363#else /* BSD4_1 */
364 int status;
365 status = wait (0);
366 if (status == pid || status == -1)
367 break;
368#endif /* BSD4_1 */
369#endif /* not subprocesses */
370 }
371}
372
373#ifdef subprocesses
374
375/*
376 * flush any pending output
377 * (may flush input as well; it does not matter the way we use it)
378 */
379
380flush_pending_output (channel)
381 int channel;
382{
383#ifdef HAVE_TERMIOS
384 /* If we try this, we get hit with SIGTTIN, because
385 the child's tty belongs to the child's pgrp. */
386#else
387#ifdef TCFLSH
388 ioctl (channel, TCFLSH, 1);
389#else
390#ifdef TIOCFLUSH
391 int zero = 0;
392 /* 3rd arg should be ignored
393 but some 4.2 kernels actually want the address of an int
394 and nonzero means something different. */
395 ioctl (channel, TIOCFLUSH, &zero);
396#endif
397#endif
398#endif
399}
400
401#ifndef VMS
402/* Set up the terminal at the other end of a pseudo-terminal that
403 we will be controlling an inferior through.
404 It should not echo or do line-editing, since that is done
405 in Emacs. No padding needed for insertion into an Emacs buffer. */
406
407child_setup_tty (out)
408 int out;
409{
91bac16a
JB
410 struct emacs_tty s;
411
412 EMACS_GET_TTY (out, &s);
86a5659e 413
86a5659e 414#ifdef HAVE_TERMIO
91bac16a
JB
415 s.main.c_oflag |= OPOST; /* Enable output postprocessing */
416 s.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */
417 s.main.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
418 /* No output delays */
419 s.main.c_lflag &= ~ECHO; /* Disable echo */
420 s.main.c_lflag |= ISIG; /* Enable signals */
421 s.main.c_iflag &= ~IUCLC; /* Disable map of upper case to lower on
422 input */
423 s.main.c_oflag &= ~OLCUC; /* Disable map of lower case to upper on
424 output */
425#if 0
426 /* Said to be unnecesary: */
427 s.main.c_cc[VMIN] = 1; /* minimum number of characters to accept */
428 s.main.c_cc[VTIME] = 0; /* wait forever for at least 1 character */
429#endif
430
431 s.main.c_lflag |= ICANON; /* Enable erase/kill and eof processing */
432 s.main.c_cc[VEOF] = 04; /* insure that EOF is Control-D */
433 s.main.c_cc[VERASE] = 0377; /* disable erase processing */
434 s.main.c_cc[VKILL] = 0377; /* disable kill processing */
435
86a5659e 436#ifdef HPUX
91bac16a 437 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
86a5659e 438#endif /* HPUX */
91bac16a 439
86a5659e
JB
440#ifdef AIX
441/* AIX enhanced edit loses NULs, so disable it */
442#ifndef IBMR2AIX
91bac16a
JB
443 s.main.c_line = 0;
444 s.main.c_iflag &= ~ASCEDIT;
86a5659e
JB
445#endif
446 /* Also, PTY overloads NUL and BREAK.
447 don't ignore break, but don't signal either, so it looks like NUL. */
91bac16a
JB
448 s.main.c_iflag &= ~IGNBRK;
449 s.main.c_iflag &= ~BRKINT;
450 /* QUIT and INTR work better as signals, so disable character forms */
451 s.main.c_cc[VQUIT] = 0377;
452 s.main.c_cc[VINTR] = 0377;
453 s.main.c_cc[VEOL] = 0377;
454 s.main.c_lflag &= ~ISIG;
455 s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
86a5659e
JB
456#endif /* AIX */
457
458#else /* not HAVE_TERMIO */
91bac16a
JB
459
460 s.main.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE
461 | CBREAK | TANDEM);
462 s.main.sg_erase = 0377;
463 s.main.sg_kill = 0377;
464
86a5659e
JB
465#endif /* not HAVE_TERMIO */
466
91bac16a 467 EMACS_SET_TTY (out, &s, 0);
86a5659e
JB
468
469#ifdef BSD4_1
470 if (interrupt_input)
471 reset_sigio ();
472#endif /* BSD4_1 */
473#ifdef RTU
474 {
475 int zero = 0;
476 ioctl (out, FIOASYNC, &zero);
477 }
478#endif /* RTU */
479}
480#endif /* not VMS */
481
482#endif /* subprocesses */
483
484/*ARGSUSED*/
485setpgrp_of_tty (pid)
486 int pid;
487{
ffd56f97 488 EMACS_SET_TTY_PGRP (input_fd, &pid);
86a5659e
JB
489}
490
491/* Record a signal code and the handler for it. */
492struct save_signal
493{
494 int code;
495 SIGTYPE (*handler) ();
496};
497
498/* Suspend the Emacs process; give terminal to its superior. */
499
500sys_suspend ()
501{
502#ifdef VMS
88191e36
RS
503 /* "Foster" parentage allows emacs to return to a subprocess that attached
504 to the current emacs as a cheaper than starting a whole new process. This
505 is set up by KEPTEDITOR.COM. */
506 unsigned long parent_id, foster_parent_id;
507 char *fpid_string;
508
509 fpid_string = getenv ("EMACS_PARENT_PID");
510 if (fpid_string != NULL)
511 {
512 sscanf (fpid_string, "%x", &foster_parent_id);
513 if (foster_parent_id != 0)
514 parent_id = foster_parent_id;
515 else
516 parent_id = getppid ();
517 }
518 else
519 parent_id = getppid ();
520
521 free (fpid_string); /* On VMS, this was malloc'd */
86a5659e 522
86a5659e
JB
523 if (parent_id && parent_id != 0xffffffff)
524 {
525 SIGTYPE (*oldsig)() = (int) signal (SIGINT, SIG_IGN);
526 int status = LIB$ATTACH (&parent_id) & 1;
527 signal (SIGINT, oldsig);
528 return status;
529 }
530 else
531 {
532 struct {
533 int l;
534 char *a;
535 } d_prompt;
536 d_prompt.l = sizeof ("Emacs: "); /* Our special prompt */
537 d_prompt.a = "Emacs: "; /* Just a reminder */
538 lib$spawn (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &d_prompt, 0);
539 return 1;
540 }
541 return -1;
542#else
543#ifdef SIGTSTP
544
91bac16a 545 EMACS_KILLPG (getpgrp (0), SIGTSTP);
86a5659e
JB
546
547#else /* No SIGTSTP */
548#ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
549 ptrace (0, 0, 0, 0); /* set for ptrace - caught by csh */
550 kill (getpid (), SIGQUIT);
551
552#else /* No SIGTSTP or USG_JOBCTRL */
553
554/* On a system where suspending is not implemented,
555 instead fork a subshell and let it talk directly to the terminal
556 while we wait. */
557 int pid = fork ();
558 struct save_signal saved_handlers[5];
559
560 saved_handlers[0].code = SIGINT;
561 saved_handlers[1].code = SIGQUIT;
562 saved_handlers[2].code = SIGTERM;
563#ifdef SIGIO
564 saved_handlers[3].code = SIGIO;
565 saved_handlers[4].code = 0;
566#else
567 saved_handlers[3].code = 0;
568#endif
569
570 if (pid == -1)
571 error ("Can't spawn subshell");
572 if (pid == 0)
573 {
574 char *sh;
575
576 sh = (char *) egetenv ("SHELL");
577 if (sh == 0)
578 sh = "sh";
579 /* Use our buffer's default directory for the subshell. */
580 {
581 Lisp_Object dir;
582 unsigned char *str;
583 int len;
584
585 /* mentioning current_buffer->buffer would mean including buffer.h,
586 which somehow wedges the hp compiler. So instead... */
587
588 dir = intern ("default-directory");
589 /* Can't use NULL */
590 if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
591 goto xyzzy;
592 dir = Fsymbol_value (dir);
593 if (XTYPE (dir) != Lisp_String)
594 goto xyzzy;
595
596 str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
597 len = XSTRING (dir)->size;
598 bcopy (XSTRING (dir)->data, str, len);
599 if (str[len - 1] != '/') str[len++] = '/';
600 str[len] = 0;
601 chdir (str);
602 }
603 xyzzy:
604#ifdef subprocesses
605 close_process_descs (); /* Close Emacs's pipes/ptys */
606#endif
1593c2fe
JB
607
608#ifdef PRIO_PROCESS
609 {
610 extern int emacs_priority;
611
612 if (emacs_priority)
613 nice (-emacs_priority);
614 }
615#endif
616
86a5659e
JB
617 execlp (sh, sh, 0);
618 write (1, "Can't execute subshell", 22);
619 _exit (1);
620 }
621
622 save_signal_handlers (saved_handlers);
623 wait_for_termination (pid);
624 restore_signal_handlers (saved_handlers);
625
626#endif /* no USG_JOBCTRL */
627#endif /* no SIGTSTP */
628#endif /* not VMS */
629}
630
631save_signal_handlers (saved_handlers)
632 struct save_signal *saved_handlers;
633{
634 while (saved_handlers->code)
635 {
508b171c
JA
636 saved_handlers->handler
637 = (SIGTYPE (*) ()) signal (saved_handlers->code, SIG_IGN);
86a5659e
JB
638 saved_handlers++;
639 }
640}
641
642restore_signal_handlers (saved_handlers)
643 struct save_signal *saved_handlers;
644{
645 while (saved_handlers->code)
646 {
647 signal (saved_handlers->code, saved_handlers->handler);
648 saved_handlers++;
649 }
650}
651\f
652#ifdef F_SETFL
653
654int old_fcntl_flags;
655
656init_sigio ()
657{
658#ifdef FASYNC
659 old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
660#endif
661 request_sigio ();
662}
663
664reset_sigio ()
665{
666 unrequest_sigio ();
667}
668
669#ifdef FASYNC /* F_SETFL does not imply existance of FASYNC */
670
671request_sigio ()
672{
673#ifdef SIGWINCH
e065a56e 674 sigunblock (sigmask (SIGWINCH));
86a5659e
JB
675#endif
676 fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
677
678 interrupts_deferred = 0;
679}
680
681unrequest_sigio ()
682{
683#ifdef SIGWINCH
e065a56e 684 sigblock (sigmask (SIGWINCH));
86a5659e
JB
685#endif
686 fcntl (0, F_SETFL, old_fcntl_flags);
687 interrupts_deferred = 1;
688}
689
690#else /* no FASYNC */
691#ifdef STRIDE /* Stride doesn't have FASYNC - use FIOASYNC */
692
693request_sigio ()
694{
695 int on = 1;
696 ioctl (0, FIOASYNC, &on);
697 interrupts_deferred = 0;
698}
699
700unrequest_sigio ()
701{
702 int off = 0;
703
704 ioctl (0, FIOASYNC, &off);
705 interrupts_deferred = 1;
706}
707
708#else /* not FASYNC, not STRIDE */
709
710request_sigio ()
711{
712 croak ("request_sigio");
713}
714
715unrequest_sigio ()
716{
717 croak ("unrequest_sigio");
718}
719
720#endif /* STRIDE */
721#endif /* FASYNC */
722#endif /* F_SETFL */
723\f
91bac16a
JB
724/* The initial tty mode bits */
725struct emacs_tty old_tty;
86a5659e
JB
726
727int term_initted; /* 1 if outer tty status has been recorded */
728
91bac16a
JB
729#ifdef BSD4_1
730/* BSD 4.1 needs to keep track of the lmode bits in order to start
731 sigio. */
732int lmode;
733#endif
734
86a5659e
JB
735#ifdef F_SETOWN
736int old_fcntl_owner;
737#endif /* F_SETOWN */
738
86a5659e
JB
739/* This may also be defined in stdio,
740 but if so, this does no harm,
741 and using the same name avoids wasting the other one's space. */
742
743#if defined (USG) || defined (DGUX)
744unsigned char _sobuf[BUFSIZ+8];
745#else
746char _sobuf[BUFSIZ];
747#endif
748
749#ifdef TIOCGLTC
750static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
751#endif
752#ifdef TIOCGETC
753 static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
754#endif
755
756init_sys_modes ()
757{
91bac16a
JB
758 struct emacs_tty tty;
759
86a5659e
JB
760#ifdef VMS
761#if 0
762 static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
763 extern int (*interrupt_signal) ();
764#endif
765#endif
766
767 if (noninteractive)
768 return;
769
770#ifdef VMS
771 if (!input_ef)
772 input_ef = get_kbd_event_flag ();
773 /* LIB$GET_EF (&input_ef); */
774 SYS$CLREF (input_ef);
775 waiting_for_ast = 0;
776 if (!timer_ef)
777 timer_ef = get_timer_event_flag ();
778 /* LIB$GET_EF (&timer_ef); */
779 SYS$CLREF (timer_ef);
780 if (!process_ef)
781 {
782 LIB$GET_EF (&process_ef);
783 SYS$CLREF (process_ef);
784 }
785 if (input_ef / 32 != process_ef / 32)
786 croak ("Input and process event flags in different clusters.");
787 if (input_ef / 32 != timer_ef / 32)
788 croak ("Input and process event flags in different clusters.");
789 input_eflist = ((unsigned) 1 << (input_ef % 32)) |
790 ((unsigned) 1 << (process_ef % 32));
791 timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
792 ((unsigned) 1 << (timer_ef % 32));
86a5659e
JB
793#ifndef VMS4_4
794 sys_access_reinit ();
795#endif
86a5659e 796#endif /* not VMS */
91bac16a
JB
797
798 EMACS_GET_TTY (input_fd, &old_tty);
799
86a5659e
JB
800 if (!read_socket_hook && EQ (Vwindow_system, Qnil))
801 {
91bac16a 802 tty = old_tty;
86a5659e
JB
803
804#ifdef HAVE_TERMIO
91bac16a
JB
805 tty.main.c_iflag |= (IGNBRK); /* Ignore break condition */
806 tty.main.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */
86a5659e 807#ifdef ISTRIP
91bac16a 808 tty.main.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */
86a5659e 809#endif
91bac16a
JB
810 tty.main.c_lflag &= ~ECHO; /* Disable echo */
811 tty.main.c_lflag &= ~ICANON; /* Disable erase/kill processing */
e2b40c23
RS
812#ifdef IEXTEN
813 tty.main.c_iflag &= ~IEXTEN; /* Disable other editing characters. */
814#endif
91bac16a 815 tty.main.c_lflag |= ISIG; /* Enable signals */
86a5659e
JB
816 if (flow_control)
817 {
91bac16a 818 tty.main.c_iflag |= IXON; /* Enable start/stop output control */
86a5659e 819#ifdef IXANY
91bac16a 820 tty.main.c_iflag &= ~IXANY;
86a5659e
JB
821#endif /* IXANY */
822 }
823 else
91bac16a
JB
824 tty.main.c_iflag &= ~IXON; /* Disable start/stop output control */
825 tty.main.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL
826 on output */
827 tty.main.c_oflag &= ~TAB3; /* Disable tab expansion */
86a5659e
JB
828#ifdef CS8
829 if (meta_key)
830 {
91bac16a
JB
831 tty.main.c_cflag |= CS8; /* allow 8th bit on input */
832 tty.main.c_cflag &= ~PARENB;/* Don't check parity */
86a5659e
JB
833 }
834#endif
91bac16a 835 tty.main.c_cc[VINTR] = quit_char; /* C-g (usually) gives SIGINT */
86a5659e
JB
836 /* Set up C-g for both SIGQUIT and SIGINT.
837 We don't know which we will get, but we handle both alike
838 so which one it really gives us does not matter. */
91bac16a
JB
839 tty.main.c_cc[VQUIT] = quit_char;
840 tty.main.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */
841 tty.main.c_cc[VTIME] = 0; /* no matter how long that takes. */
86a5659e 842#ifdef VSWTCH
e2b40c23 843 tty.main.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use
91bac16a 844 of C-z */
86a5659e
JB
845#endif /* VSWTCH */
846#if defined (mips) || defined (HAVE_TCATTR)
86a5659e 847#ifdef VSUSP
e2b40c23 848 tty.main.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */
86a5659e
JB
849#endif /* VSUSP */
850#ifdef V_DSUSP
e2b40c23 851 tty.main.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */
86a5659e 852#endif /* V_DSUSP */
e2b40c23
RS
853#ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */
854 tty.main.c_cc[VDSUSP] = CDISABLE;
855#endif /* VDSUSP */
86a5659e
JB
856#endif /* mips or HAVE_TCATTR */
857#ifdef AIX
858#ifndef IBMR2AIX
859 /* AIX enhanced edit loses NULs, so disable it */
91bac16a
JB
860 tty.main.c_line = 0;
861 tty.main.c_iflag &= ~ASCEDIT;
86a5659e 862#else
91bac16a
JB
863 tty.main.c_cc[VSTRT] = 255;
864 tty.main.c_cc[VSTOP] = 255;
865 tty.main.c_cc[VSUSP] = 255;
866 tty.main.c_cc[VDSUSP] = 255;
86a5659e
JB
867#endif /* IBMR2AIX */
868 /* Also, PTY overloads NUL and BREAK.
869 don't ignore break, but don't signal either, so it looks like NUL.
870 This really serves a purpose only if running in an XTERM window
871 or via TELNET or the like, but does no harm elsewhere. */
91bac16a
JB
872 tty.main.c_iflag &= ~IGNBRK;
873 tty.main.c_iflag &= ~BRKINT;
86a5659e
JB
874#endif
875#else /* if not HAVE_TERMIO */
876#ifdef VMS
91bac16a 877 tty.main.tt_char |= TT$M_NOECHO;
86a5659e 878 if (meta_key)
91bac16a 879 tty.main.tt_char |= TT$M_EIGHTBIT
86a5659e 880 if (flow_control)
91bac16a 881 tty.main.tt_char |= TT$M_TTSYNC;
86a5659e 882 else
91bac16a
JB
883 tty.main.tt_char &= ~TT$M_TTSYNC;
884 tty.main.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
86a5659e 885#else /* not VMS (BSD, that is) */
91bac16a 886 tty.main.sg_flags &= ~(ECHO | CRMOD | XTABS);
86a5659e 887 if (meta_key)
91bac16a
JB
888 tty.main.sg_flags |= ANYP;
889 tty.main.sg_flags |= interrupt_input ? RAW : CBREAK;
86a5659e
JB
890#endif /* not VMS (BSD, that is) */
891#endif /* not HAVE_TERMIO */
892
91bac16a
JB
893 /* If going to use CBREAK mode, we must request C-g to interrupt
894 and turn off start and stop chars, etc. If not going to use
895 CBREAK mode, do this anyway so as to turn off local flow
896 control for user coming over network on 4.2; in this case,
897 only t_stopc and t_startc really matter. */
898#ifndef HAVE_TERMIO
899#ifdef TIOCGETC
900 /* Note: if not using CBREAK mode, it makes no difference how we
901 set this */
902 tty.tchars = new_tchars;
903 tty.tchars.t_intrc = quit_char;
904 if (flow_control)
905 {
906 tty.tchars.t_startc = '\021';
907 tty.tchars.t_stopc = '\023';
908 }
909
910/* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */
911#ifndef LPASS8
912#define LPASS8 0
86a5659e 913#endif
91bac16a
JB
914
915#ifdef BSD4_1
916#define LNOFLSH 0100000
917#endif
918
919 tty.lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_tty.lmode;
920
921#ifdef BSD4_1
922 lmode = tty.lmode;
923#endif
924
925#endif /* TIOCGETC */
926#endif /* not HAVE_TERMIO */
927
928#ifdef TIOCGLTC
929 tty.ltchars = new_ltchars;
930#endif /* TIOCGLTC */
931
932 EMACS_SET_TTY (input_fd, &tty, 0);
86a5659e
JB
933
934 /* This code added to insure that, if flow-control is not to be used,
0137dbf7 935 we have an unlocked terminal at the start. */
91bac16a 936
86a5659e
JB
937#ifdef TCXONC
938 if (!flow_control) ioctl (0, TCXONC, 1);
939#endif
940#ifndef APOLLO
941#ifdef TIOCSTART
942 if (!flow_control) ioctl (0, TIOCSTART, 0);
943#endif
944#endif
945
946#ifdef AIX
947 hft_init ();
948#ifdef IBMR2AIX
949 {
950 /* IBM's HFT device usually thinks a ^J should be LF/CR. We need it
951 to be only LF. This is the way that is done. */
952 struct termio tty;
953
954 if (ioctl (1, HFTGETID, &tty) != -1)
955 write (1, "\033[20l", 5);
956 }
957#endif
958#endif
959
86a5659e
JB
960#ifdef VMS
961/* Appears to do nothing when in PASTHRU mode.
91bac16a 962 SYS$QIOW (0, input_fd, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
86a5659e
JB
963 interrupt_signal, oob_chars, 0, 0, 0, 0);
964*/
965 queue_kbd_input (0);
966#endif /* VMS */
967 }
968
969#ifdef F_SETFL
970#ifdef F_GETOWN /* F_SETFL does not imply existance of F_GETOWN */
971 if (interrupt_input)
972 {
973 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
974 fcntl (0, F_SETOWN, getpid ());
975 init_sigio ();
976 }
977#endif /* F_GETOWN */
978#endif /* F_SETFL */
979
980#ifdef BSD4_1
981 if (interrupt_input)
982 init_sigio ();
983#endif
984
985#ifdef VMS /* VMS sometimes has this symbol but lacks setvbuf. */
986#undef _IOFBF
987#endif
988#ifdef _IOFBF
989 /* This symbol is defined on recent USG systems.
990 Someone says without this call USG won't really buffer the file
991 even with a call to setbuf. */
992 setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf);
993#else
994 setbuf (stdout, _sobuf);
995#endif
996 set_terminal_modes ();
997 if (term_initted && no_redraw_on_reenter)
998 {
999 if (display_completed)
1000 direct_output_forward_char (0);
1001 }
1002 else
1003 {
0137dbf7
JB
1004 frame_garbaged = 1;
1005#ifdef MULTI_FRAME
1006 if (FRAMEP (Vterminal_frame))
1007 FRAME_GARBAGED_P (XFRAME (Vterminal_frame)) = 1;
86a5659e
JB
1008#endif
1009 }
91bac16a 1010
86a5659e
JB
1011 term_initted = 1;
1012}
1013
1014/* Return nonzero if safe to use tabs in output.
1015 At the time this is called, init_sys_modes has not been done yet. */
1016
1017tabs_safe_p ()
1018{
91bac16a
JB
1019 struct emacs_tty tty;
1020
1021 EMACS_GET_TTY (input_fd, &tty);
1022 return EMACS_TTY_TABS_OK (&tty);
86a5659e
JB
1023}
1024
1025/* Get terminal size from system.
1026 Store number of lines into *heightp and width into *widthp.
1027 If zero or a negative number is stored, the value is not valid. */
1028
0137dbf7 1029get_frame_size (widthp, heightp)
86a5659e
JB
1030 int *widthp, *heightp;
1031{
86a5659e 1032
86a5659e 1033#ifdef TIOCGWINSZ
91bac16a
JB
1034
1035 /* BSD-style. */
86a5659e 1036 struct winsize size;
91bac16a
JB
1037
1038 if (ioctl (input_fd, TIOCGWINSZ, &size) == -1)
1039 *widthp = *heightp = 0;
1040 else
1041 {
1042 *widthp = size.ws_col;
1043 *heightp = size.ws_row;
1044 }
1045
1046#else
1047#ifdef TIOCGSIZE
1048
1049 /* SunOS - style. */
1050 struct ttysize size;
1051
1052 if (ioctl (input_fd, TIOCGSIZE, &size) == -1)
1053 *widthp = *heightp = 0;
1054 else
1055 {
1056 *widthp = size.ts_cols;
1057 *heightp = size.ts_lines;
1058 }
1059
1060#else
86a5659e 1061#ifdef VMS
91bac16a
JB
1062
1063 struct sensemode tty;
1064
1065 SYS$QIOW (0, input_fd, IO$_SENSEMODE, &tty, 0, 0,
86a5659e
JB
1066 &tty.class, 12, 0, 0, 0, 0);
1067 *widthp = tty.scr_wid;
1068 *heightp = tty.scr_len;
91bac16a 1069
86a5659e 1070#else /* system doesn't know size */
91bac16a 1071
86a5659e
JB
1072 *widthp = 0;
1073 *heightp = 0;
91bac16a
JB
1074
1075#endif /* not VMS */
1076#endif /* not SunOS-style */
1077#endif /* not BSD-style */
86a5659e 1078}
91bac16a 1079
86a5659e 1080\f
91bac16a 1081/* Prepare the terminal for exiting Emacs; move the cursor to the
0137dbf7 1082 bottom of the frame, turn off interrupt-driven I/O, etc. */
86a5659e
JB
1083reset_sys_modes ()
1084{
1085 if (noninteractive)
1086 {
1087 fflush (stdout);
1088 return;
1089 }
1090 if (!term_initted)
1091 return;
1092 if (read_socket_hook || !EQ (Vwindow_system, Qnil))
1093 return;
0137dbf7
JB
1094 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
1095 clear_end_of_line (FRAME_WIDTH (selected_frame));
86a5659e 1096 /* clear_end_of_line may move the cursor */
0137dbf7 1097 cursor_to (FRAME_HEIGHT (selected_frame) - 1, 0);
86a5659e
JB
1098#ifdef IBMR2AIX
1099 {
1100 /* HFT devices normally use ^J as a LF/CR. We forced it to
1101 do the LF only. Now, we need to reset it. */
1102 struct termio tty;
1103
1104 if (ioctl (1, HFTGETID, &tty) != -1)
1105 write (1, "\033[20h", 5);
1106 }
1107#endif
1108
1109 reset_terminal_modes ();
1110 fflush (stdout);
1111#ifdef BSD
1112#ifndef BSD4_1
1113 /* Avoid possible loss of output when changing terminal modes. */
1114 fsync (fileno (stdout));
1115#endif
1116#endif
91bac16a 1117
86a5659e
JB
1118#ifdef F_SETFL
1119#ifdef F_SETOWN /* F_SETFL does not imply existance of F_SETOWN */
1120 if (interrupt_input)
1121 {
1122 reset_sigio ();
1123 fcntl (0, F_SETOWN, old_fcntl_owner);
1124 }
1125#endif /* F_SETOWN */
1126#endif /* F_SETFL */
1127#ifdef BSD4_1
1128 if (interrupt_input)
1129 reset_sigio ();
1130#endif /* BSD4_1 */
91bac16a
JB
1131
1132 while (EMACS_SET_TTY (input_fd, &old_tty, 0) < 0 && errno == EINTR)
1133 ;
86a5659e
JB
1134
1135#ifdef AIX
1136 hft_reset ();
1137#endif
1138}
1139\f
1140#ifdef HAVE_PTYS
1141
1142/* Set up the proper status flags for use of a pty. */
1143
1144setup_pty (fd)
1145 int fd;
1146{
1147 /* I'm told that TOICREMOTE does not mean control chars
1148 "can't be sent" but rather that they don't have
1149 input-editing or signaling effects.
1150 That should be good, because we have other ways
1151 to do those things in Emacs.
1152 However, telnet mode seems not to work on 4.2.
1153 So TIOCREMOTE is turned off now. */
1154
1155 /* Under hp-ux, if TIOCREMOTE is turned on, some calls
1156 will hang. In particular, the "timeout" feature (which
1157 causes a read to return if there is no data available)
1158 does this. Also it is known that telnet mode will hang
1159 in such a way that Emacs must be stopped (perhaps this
1160 is the same problem).
1161
1162 If TIOCREMOTE is turned off, then there is a bug in
1163 hp-ux which sometimes loses data. Apparently the
1164 code which blocks the master process when the internal
1165 buffer fills up does not work. Other than this,
1166 though, everything else seems to work fine.
1167
1168 Since the latter lossage is more benign, we may as well
1169 lose that way. -- cph */
1170#ifdef FIONBIO
1171#ifdef SYSV_PTYS
1172 {
1173 int on = 1;
1174 ioctl (fd, FIONBIO, &on);
1175 }
1176#endif
1177#endif
1178#ifdef IBMRTAIX
1179 /* On AIX, the parent gets SIGHUP when a pty attached child dies. So, we */
1180 /* ignore SIGHUP once we've started a child on a pty. Note that this may */
1181 /* cause EMACS not to die when it should, i.e., when its own controlling */
1182 /* tty goes away. I've complained to the AIX developers, and they may */
1183 /* change this behavior, but I'm not going to hold my breath. */
1184 signal (SIGHUP, SIG_IGN);
1185#endif
1186}
1187#endif /* HAVE_PTYS */
1188\f
1189#ifdef VMS
1190
1191/* Assigning an input channel is done at the start of Emacs execution.
1192 This is called each time Emacs is resumed, also, but does nothing
1193 because input_chain is no longer zero. */
1194
1195init_vms_input ()
1196{
1197 int status;
1198
91bac16a 1199 if (input_fd == 0)
86a5659e 1200 {
91bac16a 1201 status = SYS$ASSIGN (&input_dsc, &input_fd, 0, 0);
86a5659e
JB
1202 if (! (status & 1))
1203 LIB$STOP (status);
1204 }
1205}
1206
1207/* Deassigning the input channel is done before exiting. */
1208
1209stop_vms_input ()
1210{
91bac16a 1211 return SYS$DASSGN (input_fd);
86a5659e
JB
1212}
1213
1214short input_buffer;
1215
1216/* Request reading one character into the keyboard buffer.
1217 This is done as soon as the buffer becomes empty. */
1218
1219queue_kbd_input ()
1220{
1221 int status;
1222 waiting_for_ast = 0;
1223 stop_input = 0;
91bac16a 1224 status = SYS$QIO (0, input_fd, IO$_READVBLK,
86a5659e
JB
1225 &input_iosb, kbd_input_ast, 1,
1226 &input_buffer, 1, 0, terminator_mask, 0, 0);
1227}
1228
1229int input_count;
1230
1231/* Ast routine that is called when keyboard input comes in
1232 in accord with the SYS$QIO above. */
1233
1234kbd_input_ast ()
1235{
1236 register int c = -1;
1237 int old_errno = errno;
ffd56f97 1238 extern EMACS_TIME *input_available_clear_time;
86a5659e
JB
1239
1240 if (waiting_for_ast)
1241 SYS$SETEF (input_ef);
1242 waiting_for_ast = 0;
1243 input_count++;
1244#ifdef ASTDEBUG
1245 if (input_count == 25)
1246 exit (1);
1247 printf ("Ast # %d,", input_count);
1248 printf (" iosb = %x, %x, %x, %x",
1249 input_iosb.offset, input_iosb.status, input_iosb.termlen,
1250 input_iosb.term);
1251#endif
1252 if (input_iosb.offset)
1253 {
1254 c = input_buffer;
1255#ifdef ASTDEBUG
1256 printf (", char = 0%o", c);
1257#endif
1258 }
1259#ifdef ASTDEBUG
1260 printf ("\n");
1261 fflush (stdout);
1262 sleep (1);
1263#endif
1264 if (! stop_input)
1265 queue_kbd_input ();
1266 if (c >= 0)
1267 {
1268 struct input_event e;
1269 e.kind = ascii_keystroke;
1270 XSET (buf[i].code, Lisp_Int, cbuf[i]);
0137dbf7 1271 e.frame = selected_frame;
86a5659e
JB
1272 kbd_buffer_store_event (&e);
1273 }
1274
ffd56f97
JB
1275 if (input_available_clear_time)
1276 EMACS_SET_SECS_USECS (*input_available_clear_time, 0, 0);
86a5659e
JB
1277 errno = old_errno;
1278}
1279
1280/* Wait until there is something in kbd_buffer. */
1281
1282wait_for_kbd_input ()
1283{
1284 extern int have_process_input, process_exited;
1285
1286 /* If already something, avoid doing system calls. */
1287 if (detect_input_pending ())
1288 {
1289 return;
1290 }
1291 /* Clear a flag, and tell ast routine above to set it. */
1292 SYS$CLREF (input_ef);
1293 waiting_for_ast = 1;
1294 /* Check for timing error: ast happened while we were doing that. */
1295 if (!detect_input_pending ())
1296 {
1297 /* No timing error: wait for flag to be set. */
1298 set_waiting_for_input (0);
1299 SYS$WFLOR (input_ef, input_eflist);
1300 clear_waiting_for_input (0);
1301 if (!detect_input_pending ())
1302 /* Check for subprocess input availability */
1303 {
1304 int dsp = have_process_input || process_exited;
1305
1306 SYS$CLREF (process_ef);
1307 if (have_process_input)
1308 process_command_input ();
1309 if (process_exited)
1310 process_exit ();
1311 if (dsp)
1312 {
1313 update_mode_lines++;
1314 redisplay_preserve_echo_area ();
1315 }
1316 }
1317 }
1318 waiting_for_ast = 0;
1319}
1320
1321/* Get rid of any pending QIO, when we are about to suspend
1322 or when we want to throw away pending input.
1323 We wait for a positive sign that the AST routine has run
1324 and therefore there is no I/O request queued when we return.
1325 SYS$SETAST is used to avoid a timing error. */
1326
1327end_kbd_input ()
1328{
1329#ifdef ASTDEBUG
1330 printf ("At end_kbd_input.\n");
1331 fflush (stdout);
1332 sleep (1);
1333#endif
1334 if (LIB$AST_IN_PROG ()) /* Don't wait if suspending from kbd_buffer_store_event! */
1335 {
91bac16a 1336 SYS$CANCEL (input_fd);
86a5659e
JB
1337 return;
1338 }
1339
1340 SYS$SETAST (0);
1341 /* Clear a flag, and tell ast routine above to set it. */
1342 SYS$CLREF (input_ef);
1343 waiting_for_ast = 1;
1344 stop_input = 1;
91bac16a 1345 SYS$CANCEL (input_fd);
86a5659e
JB
1346 SYS$SETAST (1);
1347 SYS$WAITFR (input_ef);
1348 waiting_for_ast = 0;
1349}
1350
1351/* Wait for either input available or time interval expiry. */
1352
1353input_wait_timeout (timeval)
1354 int timeval; /* Time to wait, in seconds */
1355{
1356 int time [2];
1357 static int zero = 0;
1358 static int large = -10000000;
1359
1360 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
1361
1362 /* If already something, avoid doing system calls. */
1363 if (detect_input_pending ())
1364 {
1365 return;
1366 }
1367 /* Clear a flag, and tell ast routine above to set it. */
1368 SYS$CLREF (input_ef);
1369 waiting_for_ast = 1;
1370 /* Check for timing error: ast happened while we were doing that. */
1371 if (!detect_input_pending ())
1372 {
1373 /* No timing error: wait for flag to be set. */
1374 SYS$CANTIM (1, 0);
1375 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1376 SYS$WFLOR (timer_ef, timer_eflist); /* Wait for timer expiry or input */
1377 }
1378 waiting_for_ast = 0;
1379}
1380
1381/* The standard `sleep' routine works some other way
1382 and it stops working if you have ever quit out of it.
1383 This one continues to work. */
1384
1385sys_sleep (timeval)
1386 int timeval;
1387{
1388 int time [2];
1389 static int zero = 0;
1390 static int large = -10000000;
1391
1392 LIB$EMUL (&timeval, &large, &zero, time); /* Convert to VMS format */
1393
1394 SYS$CANTIM (1, 0);
1395 if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
1396 SYS$WAITFR (timer_ef); /* Wait for timer expiry only */
1397}
1398
1399init_sigio ()
1400{
1401 request_sigio ();
1402}
1403
1404reset_sigio ()
1405{
1406 unrequest_sigio ();
1407}
1408
1409request_sigio ()
1410{
1411 croak ("request sigio");
1412}
1413
1414unrequest_sigio ()
1415{
1416 croak ("unrequest sigio");
1417}
1418
1419#endif /* VMS */
1420\f
1421/* Note that VMS compiler won't accept defined (CANNOT_DUMP). */
1422#ifndef CANNOT_DUMP
1423#define NEED_STARTS
1424#endif
1425
1426#ifndef SYSTEM_MALLOC
1427#ifndef NEED_STARTS
1428#define NEED_STARTS
1429#endif
1430#endif
1431
1432#ifdef NEED_STARTS
1433/* Some systems that cannot dump also cannot implement these. */
1434
1435/*
1436 * Return the address of the start of the text segment prior to
1437 * doing an unexec. After unexec the return value is undefined.
1438 * See crt0.c for further explanation and _start.
1439 *
1440 */
1441
1442#ifndef CANNOT_UNEXEC
1443char *
1444start_of_text ()
1445{
1446#ifdef TEXT_START
1447 return ((char *) TEXT_START);
1448#else
1449#ifdef GOULD
1450 extern csrt ();
1451 return ((char *) csrt);
1452#else /* not GOULD */
1453 extern int _start ();
1454 return ((char *) _start);
1455#endif /* GOULD */
1456#endif /* TEXT_START */
1457}
1458#endif /* not CANNOT_UNEXEC */
1459
1460/*
1461 * Return the address of the start of the data segment prior to
1462 * doing an unexec. After unexec the return value is undefined.
1463 * See crt0.c for further information and definition of data_start.
1464 *
1465 * Apparently, on BSD systems this is etext at startup. On
1466 * USG systems (swapping) this is highly mmu dependent and
1467 * is also dependent on whether or not the program is running
1468 * with shared text. Generally there is a (possibly large)
1469 * gap between end of text and start of data with shared text.
1470 *
1471 * On Uniplus+ systems with shared text, data starts at a
1472 * fixed address. Each port (from a given oem) is generally
1473 * different, and the specific value of the start of data can
1474 * be obtained via the UniPlus+ specific "uvar" system call,
1475 * however the method outlined in crt0.c seems to be more portable.
1476 *
1477 * Probably what will have to happen when a USG unexec is available,
1478 * at least on UniPlus, is temacs will have to be made unshared so
1479 * that text and data are contiguous. Then once loadup is complete,
1480 * unexec will produce a shared executable where the data can be
1481 * at the normal shared text boundry and the startofdata variable
1482 * will be patched by unexec to the correct value.
1483 *
1484 */
1485
1486char *
1487start_of_data ()
1488{
1489#ifdef DATA_START
1490 return ((char *) DATA_START);
1491#else
1492 extern int data_start;
1493 return ((char *) &data_start);
1494#endif
1495}
1496#endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
1497
1498#ifndef CANNOT_DUMP
1499/* Some systems that cannot dump also cannot implement these. */
1500
1501/*
1502 * Return the address of the end of the text segment prior to
1503 * doing an unexec. After unexec the return value is undefined.
1504 */
1505
1506char *
1507end_of_text ()
1508{
1509#ifdef TEXT_END
1510 return ((char *) TEXT_END);
1511#else
1512 extern int etext;
1513 return ((char *) &etext);
1514#endif
1515}
1516
1517/*
1518 * Return the address of the end of the data segment prior to
1519 * doing an unexec. After unexec the return value is undefined.
1520 */
1521
1522char *
1523end_of_data ()
1524{
1525#ifdef DATA_END
1526 return ((char *) DATA_END);
1527#else
1528 extern int edata;
1529 return ((char *) &edata);
1530#endif
1531}
1532
1533#endif /* not CANNOT_DUMP */
1534\f
1535/* Get_system_name returns as its value
1536 a string for the Lisp function system-name to return. */
1537
1538#ifdef BSD4_1
1539#include <whoami.h>
1540#endif
1541
1542#ifdef USG
1543/* Can't have this within the function since `static' is #defined to nothing */
1544static struct utsname get_system_name_name;
1545#endif
1546
1547char *
1548get_system_name ()
1549{
1550#ifdef USG
1551 uname (&get_system_name_name);
1552 return (get_system_name_name.nodename);
1553#else /* Not USG */
1554#ifdef BSD4_1
1555 return sysname;
1556#else /* not USG, not 4.1 */
1557 static char system_name_saved[32];
1558#ifdef VMS
1559 char *sp;
1560 if ((sp = egetenv ("SYS$NODE")) == 0)
1561 sp = "vax-vms";
1562 else
1563 {
1564 char *end;
1565
1566 if ((end = index (sp, ':')) != 0)
1567 *end = '\0';
1568 }
1569 strcpy (system_name_saved, sp);
1570#else /* not VMS */
1571 gethostname (system_name_saved, sizeof (system_name_saved));
1572#endif /* not VMS */
1573 return system_name_saved;
1574#endif /* not USG, not 4.1 */
1575#endif /* not USG */
1576}
1577\f
1578#ifndef VMS
1579#ifndef HAVE_SELECT
1580
1581#ifdef HAVE_X_WINDOWS
1582/* Cause explanatory error message at compile time,
1583 since the select emulation is not good enough for X. */
1584int *x = &x_windows_lose_if_no_select_system_call;
1585#endif
1586
1587/* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
1588 * Only checks read descriptors.
1589 */
1590/* How long to wait between checking fds in select */
1591#define SELECT_PAUSE 1
1592int select_alarmed;
1593
1594/* For longjmp'ing back to read_input_waiting. */
1595
1596jmp_buf read_alarm_throw;
1597
1598/* Nonzero if the alarm signal should throw back to read_input_waiting.
1599 The read_socket_hook function sets this to 1 while it is waiting. */
1600
1601int read_alarm_should_throw;
1602
1603SIGTYPE
1604select_alarm ()
1605{
1606 select_alarmed = 1;
1607#ifdef BSD4_1
1608 sigrelse (SIGALRM);
1609#else /* not BSD4_1 */
1610 signal (SIGALRM, SIG_IGN);
1611#endif /* not BSD4_1 */
1612 if (read_alarm_should_throw)
1613 longjmp (read_alarm_throw, 1);
1614}
1615
1616/* Only rfds are checked. */
1617int
1618select (nfds, rfds, wfds, efds, timeout)
1619 int nfds;
1620 int *rfds, *wfds, *efds, *timeout;
1621{
1622 int ravail = 0, orfds = 0, old_alarm;
1623 int timeoutval = timeout ? *timeout : 100000;
1624 int *local_timeout = &timeoutval;
1625 extern int proc_buffered_char[];
1626#ifndef subprocesses
1627 int process_tick = 0, update_tick = 0;
1628#else
1629 extern int process_tick, update_tick;
1630#endif
1631 SIGTYPE (*old_trap) ();
1632 unsigned char buf;
1633
1634 if (rfds)
1635 {
1636 orfds = *rfds;
1637 *rfds = 0;
1638 }
1639 if (wfds)
1640 *wfds = 0;
1641 if (efds)
1642 *efds = 0;
1643
1644 /* If we are looking only for the terminal, with no timeout,
1645 just read it and wait -- that's more efficient. */
1646 if (orfds == 1 && *local_timeout == 100000 && process_tick == update_tick)
1647 {
1648 if (! detect_input_pending ())
1649 read_input_waiting ();
1650 *rfds = 1;
1651 return 1;
1652 }
1653
1654 /* Once a second, till the timer expires, check all the flagged read
1655 * descriptors to see if any input is available. If there is some then
1656 * set the corresponding bit in the return copy of rfds.
1657 */
1658 while (1)
1659 {
1660 register int to_check, bit, fd;
1661
1662 if (rfds)
1663 {
1664 for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
1665 {
1666 if (orfds & bit)
1667 {
1668 int avail = 0, status = 0;
1669
1670 if (bit == 1)
1671 avail = detect_input_pending (); /* Special keyboard handler */
1672 else
1673 {
1674#ifdef FIONREAD
1675 status = ioctl (fd, FIONREAD, &avail);
1676#else /* no FIONREAD */
1677 /* Hoping it will return -1 if nothing available
1678 or 0 if all 0 chars requested are read. */
1679 if (proc_buffered_char[fd] >= 0)
1680 avail = 1;
1681 else
1682 {
1683 avail = read (fd, &buf, 1);
1684 if (avail > 0)
1685 proc_buffered_char[fd] = buf;
1686 }
1687#endif /* no FIONREAD */
1688 }
1689 if (status >= 0 && avail > 0)
1690 {
1691 (*rfds) |= bit;
1692 ravail++;
1693 }
1694 }
1695 }
1696 }
1697 if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
1698 break;
1699 old_alarm = alarm (0);
34567704 1700 old_trap = signal (SIGALRM, select_alarm);
86a5659e
JB
1701 select_alarmed = 0;
1702 alarm (SELECT_PAUSE);
1703 /* Wait for a SIGALRM (or maybe a SIGTINT) */
1704 while (select_alarmed == 0 && *local_timeout != 0
1705 && process_tick == update_tick)
1706 {
1707 /* If we are interested in terminal input,
1708 wait by reading the terminal.
1709 That makes instant wakeup for terminal input at least. */
1710 if (orfds & 1)
1711 {
1712 read_input_waiting ();
1713 if (detect_input_pending ())
1714 select_alarmed = 1;
1715 }
1716 else
1717 pause ();
1718 }
1719 (*local_timeout) -= SELECT_PAUSE;
1720 /* Reset the old alarm if there was one */
1721 alarm (0);
1722 signal (SIGALRM, old_trap);
1723 if (old_alarm != 0)
1724 {
1725 /* Reset or forge an interrupt for the original handler. */
1726 old_alarm -= SELECT_PAUSE;
1727 if (old_alarm <= 0)
1728 kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
1729 else
1730 alarm (old_alarm);
1731 }
1732 if (*local_timeout == 0) /* Stop on timer being cleared */
1733 break;
1734 }
1735 return ravail;
1736}
1737
1738/* Read keyboard input into the standard buffer,
1739 waiting for at least one character. */
1740
1741/* Make all keyboard buffers much bigger when using X windows. */
1742#ifdef HAVE_X_WINDOWS
1743#define BUFFER_SIZE_FACTOR 16
1744#else
1745#define BUFFER_SIZE_FACTOR 1
1746#endif
1747
1748read_input_waiting ()
1749{
1750 char buf[256 * BUFFER_SIZE_FACTOR];
1751 struct input_event e;
34567704
JB
1752 int nread, i;
1753 extern int quit_char;
86a5659e
JB
1754
1755 if (read_socket_hook)
1756 {
1757 read_alarm_should_throw = 0;
1758 if (! setjmp (read_alarm_throw))
1759 nread = (*read_socket_hook) (0, buf, 256 * BUFFER_SIZE_FACTOR, 1, 0);
1760 else
1761 nread = -1;
1762 }
1763 else
1764 nread = read (fileno (stdin), buf, 1);
1765
1766 /* Scan the chars for C-g and store them in kbd_buffer. */
1767 e.kind = ascii_keystroke;
0137dbf7 1768 e.frame = selected_frame;
86a5659e
JB
1769 for (i = 0; i < nread; i++)
1770 {
1771 XSET (e.code, Lisp_Int, buf[i]);
1772 kbd_buffer_store_event (&e);
1773 /* Don't look at input that follows a C-g too closely.
1774 This reduces lossage due to autorepeat on C-g. */
34567704 1775 if (buf[i] == quit_char)
86a5659e
JB
1776 break;
1777 }
1778}
1779
1780#endif /* not HAVE_SELECT */
1781#endif /* not VMS */
1782\f
1783#ifdef BSD4_1
86a5659e
JB
1784/*
1785 * Partially emulate 4.2 open call.
1786 * open is defined as this in 4.1.
1787 *
1788 * - added by Michael Bloom @ Citicorp/TTI
1789 *
1790 */
1791
1792int
1793sys_open (path, oflag, mode)
1794 char *path;
1795 int oflag, mode;
1796{
1797 if (oflag & O_CREAT)
1798 return creat (path, mode);
1799 else
1800 return open (path, oflag);
1801}
1802
1803init_sigio ()
1804{
1805 if (noninteractive)
1806 return;
1807 lmode = LINTRUP | lmode;
1808 ioctl (0, TIOCLSET, &lmode);
1809}
1810
1811reset_sigio ()
1812{
1813 if (noninteractive)
1814 return;
1815 lmode = ~LINTRUP & lmode;
1816 ioctl (0, TIOCLSET, &lmode);
1817}
1818
1819request_sigio ()
1820{
1821 sigrelse (SIGTINT);
1822
1823 interrupts_deferred = 0;
1824}
1825
1826unrequest_sigio ()
1827{
1828 sighold (SIGTINT);
1829
1830 interrupts_deferred = 1;
1831}
1832
1833/* still inside #ifdef BSD4_1 */
1834#ifdef subprocesses
1835
1836int sigheld; /* Mask of held signals */
1837
1838sigholdx (signum)
1839 int signum;
1840{
1841 sigheld |= sigbit (signum);
1842 sighold (signum);
1843}
1844
1845sigisheld (signum)
1846 int signum;
1847{
1848 sigheld |= sigbit (signum);
1849}
1850
1851sigunhold (signum)
1852 int signum;
1853{
1854 sigheld &= ~sigbit (signum);
1855 sigrelse (signum);
1856}
1857
1858sigfree () /* Free all held signals */
1859{
1860 int i;
1861 for (i = 0; i < NSIG; i++)
1862 if (sigheld & sigbit (i))
1863 sigrelse (i);
1864 sigheld = 0;
1865}
1866
1867sigbit (i)
1868{
1869 return 1 << (i - 1);
1870}
1871#endif /* subprocesses */
1872#endif /* BSD4_1 */
1873\f
1874/* POSIX signals support - DJB */
1875/* Anyone with POSIX signals should have ANSI C declarations */
1876
1877#ifdef POSIX_SIGNALS
1878
1879sigset_t old_mask, empty_mask, full_mask, temp_mask;
1880static struct sigaction new_action, old_action;
1881
1882init_signals ()
1883{
1884#ifdef POSIX_SIGNALS
1885 sigemptyset (&signal_empty_mask);
1886 sigfillset (&signal_full_mask);
1887#endif
1888}
1889
1890int (*signal_handler_t) ();
1891
1892signal_handler_t
1893sys_signal (int signal_number, signal_handler_t action)
1894{
1895#ifdef DGUX
1896 /* This gets us restartable system calls for efficiency.
1897 The "else" code will works as well. */
1898 return (berk_signal (signal_number, action));
1899#else
1900 sigemptyset (&new_action.sa_mask);
1901 new_action.sa_handler = action;
1902 new_action.sa_flags = NULL;
d32b2f3c 1903 sigaction (signal_number, &new_action, &old_action);
86a5659e
JB
1904 return (old_action.sa_handler);
1905#endif /* DGUX */
1906}
1907
e065a56e
JB
1908#ifndef __GNUC__
1909/* If we're compiling with GCC, we don't need this function, since it
1910 can be written as a macro. */
1911sigset_t
1912sys_sigmask (int sig)
1913{
1914 sigset_t mask;
1915 sigemptyset (&mask);
1916 sigaddset (&mask, sig);
1917 return mask;
1918}
1919#endif
1920
86a5659e
JB
1921int
1922sys_sigpause (sigset_t new_mask)
1923{
1924 /* pause emulating berk sigpause... */
1925 sigsuspend (&new_mask);
1926 return (EINTR);
1927}
1928
1929/* I'd like to have these guys return pointers to the mask storage in here,
1930 but there'd be trouble if the code was saving multiple masks. I'll be
1931 safe and pass the structure. It normally won't be more than 2 bytes
1932 anyhow. - DJB */
1933
1934sigset_t
1935sys_sigblock (sigset_t new_mask)
1936{
1937 sigset_t old_mask;
1938 sigprocmask (SIG_BLOCK, &new_mask, &old_mask);
1939 return (old_mask);
1940}
1941
1942sigset_t
1943sys_sigunblock (sigset_t new_mask)
1944{
1945 sigset_t old_mask;
1946 sigprocmask (SIG_UNBLOCK, &new_mask, &old_mask);
1947 return (old_mask);
1948}
1949
1950sigset_t
1951sys_sigsetmask (sigset_t new_mask)
1952{
1953 sigset_t old_mask;
1954 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
1955 return (old_mask);
1956}
1957
1958#endif /* POSIX_SIGNALS */
1959\f
1960#ifndef BSTRING
1961
1962void
1963bzero (b, length)
1964 register char *b;
1965 register int length;
1966{
1967#ifdef VMS
1968 short zero = 0;
1969 long max_str = 65535;
1970
1971 while (length > max_str) {
1972 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
1973 length -= max_str;
1974 b += max_str;
1975 }
1976 max_str = length;
1977 (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
1978#else
1979 while (length-- > 0)
1980 *b++ = 0;
1981#endif /* not VMS */
1982}
1983
1984/* Saying `void' requires a declaration, above, where bcopy is used
1985 and that declaration causes pain for systems where bcopy is a macro. */
1986bcopy (b1, b2, length)
1987 register char *b1;
1988 register char *b2;
1989 register int length;
1990{
1991#ifdef VMS
1992 long max_str = 65535;
1993
1994 while (length > max_str) {
1995 (void) LIB$MOVC3 (&max_str, b1, b2);
1996 length -= max_str;
1997 b1 += max_str;
1998 b2 += max_str;
1999 }
2000 max_str = length;
2001 (void) LIB$MOVC3 (&length, b1, b2);
2002#else
2003 while (length-- > 0)
2004 *b2++ = *b1++;
2005#endif /* not VMS */
2006}
2007
2008int
2009bcmp (b1, b2, length) /* This could be a macro! */
2010 register char *b1;
2011 register char *b2;
2012 register int length;
2013{
2014#ifdef VMS
2015 struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
2016 struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
2017
2018 return STR$COMPARE (&src1, &src2);
2019#else
2020 while (length-- > 0)
2021 if (*b1++ != *b2++)
2022 return 1;
2023
2024 return 0;
2025#endif /* not VMS */
2026}
2027#endif /* not BSTRING */
2028\f
2029#ifdef USG
2030/*
2031 * The BSD random returns numbers in the range of
2032 * 0 to 2e31 - 1. The USG rand returns numbers in the
2033 * range of 0 to 2e15 - 1. This is probably not significant
2034 * in this usage.
2035 */
2036
2037long
2038random ()
2039{
2040 /* Arrange to return a range centered on zero. */
2041 return (rand () << 15) + rand () - (1 << 29);
2042}
2043
2044srandom (arg)
2045 int arg;
2046{
2047 srand (arg);
2048}
2049
2050#endif /* USG */
2051
2052#ifdef BSD4_1
2053long random ()
2054{
2055 /* Arrange to return a range centered on zero. */
2056 return (rand () << 15) + rand () - (1 << 29);
2057}
2058
2059srandom (arg)
2060 int arg;
2061{
2062 srand (arg);
2063}
2064#endif /* BSD4_1 */
2065\f
2066#ifdef WRONG_NAME_INSQUE
2067
2068insque (q,p)
2069 caddr_t q,p;
2070{
2071 _insque (q,p);
2072}
2073
2074#endif
2075\f
2076#ifdef VMS
2077
2078#ifdef getenv
2079/* If any place else asks for the TERM variable,
2080 allow it to be overridden with the EMACS_TERM variable
2081 before attempting to translate the logical name TERM. As a last
2082 resort, ask for VAX C's special idea of the TERM variable. */
2083#undef getenv
2084char *
2085sys_getenv (name)
2086 char *name;
2087{
2088 register char *val;
2089 static char buf[256];
2090 static struct dsc$descriptor_s equiv
2091 = {sizeof (buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
2092 static struct dsc$descriptor_s d_name
2093 = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
2094 short eqlen;
2095
2096 if (!strcmp (name, "TERM"))
2097 {
2098 val = (char *) getenv ("EMACS_TERM");
2099 if (val)
2100 return val;
2101 }
2102
2103 d_name.dsc$w_length = strlen (name);
2104 d_name.dsc$a_pointer = name;
2105 if (lib$sys_trnlog (&d_name, &eqlen, &equiv) == 1)
2106 {
2107 char *str = (char *) xmalloc (eqlen + 1);
2108 bcopy (buf, str, eqlen);
2109 str[eqlen] = '\0';
2110 /* This is a storage leak, but a pain to fix. With luck,
2111 no one will ever notice. */
2112 return str;
2113 }
2114 return (char *) getenv (name);
2115}
2116#endif /* getenv */
2117
2118#ifdef abort
2119/* Since VMS doesn't believe in core dumps, the only way to debug this beast is
2120 to force a call on the debugger from within the image. */
2121#undef abort
2122sys_abort ()
2123{
2124 reset_sys_modes ();
2125 LIB$SIGNAL (SS$_DEBUG);
2126}
2127#endif /* abort */
2128#endif /* VMS */
2129\f
2130#ifdef VMS
2131#ifdef LINK_CRTL_SHARE
2132#ifdef SHAREABLE_LIB_BUG
2133/* Variables declared noshare and initialized in shareable libraries
2134 cannot be shared. The VMS linker incorrectly forces you to use a private
2135 version which is uninitialized... If not for this "feature", we
2136 could use the C library definition of sys_nerr and sys_errlist. */
2137int sys_nerr = 35;
2138char *sys_errlist[] =
2139 {
2140 "error 0",
2141 "not owner",
2142 "no such file or directory",
2143 "no such process",
2144 "interrupted system call",
2145 "i/o error",
2146 "no such device or address",
2147 "argument list too long",
2148 "exec format error",
2149 "bad file number",
2150 "no child process",
2151 "no more processes",
2152 "not enough memory",
2153 "permission denied",
2154 "bad address",
2155 "block device required",
2156 "mount devices busy",
2157 "file exists",
2158 "cross-device link",
2159 "no such device",
2160 "not a directory",
2161 "is a directory",
2162 "invalid argument",
2163 "file table overflow",
2164 "too many open files",
2165 "not a typewriter",
2166 "text file busy",
2167 "file too big",
2168 "no space left on device",
2169 "illegal seek",
2170 "read-only file system",
2171 "too many links",
2172 "broken pipe",
2173 "math argument",
2174 "result too large",
2175 "I/O stream empty",
2176 "vax/vms specific error code nontranslatable error"
2177 };
2178#endif /* SHAREABLE_LIB_BUG */
2179#endif /* LINK_CRTL_SHARE */
2180#endif /* VMS */
2181\f
2182#ifdef INTERRUPTIBLE_OPEN
2183
2184int
2185/* VARARGS 2 */
2186sys_open (path, oflag, mode)
2187 char *path;
2188 int oflag, mode;
2189{
2190 register int rtnval;
2191
2192 while ((rtnval = open (path, oflag, mode)) == -1
2193 && (errno == EINTR));
2194 return (rtnval);
2195}
2196
2197#endif /* INTERRUPTIBLE_OPEN */
2198
2199#ifdef INTERRUPTIBLE_CLOSE
2200
2201sys_close (fd)
2202 int fd;
2203{
2204 register int rtnval;
2205
2206 while ((rtnval = close (fd)) == -1
2207 && (errno == EINTR));
2208 return rtnval;
2209}
2210
2211#endif /* INTERRUPTIBLE_CLOSE */
2212
2213#ifdef INTERRUPTIBLE_IO
2214
2215int
2216sys_read (fildes, buf, nbyte)
2217 int fildes;
2218 char *buf;
2219 unsigned int nbyte;
2220{
2221 register int rtnval;
2222
2223 while ((rtnval = read (fildes, buf, nbyte)) == -1
2224 && (errno == EINTR));
2225 return (rtnval);
2226}
2227
2228int
2229sys_write (fildes, buf, nbyte)
2230 int fildes;
2231 char *buf;
2232 unsigned int nbyte;
2233{
2234 register int rtnval;
2235
2236 while ((rtnval = write (fildes, buf, nbyte)) == -1
2237 && (errno == EINTR));
2238 return (rtnval);
2239}
2240
2241#endif /* INTERRUPTIBLE_IO */
2242\f
2243#ifdef USG
2244/*
2245 * All of the following are for USG.
2246 *
2247 * On USG systems the system calls are INTERRUPTIBLE by signals
2248 * that the user program has elected to catch. Thus the system call
2249 * must be retried in these cases. To handle this without massive
2250 * changes in the source code, we remap the standard system call names
2251 * to names for our own functions in sysdep.c that do the system call
2252 * with retries. Actually, for portability reasons, it is good
2253 * programming practice, as this example shows, to limit all actual
2254 * system calls to a single occurance in the source. Sure, this
2255 * adds an extra level of function call overhead but it is almost
2256 * always negligible. Fred Fish, Unisoft Systems Inc.
2257 */
2258
2259char *sys_siglist[NSIG + 1] =
2260{
2261#ifdef AIX
2262/* AIX has changed the signals a bit */
2263 "bogus signal", /* 0 */
2264 "hangup", /* 1 SIGHUP */
2265 "interrupt", /* 2 SIGINT */
2266 "quit", /* 3 SIGQUIT */
2267 "illegal instruction", /* 4 SIGILL */
2268 "trace trap", /* 5 SIGTRAP */
2269 "IOT instruction", /* 6 SIGIOT */
2270 "crash likely", /* 7 SIGDANGER */
2271 "floating point exception", /* 8 SIGFPE */
2272 "kill", /* 9 SIGKILL */
2273 "bus error", /* 10 SIGBUS */
2274 "segmentation violation", /* 11 SIGSEGV */
2275 "bad argument to system call", /* 12 SIGSYS */
2276 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2277 "alarm clock", /* 14 SIGALRM */
2278 "software termination signum", /* 15 SIGTERM */
2279 "user defined signal 1", /* 16 SIGUSR1 */
2280 "user defined signal 2", /* 17 SIGUSR2 */
2281 "death of a child", /* 18 SIGCLD */
2282 "power-fail restart", /* 19 SIGPWR */
2283 "bogus signal", /* 20 */
2284 "bogus signal", /* 21 */
2285 "bogus signal", /* 22 */
2286 "bogus signal", /* 23 */
2287 "bogus signal", /* 24 */
2288 "LAN I/O interrupt", /* 25 SIGAIO */
2289 "PTY I/O interrupt", /* 26 SIGPTY */
2290 "I/O intervention required", /* 27 SIGIOINT */
2291 "HFT grant", /* 28 SIGGRANT */
2292 "HFT retract", /* 29 SIGRETRACT */
2293 "HFT sound done", /* 30 SIGSOUND */
2294 "HFT input ready", /* 31 SIGMSG */
2295#else /* not AIX */
2296 "bogus signal", /* 0 */
2297 "hangup", /* 1 SIGHUP */
2298 "interrupt", /* 2 SIGINT */
2299 "quit", /* 3 SIGQUIT */
2300 "illegal instruction", /* 4 SIGILL */
2301 "trace trap", /* 5 SIGTRAP */
2302 "IOT instruction", /* 6 SIGIOT */
2303 "EMT instruction", /* 7 SIGEMT */
2304 "floating point exception", /* 8 SIGFPE */
2305 "kill", /* 9 SIGKILL */
2306 "bus error", /* 10 SIGBUS */
2307 "segmentation violation", /* 11 SIGSEGV */
2308 "bad argument to system call", /* 12 SIGSYS */
2309 "write on a pipe with no one to read it", /* 13 SIGPIPE */
2310 "alarm clock", /* 14 SIGALRM */
2311 "software termination signum", /* 15 SIGTERM */
2312 "user defined signal 1", /* 16 SIGUSR1 */
2313 "user defined signal 2", /* 17 SIGUSR2 */
2314 "death of a child", /* 18 SIGCLD */
2315 "power-fail restart", /* 19 SIGPWR */
2316#endif /* not AIX */
2317 0
2318 };
2319
2320/*
2321 * Warning, this function may not duplicate 4.2 action properly
2322 * under error conditions.
2323 */
2324
2325#ifndef MAXPATHLEN
2326/* In 4.1, param.h fails to define this. */
2327#define MAXPATHLEN 1024
2328#endif
2329
2330#ifndef HAVE_GETWD
2331
2332char *
2333getwd (pathname)
2334 char *pathname;
2335{
2336 char *npath, *spath;
2337 extern char *getcwd ();
2338
2339 spath = npath = getcwd ((char *) 0, MAXPATHLEN);
2340 /* On Altos 3068, getcwd can return @hostname/dir, so discard
2341 up to first slash. Should be harmless on other systems. */
2342 while (*npath && *npath != '/')
2343 npath++;
2344 strcpy (pathname, npath);
2345 free (spath); /* getcwd uses malloc */
2346 return pathname;
2347}
2348
2349#endif /* HAVE_GETWD */
2350
2351/*
2352 * Emulate rename using unlink/link. Note that this is
2353 * only partially correct. Also, doesn't enforce restriction
2354 * that files be of same type (regular->regular, dir->dir, etc).
2355 */
2356
4746118a
JB
2357#ifndef HAVE_RENAME
2358
86a5659e
JB
2359rename (from, to)
2360 char *from;
2361 char *to;
2362{
2363 if (access (from, 0) == 0)
2364 {
2365 unlink (to);
2366 if (link (from, to) == 0)
2367 if (unlink (from) == 0)
2368 return (0);
2369 }
2370 return (-1);
2371}
2372
4746118a
JB
2373#endif
2374
86a5659e
JB
2375#ifndef HAVE_VFORK
2376
2377/*
2378 * Substitute fork for vfork on USG flavors.
2379 */
2380
2381vfork ()
2382{
2383 return (fork ());
2384}
2385
2386#endif /* not HAVE_VFORK */
2387
2388#ifdef MISSING_UTIMES
2389
2390/* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes. */
2391
2392utimes ()
2393{
2394}
2395#endif
2396
2397#ifdef IRIS_UTIME
2398
2399/* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
2400 utimbuf structure defined anywhere but in the man page. */
2401
2402struct utimbuf
2403 {
2404 long actime;
2405 long modtime;
2406 };
2407
2408utimes (name, tvp)
2409 char *name;
2410 struct timeval tvp[];
2411{
2412 struct utimbuf utb;
2413 utb.actime = tvp[0].tv_sec;
2414 utb.modtime = tvp[1].tv_sec;
2415 utime (name, &utb);
2416}
2417#endif /* IRIS_UTIME */
2418
2419
2420#ifdef HPUX
2421#ifndef HAVE_PERROR
2422
2423/* HPUX curses library references perror, but as far as we know
2424 it won't be called. Anyway this definition will do for now. */
2425
2426perror ()
2427{
2428}
2429
2430#endif /* not HAVE_PERROR */
2431#endif /* HPUX */
2432
2433#ifndef HAVE_DUP2
2434
2435/*
2436 * Emulate BSD dup2. First close newd if it already exists.
2437 * Then, attempt to dup oldd. If not successful, call dup2 recursively
2438 * until we are, then close the unsuccessful ones.
2439 */
2440
2441dup2 (oldd, newd)
2442 int oldd;
2443 int newd;
2444{
2445 register int fd, ret;
2446
2447 sys_close (newd);
2448
2449#ifdef F_DUPFD
2450 fd = fcntl (oldd, F_DUPFD, newd);
2451 if (fd != newd)
2452 error ("can't dup2 (%i,%i) : %s", oldd, newd, sys_errlist[errno]);
2453#else
2454 fd = dup (old);
2455 if (fd == -1)
2456 return -1;
2457 if (fd == new)
2458 return new;
2459 ret = dup2 (old,new);
2460 sys_close (fd);
2461 return ret;
2462#endif
2463}
2464
2465#endif /* not HAVE_DUP2 */
2466
2467/*
2468 * Gettimeofday. Simulate as much as possible. Only accurate
2469 * to nearest second. Emacs doesn't use tzp so ignore it for now.
2470 * Only needed when subprocesses are defined.
2471 */
2472
2473#ifdef subprocesses
2474#ifndef VMS
2475#ifndef HAVE_GETTIMEOFDAY
2476#ifdef HAVE_TIMEVAL
2477
2478/* ARGSUSED */
2479gettimeofday (tp, tzp)
2480 struct timeval *tp;
2481 struct timezone *tzp;
2482{
2483 extern long time ();
2484
2485 tp->tv_sec = time ((long *)0);
2486 tp->tv_usec = 0;
2487 tzp->tz_minuteswest = -1;
2488}
2489
2490#endif
2491#endif
2492#endif
2493#endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL && !VMS */
2494
2495/*
2496 * This function will go away as soon as all the stubs fixed. (fnf)
2497 */
2498
2499croak (badfunc)
2500 char *badfunc;
2501{
2502 printf ("%s not yet implemented\r\n", badfunc);
2503 reset_sys_modes ();
2504 exit (1);
2505}
2506
2507#endif /* USG */
2508\f
2509#ifdef DGUX
2510
2511char *sys_siglist[NSIG + 1] =
2512{
2513 "null signal", /* 0 SIGNULL */
2514 "hangup", /* 1 SIGHUP */
2515 "interrupt", /* 2 SIGINT */
2516 "quit", /* 3 SIGQUIT */
2517 "illegal instruction", /* 4 SIGILL */
2518 "trace trap", /* 5 SIGTRAP */
2519 "abort termination", /* 6 SIGABRT */
2520 "SIGEMT", /* 7 SIGEMT */
2521 "floating point exception", /* 8 SIGFPE */
2522 "kill", /* 9 SIGKILL */
2523 "bus error", /* 10 SIGBUS */
2524 "segmentation violation", /* 11 SIGSEGV */
2525 "bad argument to system call", /* 12 SIGSYS */
2526 "write on a pipe with no reader", /* 13 SIGPIPE */
2527 "alarm clock", /* 14 SIGALRM */
2528 "software termination signal", /* 15 SIGTERM */
2529 "user defined signal 1", /* 16 SIGUSR1 */
2530 "user defined signal 2", /* 17 SIGUSR2 */
2531 "child stopped or terminated", /* 18 SIGCLD */
2532 "power-fail restart", /* 19 SIGPWR */
2533 "window size changed", /* 20 SIGWINCH */
2534 "undefined", /* 21 */
2535 "pollable event occured", /* 22 SIGPOLL */
2536 "sendable stop signal not from tty", /* 23 SIGSTOP */
2537 "stop signal from tty", /* 24 SIGSTP */
2538 "continue a stopped process", /* 25 SIGCONT */
2539 "attempted background tty read", /* 26 SIGTTIN */
2540 "attempted background tty write", /* 27 SIGTTOU */
2541 "undefined", /* 28 */
2542 "undefined", /* 29 */
2543 "undefined", /* 30 */
2544 "undefined", /* 31 */
2545 "undefined", /* 32 */
2546 "socket (TCP/IP) urgent data arrival", /* 33 SIGURG */
2547 "I/O is possible", /* 34 SIGIO */
2548 "exceeded cpu time limit", /* 35 SIGXCPU */
2549 "exceeded file size limit", /* 36 SIGXFSZ */
2550 "virtual time alarm", /* 37 SIGVTALRM */
2551 "profiling time alarm", /* 38 SIGPROF */
2552 "undefined", /* 39 */
2553 "file record locks revoked", /* 40 SIGLOST */
2554 "undefined", /* 41 */
2555 "undefined", /* 42 */
2556 "undefined", /* 43 */
2557 "undefined", /* 44 */
2558 "undefined", /* 45 */
2559 "undefined", /* 46 */
2560 "undefined", /* 47 */
2561 "undefined", /* 48 */
2562 "undefined", /* 49 */
2563 "undefined", /* 50 */
2564 "undefined", /* 51 */
2565 "undefined", /* 52 */
2566 "undefined", /* 53 */
2567 "undefined", /* 54 */
2568 "undefined", /* 55 */
2569 "undefined", /* 56 */
2570 "undefined", /* 57 */
2571 "undefined", /* 58 */
2572 "undefined", /* 59 */
2573 "undefined", /* 60 */
2574 "undefined", /* 61 */
2575 "undefined", /* 62 */
2576 "undefined", /* 63 */
2577 "notification message in mess. queue", /* 64 SIGDGNOTIFY */
2578 0
2579};
2580
2581#endif /* DGUX */
2582\f
2583/* Directory routines for systems that don't have them. */
2584
2585#ifdef SYSV_SYSTEM_DIR
2586
2587#include <dirent.h>
2588
2589#ifndef AIX
2590int
2591closedir (dirp)
2592 register DIR *dirp; /* stream from opendir */
2593{
2594 sys_close (dirp->dd_fd);
2595 free ((char *) dirp->dd_buf); /* directory block defined in <dirent.h> */
2596 free ((char *) dirp);
2597}
2598#endif /* not AIX */
2599#endif /* SYSV_SYSTEM_DIR */
2600
2601#ifdef NONSYSTEM_DIR_LIBRARY
2602
2603DIR *
2604opendir (filename)
2605 char *filename; /* name of directory */
2606{
2607 register DIR *dirp; /* -> malloc'ed storage */
2608 register int fd; /* file descriptor for read */
2609 struct stat sbuf; /* result of fstat */
2610
2611 fd = sys_open (filename, 0);
2612 if (fd < 0)
2613 return 0;
2614
2615 if (fstat (fd, &sbuf) < 0
2616 || (sbuf.st_mode & S_IFMT) != S_IFDIR
2617 || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
2618 {
2619 sys_close (fd);
2620 return 0; /* bad luck today */
2621 }
2622
2623 dirp->dd_fd = fd;
2624 dirp->dd_loc = dirp->dd_size = 0; /* refill needed */
2625
2626 return dirp;
2627}
2628
2629void
2630closedir (dirp)
2631 register DIR *dirp; /* stream from opendir */
2632{
2633 sys_close (dirp->dd_fd);
2634 free ((char *) dirp);
2635}
2636
2637
2638#ifndef VMS
2639#define DIRSIZ 14
2640struct olddir
2641 {
2642 ino_t od_ino; /* inode */
2643 char od_name[DIRSIZ]; /* filename */
2644 };
2645#endif /* not VMS */
2646
2647struct direct dir_static; /* simulated directory contents */
2648
2649/* ARGUSED */
2650struct direct *
2651readdir (dirp)
2652 register DIR *dirp; /* stream from opendir */
2653{
2654#ifndef VMS
2655 register struct olddir *dp; /* -> directory data */
2656#else /* VMS */
2657 register struct dir$_name *dp; /* -> directory data */
2658 register struct dir$_version *dv; /* -> version data */
2659#endif /* VMS */
2660
2661 for (; ;)
2662 {
2663 if (dirp->dd_loc >= dirp->dd_size)
2664 dirp->dd_loc = dirp->dd_size = 0;
2665
2666 if (dirp->dd_size == 0 /* refill buffer */
2667 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2668 return 0;
2669
2670#ifndef VMS
2671 dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
2672 dirp->dd_loc += sizeof (struct olddir);
2673
2674 if (dp->od_ino != 0) /* not deleted entry */
2675 {
2676 dir_static.d_ino = dp->od_ino;
2677 strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
2678 dir_static.d_name[DIRSIZ] = '\0';
2679 dir_static.d_namlen = strlen (dir_static.d_name);
2680 dir_static.d_reclen = sizeof (struct direct)
2681 - MAXNAMLEN + 3
2682 + dir_static.d_namlen - dir_static.d_namlen % 4;
2683 return &dir_static; /* -> simulated structure */
2684 }
2685#else /* VMS */
2686 dp = (struct dir$_name *) dirp->dd_buf;
2687 if (dirp->dd_loc == 0)
2688 dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
2689 : dp->dir$b_namecount;
2690 dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
2691 dir_static.d_ino = dv->dir$w_fid_num;
2692 dir_static.d_namlen = dp->dir$b_namecount;
2693 dir_static.d_reclen = sizeof (struct direct)
2694 - MAXNAMLEN + 3
2695 + dir_static.d_namlen - dir_static.d_namlen % 4;
2696 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2697 dir_static.d_name[dir_static.d_namlen] = '\0';
2698 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
2699 return &dir_static;
2700#endif /* VMS */
2701 }
2702}
2703
2704#ifdef VMS
2705/* readdirver is just like readdir except it returns all versions of a file
2706 as separate entries. */
2707
2708/* ARGUSED */
2709struct direct *
2710readdirver (dirp)
2711 register DIR *dirp; /* stream from opendir */
2712{
2713 register struct dir$_name *dp; /* -> directory data */
2714 register struct dir$_version *dv; /* -> version data */
2715
2716 if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
2717 dirp->dd_loc = dirp->dd_size = 0;
2718
2719 if (dirp->dd_size == 0 /* refill buffer */
2720 && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
2721 return 0;
2722
2723 dp = (struct dir$_name *) dirp->dd_buf;
2724 if (dirp->dd_loc == 0)
2725 dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
2726 : dp->dir$b_namecount;
2727 dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
2728 strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
2729 sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
2730 dir_static.d_namlen = strlen (dir_static.d_name);
2731 dir_static.d_ino = dv->dir$w_fid_num;
2732 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
2733 + dir_static.d_namlen - dir_static.d_namlen % 4;
2734 dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
2735 return &dir_static;
2736}
2737
2738#endif /* VMS */
2739
2740#endif /* NONSYSTEM_DIR_LIBRARY */
2741\f
2742/* Functions for VMS */
2743#ifdef VMS
91bac16a 2744#include "vms-pwd.h"
86a5659e
JB
2745#include <acldef.h>
2746#include <chpdef.h>
2747#include <jpidef.h>
2748
2749/* Return as a string the VMS error string pertaining to STATUS.
2750 Reuses the same static buffer each time it is called. */
2751
2752char *
2753vmserrstr (status)
2754 int status; /* VMS status code */
2755{
2756 int bufadr[2];
2757 short len;
2758 static char buf[257];
2759
2760 bufadr[0] = sizeof buf - 1;
2761 bufadr[1] = (int) buf;
2762 if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
2763 return "untranslatable VMS error status";
2764 buf[len] = '\0';
2765 return buf;
2766}
2767
2768#ifdef access
2769#undef access
2770
2771/* The following is necessary because 'access' emulation by VMS C (2.0) does
2772 * not work correctly. (It also doesn't work well in version 2.3.)
2773 */
2774
2775#ifdef VMS4_4
2776
2777#define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
2778 { strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
2779
2780typedef union {
2781 struct {
2782 unsigned short s_buflen;
2783 unsigned short s_code;
2784 char *s_bufadr;
2785 unsigned short *s_retlenadr;
2786 } s;
2787 int end;
2788} item;
2789#define buflen s.s_buflen
2790#define code s.s_code
2791#define bufadr s.s_bufadr
2792#define retlenadr s.s_retlenadr
2793
2794#define R_OK 4 /* test for read permission */
2795#define W_OK 2 /* test for write permission */
2796#define X_OK 1 /* test for execute (search) permission */
2797#define F_OK 0 /* test for presence of file */
2798
2799int
2800sys_access (path, mode)
2801 char *path;
2802 int mode;
2803{
2804 static char *user = NULL;
2805 char dir_fn[512];
2806
2807 /* translate possible directory spec into .DIR file name, so brain-dead
2808 * access can treat the directory like a file. */
2809 if (directory_file_name (path, dir_fn))
2810 path = dir_fn;
2811
2812 if (mode == F_OK)
2813 return access (path, mode);
2814 if (user == NULL && (user = (char *) getenv ("USER")) == NULL)
2815 return -1;
2816 {
2817 int stat;
2818 int flags;
2819 int acces;
2820 unsigned short int dummy;
2821 item itemlst[3];
2822 static int constant = ACL$C_FILE;
2823 DESCRIPTOR (path_desc, path);
2824 DESCRIPTOR (user_desc, user);
2825
2826 flags = 0;
2827 acces = 0;
2828 if ((mode & X_OK) && ((stat = access (path, mode)) < 0 || mode == X_OK))
2829 return stat;
2830 if (mode & R_OK)
2831 acces |= CHP$M_READ;
2832 if (mode & W_OK)
2833 acces |= CHP$M_WRITE;
2834 itemlst[0].buflen = sizeof (int);
2835 itemlst[0].code = CHP$_FLAGS;
2836 itemlst[0].bufadr = (char *) &flags;
2837 itemlst[0].retlenadr = &dummy;
2838 itemlst[1].buflen = sizeof (int);
2839 itemlst[1].code = CHP$_ACCESS;
2840 itemlst[1].bufadr = (char *) &acces;
2841 itemlst[1].retlenadr = &dummy;
2842 itemlst[2].end = CHP$_END;
2843 stat = SYS$CHECK_ACCESS (&constant, &path_desc, &user_desc, itemlst);
2844 return stat == SS$_NORMAL ? 0 : -1;
2845 }
2846}
2847
2848#else /* not VMS4_4 */
2849
2850#include <prvdef.h>
2851#define ACE$M_WRITE 2
2852#define ACE$C_KEYID 1
2853
2854static unsigned short memid, grpid;
2855static unsigned int uic;
2856
2857/* Called from init_sys_modes, so it happens not very often
2858 but at least each time Emacs is loaded. */
2859sys_access_reinit ()
2860{
2861 uic = 0;
2862}
2863
2864int
2865sys_access (filename, type)
2866 char * filename;
2867 int type;
2868{
2869 struct FAB fab;
2870 struct XABPRO xab;
2871 int status, size, i, typecode, acl_controlled;
2872 unsigned int *aclptr, *aclend, aclbuf[60];
2873 union prvdef prvmask;
2874
2875 /* Get UIC and GRP values for protection checking. */
2876 if (uic == 0)
2877 {
2878 status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
2879 if (! (status & 1))
2880 return -1;
2881 memid = uic & 0xFFFF;
2882 grpid = uic >> 16;
2883 }
2884
2885 if (type != 2) /* not checking write access */
2886 return access (filename, type);
2887
2888 /* Check write protection. */
2889
2890#define CHECKPRIV(bit) (prvmask.bit)
2891#define WRITEABLE(field) (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
2892
2893 /* Find privilege bits */
2894 status = sys$setprv (0, 0, 0, prvmask);
2895 if (! (status & 1))
2896 error ("Unable to find privileges: %s", vmserrstr (status));
2897 if (CHECKPRIV (PRV$V_BYPASS))
2898 return 0; /* BYPASS enabled */
2899 fab = cc$rms_fab;
2900 fab.fab$b_fac = FAB$M_GET;
2901 fab.fab$l_fna = filename;
2902 fab.fab$b_fns = strlen (filename);
2903 fab.fab$l_xab = &xab;
2904 xab = cc$rms_xabpro;
2905 xab.xab$l_aclbuf = aclbuf;
2906 xab.xab$w_aclsiz = sizeof (aclbuf);
2907 status = sys$open (&fab, 0, 0);
2908 if (! (status & 1))
2909 return -1;
2910 sys$close (&fab, 0, 0);
2911 /* Check system access */
2912 if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
2913 return 0;
2914 /* Check ACL entries, if any */
2915 acl_controlled = 0;
2916 if (xab.xab$w_acllen > 0)
2917 {
2918 aclptr = aclbuf;
2919 aclend = &aclbuf[xab.xab$w_acllen / 4];
2920 while (*aclptr && aclptr < aclend)
2921 {
2922 size = (*aclptr & 0xff) / 4;
2923 typecode = (*aclptr >> 8) & 0xff;
2924 if (typecode == ACE$C_KEYID)
2925 for (i = size - 1; i > 1; i--)
2926 if (aclptr[i] == uic)
2927 {
2928 acl_controlled = 1;
2929 if (aclptr[1] & ACE$M_WRITE)
2930 return 0; /* Write access through ACL */
2931 }
2932 aclptr = &aclptr[size];
2933 }
2934 if (acl_controlled) /* ACL specified, prohibits write access */
2935 return -1;
2936 }
2937 /* No ACL entries specified, check normal protection */
2938 if (WRITEABLE (XAB$V_WLD)) /* World writeable */
2939 return 0;
2940 if (WRITEABLE (XAB$V_GRP) &&
2941 (unsigned short) (xab.xab$l_uic >> 16) == grpid)
2942 return 0; /* Group writeable */
2943 if (WRITEABLE (XAB$V_OWN) &&
2944 (xab.xab$l_uic & 0xFFFF) == memid)
2945 return 0; /* Owner writeable */
2946
2947 return -1; /* Not writeable */
2948}
2949#endif /* not VMS4_4 */
2950#endif /* access */
2951
2952static char vtbuf[NAM$C_MAXRSS+1];
2953
2954/* translate a vms file spec to a unix path */
2955char *
2956sys_translate_vms (vfile)
2957 char * vfile;
2958{
2959 char * p;
2960 char * targ;
2961
2962 if (!vfile)
2963 return 0;
2964
2965 targ = vtbuf;
2966
2967 /* leading device or logical name is a root directory */
2968 if (p = strchr (vfile, ':'))
2969 {
2970 *targ++ = '/';
2971 while (vfile < p)
2972 *targ++ = *vfile++;
2973 vfile++;
2974 *targ++ = '/';
2975 }
2976 p = vfile;
2977 if (*p == '[' || *p == '<')
2978 {
2979 while (*++vfile != *p + 2)
2980 switch (*vfile)
2981 {
2982 case '.':
2983 if (vfile[-1] == *p)
2984 *targ++ = '.';
2985 *targ++ = '/';
2986 break;
2987
2988 case '-':
2989 *targ++ = '.';
2990 *targ++ = '.';
2991 break;
2992
2993 default:
2994 *targ++ = *vfile;
2995 break;
2996 }
2997 vfile++;
2998 *targ++ = '/';
2999 }
3000 while (*vfile)
3001 *targ++ = *vfile++;
3002
3003 return vtbuf;
3004}
3005
3006static char utbuf[NAM$C_MAXRSS+1];
3007
3008/* translate a unix path to a VMS file spec */
3009char *
3010sys_translate_unix (ufile)
3011 char * ufile;
3012{
3013 int slash_seen = 0;
3014 char *p;
3015 char * targ;
3016
3017 if (!ufile)
3018 return 0;
3019
3020 targ = utbuf;
3021
3022 if (*ufile == '/')
3023 {
3024 ufile++;
3025 }
3026
3027 while (*ufile)
3028 {
3029 switch (*ufile)
3030 {
3031 case '/':
3032 if (slash_seen)
3033 if (index (&ufile[1], '/'))
3034 *targ++ = '.';
3035 else
3036 *targ++ = ']';
3037 else
3038 {
3039 *targ++ = ':';
3040 if (index (&ufile[1], '/'))
3041 *targ++ = '[';
3042 slash_seen = 1;
3043 }
3044 break;
3045
3046 case '.':
3047 if (strncmp (ufile, "./", 2) == 0)
3048 {
3049 if (!slash_seen)
3050 {
3051 *targ++ = '[';
3052 slash_seen = 1;
3053 }
3054 ufile++; /* skip the dot */
3055 if (index (&ufile[1], '/'))
3056 *targ++ = '.';
3057 else
3058 *targ++ = ']';
3059 }
3060 else if (strncmp (ufile, "../", 3) == 0)
3061 {
3062 if (!slash_seen)
3063 {
3064 *targ++ = '[';
3065 slash_seen = 1;
3066 }
3067 *targ++ = '-';
3068 ufile += 2; /* skip the dots */
3069 if (index (&ufile[1], '/'))
3070 *targ++ = '.';
3071 else
3072 *targ++ = ']';
3073 }
3074 else
3075 *targ++ = *ufile;
3076 break;
3077
3078 default:
3079 *targ++ = *ufile;
3080 break;
3081 }
3082 ufile++;
3083 }
3084 *targ = '\0';
3085
3086 return utbuf;
3087}
3088
3089char *
3090getwd (pathname)
3091 char *pathname;
3092{
3093 char *ptr;
3094 strcpy (pathname, egetenv ("PATH"));
3095
3096 ptr = pathname;
3097 while (*ptr)
3098 {
3099 if ('a' <= *ptr && *ptr <= 'z')
3100 *ptr -= 040;
3101 ptr++;
3102 }
3103 return pathname;
3104}
3105
3106getppid ()
3107{
3108 long item_code = JPI$_OWNER;
3109 unsigned long parent_id;
3110 int status;
3111
3112 if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
3113 {
3114 errno = EVMSERR;
3115 vaxc$errno = status;
3116 return -1;
3117 }
3118 return parent_id;
3119}
3120
3121#undef getuid
3122unsigned
3123sys_getuid ()
3124{
3125 return (getgid () << 16) | getuid ();
3126}
3127
3128int
3129sys_read (fildes, buf, nbyte)
3130 int fildes;
3131 char *buf;
3132 unsigned int nbyte;
3133{
3134 return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
3135}
3136
3137#if 0
3138int
3139sys_write (fildes, buf, nbyte)
3140 int fildes;
3141 char *buf;
3142 unsigned int nbyte;
3143{
3144 register int nwrote, rtnval = 0;
3145
3146 while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
3147 nbyte -= nwrote;
3148 buf += nwrote;
3149 rtnval += nwrote;
3150 }
3151 if (nwrote < 0)
3152 return rtnval ? rtnval : -1;
3153 if ((nwrote = write (fildes, buf, nbyte)) < 0)
3154 return rtnval ? rtnval : -1;
3155 return (rtnval + nwrote);
3156}
3157#endif /* 0 */
3158
3159/*
3160 * VAX/VMS VAX C RTL really loses. It insists that records
3161 * end with a newline (carriage return) character, and if they
3162 * don't it adds one (nice of it isn't it!)
3163 *
3164 * Thus we do this stupidity below.
3165 */
3166
3167int
3168sys_write (fildes, buf, nbytes)
3169 int fildes;
3170 char *buf;
3171 unsigned int nbytes;
3172{
3173 register char *p;
3174 register char *e;
23b0668c
JB
3175 int sum = 0;
3176 struct stat st;
3177
3178 fstat (fildes, &st);
86a5659e 3179 p = buf;
86a5659e
JB
3180 while (nbytes > 0)
3181 {
23b0668c
JB
3182 int len, retval;
3183
3184 /* Handle fixed-length files with carriage control. */
3185 if (st.st_fab_rfm == FAB$C_FIX
3186 && ((st.st_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0))
3187 {
3188 len = st.st_fab_mrs;
3189 retval = write (fildes, p, min (len, nbytes));
3190 if (retval != len)
3191 return -1;
3192 retval++; /* This skips the implied carriage control */
3193 }
3194 else
3195 {
3196 e = p + min (MAXIOSIZE, nbytes) - 1;
3197 while (*e != '\n' && e > p) e--;
3198 if (p == e) /* Ok.. so here we add a newline... sigh. */
3199 e = p + min (MAXIOSIZE, nbytes) - 1;
3200 len = e + 1 - p;
3201 retval = write (fildes, p, len);
3202 if (retval != len)
3203 return -1;
3204 }
3205 p += retval;
3206 sum += retval;
86a5659e
JB
3207 nbytes -= retval;
3208 }
3209 return sum;
3210}
3211
3212/* Create file NEW copying its attributes from file OLD. If
3213 OLD is 0 or does not exist, create based on the value of
3214 vms_stmlf_recfm. */
3215
3216/* Protection value the file should ultimately have.
3217 Set by create_copy_attrs, and use by rename_sansversions. */
3218static unsigned short int fab_final_pro;
3219
3220int
3221creat_copy_attrs (old, new)
3222 char *old, *new;
3223{
3224 struct FAB fab = cc$rms_fab;
3225 struct XABPRO xabpro;
3226 char aclbuf[256]; /* Choice of size is arbitrary. See below. */
3227 extern int vms_stmlf_recfm;
3228
3229 if (old)
3230 {
3231 fab.fab$b_fac = FAB$M_GET;
3232 fab.fab$l_fna = old;
3233 fab.fab$b_fns = strlen (old);
3234 fab.fab$l_xab = (char *) &xabpro;
3235 xabpro = cc$rms_xabpro;
3236 xabpro.xab$l_aclbuf = aclbuf;
3237 xabpro.xab$w_aclsiz = sizeof aclbuf;
3238 /* Call $OPEN to fill in the fab & xabpro fields. */
3239 if (sys$open (&fab, 0, 0) & 1)
3240 {
3241 sys$close (&fab, 0, 0);
3242 fab.fab$l_alq = 0; /* zero the allocation quantity */
3243 if (xabpro.xab$w_acllen > 0)
3244 {
3245 if (xabpro.xab$w_acllen > sizeof aclbuf)
3246 /* If the acl buffer was too short, redo open with longer one.
3247 Wouldn't need to do this if there were some system imposed
3248 limit on the size of an ACL, but I can't find any such. */
3249 {
3250 xabpro.xab$l_aclbuf = (char *) alloca (xabpro.xab$w_acllen);
3251 xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
3252 if (sys$open (&fab, 0, 0) & 1)
3253 sys$close (&fab, 0, 0);
3254 else
3255 old = 0;
3256 }
3257 }
3258 else
3259 xabpro.xab$l_aclbuf = 0;
3260 }
3261 else
3262 old = 0;
3263 }
3264 fab.fab$l_fna = new;
3265 fab.fab$b_fns = strlen (new);
3266 if (!old)
3267 {
3268 fab.fab$l_xab = 0;
3269 fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
3270 fab.fab$b_rat = FAB$M_CR;
3271 }
3272
3273 /* Set the file protections such that we will be able to manipulate
3274 this file. Once we are done writing and renaming it, we will set
3275 the protections back. */
3276 if (old)
3277 fab_final_pro = xabpro.xab$w_pro;
3278 else
3279 sys$setdfprot (0, &fab_final_pro);
3280 xabpro.xab$w_pro &= 0xff0f; /* set O:rewd for now. This is set back later. */
3281
3282 /* Create the new file with either default attrs or attrs copied
3283 from old file. */
3284 if (!(SYS$CREATE (&fab, 0, 0) & 1))
3285 return -1;
3286 sys$close (&fab, 0, 0);
3287 /* As this is a "replacement" for creat, return a file descriptor
3288 opened for writing. */
3289 return open (new, O_WRONLY);
3290}
3291
3292#ifdef creat
3293#undef creat
3294#include <varargs.h>
3295#ifdef __GNUC__
3296#ifndef va_count
3297#define va_count(X) ((X) = *(((int *) &(va_alist)) - 1))
3298#endif
3299#endif
3300
3301sys_creat (va_alist)
3302 va_dcl
3303{
3304 va_list list_incrementor;
3305 char *name;
3306 int mode;
3307 int rfd; /* related file descriptor */
3308 int fd; /* Our new file descriptor */
3309 int count;
3310 struct stat st_buf;
3311 char rfm[12];
3312 char rat[15];
3313 char mrs[13];
3314 char fsz[13];
3315 extern int vms_stmlf_recfm;
3316
3317 va_count (count);
3318 va_start (list_incrementor);
3319 name = va_arg (list_incrementor, char *);
3320 mode = va_arg (list_incrementor, int);
3321 if (count > 2)
3322 rfd = va_arg (list_incrementor, int);
3323 va_end (list_incrementor);
3324 if (count > 2)
3325 {
3326 /* Use information from the related file descriptor to set record
3327 format of the newly created file. */
3328 fstat (rfd, &st_buf);
3329 switch (st_buf.st_fab_rfm)
3330 {
3331 case FAB$C_FIX:
3332 strcpy (rfm, "rfm = fix");
3333 sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
3334 strcpy (rat, "rat = ");
3335 if (st_buf.st_fab_rat & FAB$M_CR)
3336 strcat (rat, "cr");
3337 else if (st_buf.st_fab_rat & FAB$M_FTN)
3338 strcat (rat, "ftn");
3339 else if (st_buf.st_fab_rat & FAB$M_PRN)
3340 strcat (rat, "prn");
3341 if (st_buf.st_fab_rat & FAB$M_BLK)
3342 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3343 strcat (rat, ", blk");
3344 else
3345 strcat (rat, "blk");
3346 return creat (name, 0, rfm, rat, mrs);
3347
3348 case FAB$C_VFC:
3349 strcpy (rfm, "rfm = vfc");
3350 sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
3351 strcpy (rat, "rat = ");
3352 if (st_buf.st_fab_rat & FAB$M_CR)
3353 strcat (rat, "cr");
3354 else if (st_buf.st_fab_rat & FAB$M_FTN)
3355 strcat (rat, "ftn");
3356 else if (st_buf.st_fab_rat & FAB$M_PRN)
3357 strcat (rat, "prn");
3358 if (st_buf.st_fab_rat & FAB$M_BLK)
3359 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3360 strcat (rat, ", blk");
3361 else
3362 strcat (rat, "blk");
3363 return creat (name, 0, rfm, rat, fsz);
3364
3365 case FAB$C_STM:
3366 strcpy (rfm, "rfm = stm");
3367 break;
3368
3369 case FAB$C_STMCR:
3370 strcpy (rfm, "rfm = stmcr");
3371 break;
3372
3373 case FAB$C_STMLF:
3374 strcpy (rfm, "rfm = stmlf");
3375 break;
3376
3377 case FAB$C_UDF:
3378 strcpy (rfm, "rfm = udf");
3379 break;
3380
3381 case FAB$C_VAR:
3382 strcpy (rfm, "rfm = var");
3383 break;
3384 }
3385 strcpy (rat, "rat = ");
3386 if (st_buf.st_fab_rat & FAB$M_CR)
3387 strcat (rat, "cr");
3388 else if (st_buf.st_fab_rat & FAB$M_FTN)
3389 strcat (rat, "ftn");
3390 else if (st_buf.st_fab_rat & FAB$M_PRN)
3391 strcat (rat, "prn");
3392 if (st_buf.st_fab_rat & FAB$M_BLK)
3393 if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
3394 strcat (rat, ", blk");
3395 else
3396 strcat (rat, "blk");
3397 }
3398 else
3399 {
3400 strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
3401 strcpy (rat, "rat=cr");
3402 }
3403 /* Until the VAX C RTL fixes the many bugs with modes, always use
3404 mode 0 to get the user's default protection. */
3405 fd = creat (name, 0, rfm, rat);
3406 if (fd < 0 && errno == EEXIST)
3407 {
3408 if (unlink (name) < 0)
3409 report_file_error ("delete", build_string (name));
3410 fd = creat (name, 0, rfm, rat);
3411 }
3412 return fd;
3413}
3414#endif /* creat */
3415
3416/* fwrite to stdout is S L O W. Speed it up by using fputc...*/
3417sys_fwrite (ptr, size, num, fp)
3418 register char * ptr;
3419 FILE * fp;
3420{
3421 register int tot = num * size;
3422
3423 while (tot--)
3424 fputc (*ptr++, fp);
3425}
3426
3427/*
3428 * The VMS C library routine creat actually creates a new version of an
3429 * existing file rather than truncating the old version. There are times
3430 * when this is not the desired behavior, for instance, when writing an
3431 * auto save file (you only want one version), or when you don't have
3432 * write permission in the directory containing the file (but the file
3433 * itself is writable). Hence this routine, which is equivalent to
3434 * "close (creat (fn, 0));" on Unix if fn already exists.
3435 */
3436int
3437vms_truncate (fn)
3438 char *fn;
3439{
3440 struct FAB xfab = cc$rms_fab;
3441 struct RAB xrab = cc$rms_rab;
3442 int status;
3443
3444 xfab.fab$l_fop = FAB$M_TEF; /* free allocated but unused blocks on close */
3445 xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
3446 xfab.fab$b_shr = FAB$M_NIL; /* allow no sharing - file must be locked */
3447 xfab.fab$l_fna = fn;
3448 xfab.fab$b_fns = strlen (fn);
3449 xfab.fab$l_dna = ";0"; /* default to latest version of the file */
3450 xfab.fab$b_dns = 2;
3451 xrab.rab$l_fab = &xfab;
3452
3453 /* This gibberish opens the file, positions to the first record, and
3454 deletes all records from there until the end of file. */
3455 if ((sys$open (&xfab) & 01) == 01)
3456 {
3457 if ((sys$connect (&xrab) & 01) == 01 &&
3458 (sys$find (&xrab) & 01) == 01 &&
3459 (sys$truncate (&xrab) & 01) == 01)
3460 status = 0;
3461 else
3462 status = -1;
3463 }
3464 else
3465 status = -1;
3466 sys$close (&xfab);
3467 return status;
3468}
3469
3470/* Define this symbol to actually read SYSUAF.DAT. This requires either
3471 SYSPRV or a readable SYSUAF.DAT. */
3472
3473#ifdef READ_SYSUAF
3474/*
3475 * getuaf.c
3476 *
3477 * Routine to read the VMS User Authorization File and return
3478 * a specific user's record.
3479 */
3480
3481static struct UAF retuaf;
3482
3483struct UAF *
3484get_uaf_name (uname)
3485 char * uname;
3486{
3487 register status;
3488 struct FAB uaf_fab;
3489 struct RAB uaf_rab;
3490
3491 uaf_fab = cc$rms_fab;
3492 uaf_rab = cc$rms_rab;
3493 /* initialize fab fields */
3494 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3495 uaf_fab.fab$b_fns = 21;
3496 uaf_fab.fab$b_fac = FAB$M_GET;
3497 uaf_fab.fab$b_org = FAB$C_IDX;
3498 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3499 /* initialize rab fields */
3500 uaf_rab.rab$l_fab = &uaf_fab;
3501 /* open the User Authorization File */
3502 status = sys$open (&uaf_fab);
3503 if (!(status&1))
3504 {
3505 errno = EVMSERR;
3506 vaxc$errno = status;
3507 return 0;
3508 }
3509 status = sys$connect (&uaf_rab);
3510 if (!(status&1))
3511 {
3512 errno = EVMSERR;
3513 vaxc$errno = status;
3514 return 0;
3515 }
3516 /* read the requested record - index is in uname */
3517 uaf_rab.rab$l_kbf = uname;
3518 uaf_rab.rab$b_ksz = strlen (uname);
3519 uaf_rab.rab$b_rac = RAB$C_KEY;
3520 uaf_rab.rab$l_ubf = (char *)&retuaf;
3521 uaf_rab.rab$w_usz = sizeof retuaf;
3522 status = sys$get (&uaf_rab);
3523 if (!(status&1))
3524 {
3525 errno = EVMSERR;
3526 vaxc$errno = status;
3527 return 0;
3528 }
3529 /* close the User Authorization File */
3530 status = sys$disconnect (&uaf_rab);
3531 if (!(status&1))
3532 {
3533 errno = EVMSERR;
3534 vaxc$errno = status;
3535 return 0;
3536 }
3537 status = sys$close (&uaf_fab);
3538 if (!(status&1))
3539 {
3540 errno = EVMSERR;
3541 vaxc$errno = status;
3542 return 0;
3543 }
3544 return &retuaf;
3545}
3546
3547struct UAF *
3548get_uaf_uic (uic)
3549 unsigned long uic;
3550{
3551 register status;
3552 struct FAB uaf_fab;
3553 struct RAB uaf_rab;
3554
3555 uaf_fab = cc$rms_fab;
3556 uaf_rab = cc$rms_rab;
3557 /* initialize fab fields */
3558 uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
3559 uaf_fab.fab$b_fns = 21;
3560 uaf_fab.fab$b_fac = FAB$M_GET;
3561 uaf_fab.fab$b_org = FAB$C_IDX;
3562 uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
3563 /* initialize rab fields */
3564 uaf_rab.rab$l_fab = &uaf_fab;
3565 /* open the User Authorization File */
3566 status = sys$open (&uaf_fab);
3567 if (!(status&1))
3568 {
3569 errno = EVMSERR;
3570 vaxc$errno = status;
3571 return 0;
3572 }
3573 status = sys$connect (&uaf_rab);
3574 if (!(status&1))
3575 {
3576 errno = EVMSERR;
3577 vaxc$errno = status;
3578 return 0;
3579 }
3580 /* read the requested record - index is in uic */
3581 uaf_rab.rab$b_krf = 1; /* 1st alternate key */
3582 uaf_rab.rab$l_kbf = (char *) &uic;
3583 uaf_rab.rab$b_ksz = sizeof uic;
3584 uaf_rab.rab$b_rac = RAB$C_KEY;
3585 uaf_rab.rab$l_ubf = (char *)&retuaf;
3586 uaf_rab.rab$w_usz = sizeof retuaf;
3587 status = sys$get (&uaf_rab);
3588 if (!(status&1))
3589 {
3590 errno = EVMSERR;
3591 vaxc$errno = status;
3592 return 0;
3593 }
3594 /* close the User Authorization File */
3595 status = sys$disconnect (&uaf_rab);
3596 if (!(status&1))
3597 {
3598 errno = EVMSERR;
3599 vaxc$errno = status;
3600 return 0;
3601 }
3602 status = sys$close (&uaf_fab);
3603 if (!(status&1))
3604 {
3605 errno = EVMSERR;
3606 vaxc$errno = status;
3607 return 0;
3608 }
3609 return &retuaf;
3610}
3611
3612static struct passwd retpw;
3613
3614struct passwd *
3615cnv_uaf_pw (up)
3616 struct UAF * up;
3617{
3618 char * ptr;
3619
3620 /* copy these out first because if the username is 32 chars, the next
3621 section will overwrite the first byte of the UIC */
3622 retpw.pw_uid = up->uaf$w_mem;
3623 retpw.pw_gid = up->uaf$w_grp;
3624
3625 /* I suppose this is not the best sytle, to possibly overwrite one
3626 byte beyond the end of the field, but what the heck... */
3627 ptr = &up->uaf$t_username[UAF$S_USERNAME];
3628 while (ptr[-1] == ' ')
3629 ptr--;
3630 *ptr = '\0';
3631 strcpy (retpw.pw_name, up->uaf$t_username);
3632
3633 /* the rest of these are counted ascii strings */
3634 strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
3635 retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
3636 strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
3637 retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
3638 strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
3639 retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
3640 strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
3641 retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
3642
3643 return &retpw;
3644}
3645#else /* not READ_SYSUAF */
3646static struct passwd retpw;
3647#endif /* not READ_SYSUAF */
3648
3649struct passwd *
3650getpwnam (name)
3651 char * name;
3652{
3653#ifdef READ_SYSUAF
3654 struct UAF *up;
3655#else
3656 char * user;
3657 char * dir;
3658 unsigned char * full;
3659#endif /* READ_SYSUAF */
3660 char *ptr = name;
3661
3662 while (*ptr)
3663 {
3664 if ('a' <= *ptr && *ptr <= 'z')
3665 *ptr -= 040;
3666 ptr++;
3667 }
3668#ifdef READ_SYSUAF
3669 if (!(up = get_uaf_name (name)))
3670 return 0;
3671 return cnv_uaf_pw (up);
3672#else
3673 if (strcmp (name, getenv ("USER")) == 0)
3674 {
3675 retpw.pw_uid = getuid ();
3676 retpw.pw_gid = getgid ();
3677 strcpy (retpw.pw_name, name);
3678 if (full = egetenv ("FULLNAME"))
3679 strcpy (retpw.pw_gecos, full);
3680 else
3681 *retpw.pw_gecos = '\0';
3682 strcpy (retpw.pw_dir, egetenv ("HOME"));
3683 *retpw.pw_shell = '\0';
3684 return &retpw;
3685 }
3686 else
3687 return 0;
3688#endif /* not READ_SYSUAF */
3689}
3690
3691struct passwd *
3692getpwuid (uid)
3693 unsigned long uid;
3694{
3695#ifdef READ_SYSUAF
3696 struct UAF * up;
3697
3698 if (!(up = get_uaf_uic (uid)))
3699 return 0;
3700 return cnv_uaf_pw (up);
3701#else
3702 if (uid == sys_getuid ())
3703 return getpwnam (egetenv ("USER"));
3704 else
3705 return 0;
3706#endif /* not READ_SYSUAF */
3707}
3708
3709/* return total address space available to the current process. This is
3710 the sum of the current p0 size, p1 size and free page table entries
3711 available. */
3712vlimit ()
3713{
3714 int item_code;
3715 unsigned long free_pages;
3716 unsigned long frep0va;
3717 unsigned long frep1va;
3718 register status;
3719
3720 item_code = JPI$_FREPTECNT;
3721 if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
3722 {
3723 errno = EVMSERR;
3724 vaxc$errno = status;
3725 return -1;
3726 }
3727 free_pages *= 512;
3728
3729 item_code = JPI$_FREP0VA;
3730 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
3731 {
3732 errno = EVMSERR;
3733 vaxc$errno = status;
3734 return -1;
3735 }
3736 item_code = JPI$_FREP1VA;
3737 if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
3738 {
3739 errno = EVMSERR;
3740 vaxc$errno = status;
3741 return -1;
3742 }
3743
3744 return free_pages + frep0va + (0x7fffffff - frep1va);
3745}
3746
3747define_logical_name (varname, string)
3748 char *varname;
3749 char *string;
3750{
3751 struct dsc$descriptor_s strdsc =
3752 {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
3753 struct dsc$descriptor_s envdsc =
3754 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3755 struct dsc$descriptor_s lnmdsc =
3756 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3757
3758 return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
3759}
3760
3761delete_logical_name (varname)
3762 char *varname;
3763{
3764 struct dsc$descriptor_s envdsc =
3765 {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
3766 struct dsc$descriptor_s lnmdsc =
3767 {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
3768
3769 return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
3770}
3771
3772ulimit ()
3773{}
3774
86a5659e
JB
3775setpgrp ()
3776{}
3777
3778execvp ()
3779{
3780 error ("execvp system call not implemented");
3781}
3782
3783int
3784rename (from, to)
3785 char *from, *to;
3786{
3787 int status;
3788 struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
3789 struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
3790 char from_esn[NAM$C_MAXRSS];
3791 char to_esn[NAM$C_MAXRSS];
3792
3793 from_fab.fab$l_fna = from;
3794 from_fab.fab$b_fns = strlen (from);
3795 from_fab.fab$l_nam = &from_nam;
3796 from_fab.fab$l_fop = FAB$M_NAM;
3797
3798 from_nam.nam$l_esa = from_esn;
3799 from_nam.nam$b_ess = sizeof from_esn;
3800
3801 to_fab.fab$l_fna = to;
3802 to_fab.fab$b_fns = strlen (to);
3803 to_fab.fab$l_nam = &to_nam;
3804 to_fab.fab$l_fop = FAB$M_NAM;
3805
3806 to_nam.nam$l_esa = to_esn;
3807 to_nam.nam$b_ess = sizeof to_esn;
3808
3809 status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
3810
3811 if (status & 1)
3812 return 0;
3813 else
3814 {
3815 if (status == RMS$_DEV)
3816 errno = EXDEV;
3817 else
3818 errno = EVMSERR;
3819 vaxc$errno = status;
3820 return -1;
3821 }
3822}
3823
3824/* This function renames a file like `rename', but it strips
3825 the version number from the "to" filename, such that the "to" file is
3826 will always be a new version. It also sets the file protection once it is
3827 finished. The protection that we will use is stored in fab_final_pro,
3828 and was set when we did a creat_copy_attrs to create the file that we
3829 are renaming.
3830
3831 We could use the chmod function, but Eunichs uses 3 bits per user category
3832 to describe the protection, and VMS uses 4 (write and delete are seperate
3833 bits). To maintain portability, the VMS implementation of `chmod' wires
3834 the W and D bits together. */
3835
3836
3837static struct fibdef fib; /* We need this initialized to zero */
3838char vms_file_written[NAM$C_MAXRSS];
3839
3840int
3841rename_sans_version (from,to)
3842 char *from, *to;
3843{
3844 short int chan;
3845 int stat;
3846 short int iosb[4];
3847 int status;
3848 struct FAB to_fab = cc$rms_fab;
3849 struct NAM to_nam = cc$rms_nam;
3850 struct dsc$descriptor fib_d ={sizeof (fib),0,0,(char*) &fib};
3851 struct dsc$descriptor fib_attr[2]
3852 = {{sizeof (fab_final_pro),ATR$C_FPRO,0,(char*) &fab_final_pro},{0,0,0,0}};
3853 char to_esn[NAM$C_MAXRSS];
3854
3855 $DESCRIPTOR (disk,to_esn);
3856
3857 to_fab.fab$l_fna = to;
3858 to_fab.fab$b_fns = strlen (to);
3859 to_fab.fab$l_nam = &to_nam;
3860 to_fab.fab$l_fop = FAB$M_NAM;
3861
3862 to_nam.nam$l_esa = to_esn;
3863 to_nam.nam$b_ess = sizeof to_esn;
3864
3865 status = SYS$PARSE (&to_fab, 0, 0); /* figure out the full file name */
3866
3867 if (to_nam.nam$l_fnb && NAM$M_EXP_VER)
3868 *(to_nam.nam$l_ver) = '\0';
3869
3870 stat = rename (from, to_esn);
3871 if (stat < 0)
3872 return stat;
3873
3874 strcpy (vms_file_written, to_esn);
3875
3876 to_fab.fab$l_fna = vms_file_written; /* this points to the versionless name */
3877 to_fab.fab$b_fns = strlen (vms_file_written);
3878
3879 /* Now set the file protection to the correct value */
3880 sys$open (&to_fab, 0, 0); /* This fills in the nam$w_fid fields */
3881
3882 /* Copy these fields into the fib */
3883 fib.fib$r_fid_overlay.fib$w_fid[0] = to_nam.nam$w_fid[0];
3884 fib.fib$r_fid_overlay.fib$w_fid[1] = to_nam.nam$w_fid[1];
3885 fib.fib$r_fid_overlay.fib$w_fid[2] = to_nam.nam$w_fid[2];
3886
3887 sys$close (&to_fab, 0, 0);
3888
3889 stat = sys$assign (&disk, &chan, 0, 0); /* open a channel to the disk */
3890 if (!stat)
3891 lib$signal (stat);
3892 stat = sys$qiow (0, chan, IO$_MODIFY, iosb, 0, 0, &fib_d,
3893 0, 0, 0, &fib_attr, 0);
3894 if (!stat)
3895 lib$signal (stat);
3896 stat = sys$dassgn (chan);
3897 if (!stat)
3898 lib$signal (stat);
0137dbf7 3899 strcpy (vms_file_written, to_esn); /* We will write this to the terminal*/
86a5659e
JB
3900 return 0;
3901}
3902
3903link (file, new)
3904 char * file, * new;
3905{
3906 register status;
3907 struct FAB fab;
3908 struct NAM nam;
3909 unsigned short fid[3];
3910 char esa[NAM$C_MAXRSS];
3911
3912 fab = cc$rms_fab;
3913 fab.fab$l_fop = FAB$M_OFP;
3914 fab.fab$l_fna = file;
3915 fab.fab$b_fns = strlen (file);
3916 fab.fab$l_nam = &nam;
3917
3918 nam = cc$rms_nam;
3919 nam.nam$l_esa = esa;
3920 nam.nam$b_ess = NAM$C_MAXRSS;
3921
3922 status = SYS$PARSE (&fab);
3923 if ((status & 1) == 0)
3924 {
3925 errno = EVMSERR;
3926 vaxc$errno = status;
3927 return -1;
3928 }
3929 status = SYS$SEARCH (&fab);
3930 if ((status & 1) == 0)
3931 {
3932 errno = EVMSERR;
3933 vaxc$errno = status;
3934 return -1;
3935 }
3936
3937 fid[0] = nam.nam$w_fid[0];
3938 fid[1] = nam.nam$w_fid[1];
3939 fid[2] = nam.nam$w_fid[2];
3940
3941 fab.fab$l_fna = new;
3942 fab.fab$b_fns = strlen (new);
3943
3944 status = SYS$PARSE (&fab);
3945 if ((status & 1) == 0)
3946 {
3947 errno = EVMSERR;
3948 vaxc$errno = status;
3949 return -1;
3950 }
3951
3952 nam.nam$w_fid[0] = fid[0];
3953 nam.nam$w_fid[1] = fid[1];
3954 nam.nam$w_fid[2] = fid[2];
3955
3956 nam.nam$l_esa = nam.nam$l_name;
3957 nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
3958
3959 status = SYS$ENTER (&fab);
3960 if ((status & 1) == 0)
3961 {
3962 errno = EVMSERR;
3963 vaxc$errno = status;
3964 return -1;
3965 }
3966
3967 return 0;
3968}
3969
3970croak (badfunc)
3971 char *badfunc;
3972{
3973 printf ("%s not yet implemented\r\n", badfunc);
3974 reset_sys_modes ();
3975 exit (1);
3976}
3977
3978long
3979random ()
3980{
3981 /* Arrange to return a range centered on zero. */
3982 return rand () - (1 << 30);
3983}
3984
3985srandom (seed)
3986{
3987 srand (seed);
3988}
3989#endif /* VMS */
3990\f
3991#ifdef AIX
3992
3993/* Called from init_sys_modes. */
3994hft_init ()
3995{
3996 int junk;
3997
3998 /* If we're not on an HFT we shouldn't do any of this. We determine
3999 if we are on an HFT by trying to get an HFT error code. If this
4000 call fails, we're not on an HFT. */
4001#ifdef IBMR2AIX
4002 if (ioctl (0, HFQERROR, &junk) < 0)
4003 return;
4004#else /* not IBMR2AIX */
4005 if (ioctl (0, HFQEIO, 0) < 0)
4006 return;
4007#endif /* not IBMR2AIX */
4008
4009 /* On AIX the default hft keyboard mapping uses backspace rather than delete
4010 as the rubout key's ASCII code. Here this is changed. The bug is that
4011 there's no way to determine the old mapping, so in reset_sys_modes
4012 we need to assume that the normal map had been present. Of course, this
4013 code also doesn't help if on a terminal emulator which doesn't understand
4014 HFT VTD's. */
4015 {
4016 struct hfbuf buf;
4017 struct hfkeymap keymap;
4018
4019 buf.hf_bufp = (char *)&keymap;
4020 buf.hf_buflen = sizeof (keymap);
4021 keymap.hf_nkeys = 2;
4022 keymap.hfkey[0].hf_kpos = 15;
4023 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4024#ifdef IBMR2AIX
4025 keymap.hfkey[0].hf_keyidh = '<';
4026#else /* not IBMR2AIX */
4027 keymap.hfkey[0].hf_page = '<';
4028#endif /* not IBMR2AIX */
4029 keymap.hfkey[0].hf_char = 127;
4030 keymap.hfkey[1].hf_kpos = 15;
4031 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4032#ifdef IBMR2AIX
4033 keymap.hfkey[1].hf_keyidh = '<';
4034#else /* not IBMR2AIX */
4035 keymap.hfkey[1].hf_page = '<';
4036#endif /* not IBMR2AIX */
4037 keymap.hfkey[1].hf_char = 127;
4038 hftctl (0, HFSKBD, &buf);
4039 }
4040 /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
4041 at times. */
4042 line_ins_del_ok = char_ins_del_ok = 0;
4043}
4044
4045/* Reset the rubout key to backspace. */
4046
4047hft_reset ()
4048{
4049 struct hfbuf buf;
4050 struct hfkeymap keymap;
4051 int junk;
4052
4053#ifdef IBMR2AIX
4054 if (ioctl (0, HFQERROR, &junk) < 0)
4055 return;
4056#else /* not IBMR2AIX */
4057 if (ioctl (0, HFQEIO, 0) < 0)
4058 return;
4059#endif /* not IBMR2AIX */
4060
4061 buf.hf_bufp = (char *)&keymap;
4062 buf.hf_buflen = sizeof (keymap);
4063 keymap.hf_nkeys = 2;
4064 keymap.hfkey[0].hf_kpos = 15;
4065 keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
4066#ifdef IBMR2AIX
4067 keymap.hfkey[0].hf_keyidh = '<';
4068#else /* not IBMR2AIX */
4069 keymap.hfkey[0].hf_page = '<';
4070#endif /* not IBMR2AIX */
4071 keymap.hfkey[0].hf_char = 8;
4072 keymap.hfkey[1].hf_kpos = 15;
4073 keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
4074#ifdef IBMR2AIX
4075 keymap.hfkey[1].hf_keyidh = '<';
4076#else /* not IBMR2AIX */
4077 keymap.hfkey[1].hf_page = '<';
4078#endif /* not IBMR2AIX */
4079 keymap.hfkey[1].hf_char = 8;
4080 hftctl (0, HFSKBD, &buf);
4081}
4082
4083#endif /* AIX */