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