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