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