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