159812Shibler /* Interfaces to system-dependent kernel and library entries.
259812Shibler    Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
359812Shibler 
459812Shibler This file is part of GNU Emacs.
559812Shibler 
659812Shibler GNU Emacs is free software; you can redistribute it and/or modify
759812Shibler it under the terms of the GNU General Public License as published by
859812Shibler the Free Software Foundation; either version 1, or (at your option)
959812Shibler any later version.
1059812Shibler 
1159812Shibler GNU Emacs is distributed in the hope that it will be useful,
1259812Shibler but WITHOUT ANY WARRANTY; without even the implied warranty of
1359812Shibler MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1459812Shibler GNU General Public License for more details.
1559812Shibler 
1659812Shibler You should have received a copy of the GNU General Public License
1759812Shibler along with GNU Emacs; see the file COPYING.  If not, write to
1859812Shibler the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
1959812Shibler 
2059812Shibler 
2159812Shibler #include <signal.h>
2259812Shibler #include <setjmp.h>
2359812Shibler 
2459812Shibler #include "config.h"
2559812Shibler #include "lisp.h"
2659812Shibler #undef NULL
2759812Shibler 
2859812Shibler #define min(x,y) ((x) > (y) ? (y) : (x))
2959812Shibler 
3059812Shibler /* In this file, open, read and write refer to the system calls,
3159812Shibler    not our sugared interfaces  sys_open, sys_read and sys_write.
3259812Shibler    Contrariwise, for systems where we use the system calls directly,
3359812Shibler    define sys_read, etc. here as aliases for them.  */
3459812Shibler #ifndef read
3559812Shibler #define sys_read read
3659812Shibler #define sys_write write
3759812Shibler #endif /* `read' is not a macro */
3859812Shibler 
3959812Shibler #undef read
4059812Shibler #undef write
4159812Shibler 
4259812Shibler #ifndef close
4359812Shibler #define sys_close close
4459812Shibler #else
4559812Shibler #undef close
4659812Shibler #endif
4759812Shibler 
4859812Shibler #ifndef open
4959812Shibler #define sys_open open
5059812Shibler #else /* `open' is a macro */
5159812Shibler #undef open
5259812Shibler #endif /* `open' is a macro */
5359812Shibler 
5459812Shibler #include <stdio.h>
5559812Shibler #include <sys/types.h>
5659812Shibler #include <sys/stat.h>
5759812Shibler #include <errno.h>
5859812Shibler 
5959812Shibler extern int errno;
6059812Shibler #ifndef VMS
61*60297Shibler #ifndef BSD4_4
6259812Shibler extern char *sys_errlist[];
6359812Shibler #endif
64*60297Shibler #endif
6559812Shibler 
6659812Shibler #ifdef VMS
6759812Shibler #include <rms.h>
6859812Shibler #include <ttdef.h>
6959812Shibler #include <tt2def.h>
7059812Shibler #include <iodef.h>
7159812Shibler #include <ssdef.h>
7259812Shibler #include <descrip.h>
7359812Shibler #include <ctype.h>
7459812Shibler #include <file.h>
7559812Shibler #ifndef RAB$C_BID
7659812Shibler #include <rab.h>
7759812Shibler #endif
7859812Shibler #define	MAXIOSIZE ( 32 * PAGESIZE )	/* Don't I/O more than 32 blocks at a time */
7959812Shibler #endif /* VMS */
8059812Shibler 
8159812Shibler #ifndef BSD4_1
8259812Shibler #ifdef BSD /* this is done this way to avoid defined(BSD) || defined (USG)
8359812Shibler 	      because the vms compiler doesn't grok `defined' */
8459812Shibler #include <fcntl.h>
8559812Shibler #endif
8659812Shibler #ifdef USG
8759812Shibler #include <fcntl.h>
8859812Shibler #endif
8959812Shibler #endif /* not 4.1 bsd */
9059812Shibler 
9159812Shibler #ifdef BSD
9259812Shibler #include <sys/ioctl.h>
9359812Shibler #ifdef BSD4_1
9459812Shibler #include <wait.h>
9559812Shibler #else /* not 4.1 */
9659812Shibler #include <sys/wait.h>
9759812Shibler #endif /* not 4.1 */
9859812Shibler #endif /* BSD */
9959812Shibler 
10059812Shibler #ifdef STRIDE
10159812Shibler #include <sys/ioctl.h>
10259812Shibler #endif
10359812Shibler 
10459812Shibler #ifdef mips
10559812Shibler #include <sys/ioctl.h>
10659812Shibler #endif
10759812Shibler 
10859812Shibler #ifdef AIX
10959812Shibler /* Get files for keyboard remapping */
11059812Shibler #define HFNKEYS 2
11159812Shibler #include <sys/hft.h>
11259812Shibler #include <sys/devinfo.h>
11359812Shibler #endif
11459812Shibler 
11559812Shibler /* Get rid of LLITOUT in 4.1, since it is said to stimulate kernel bugs.  */
11659812Shibler #ifdef BSD4_1
11759812Shibler #undef LLITOUT
11859812Shibler #define LLITOUT 0
11959812Shibler #endif /* 4.1 */
12059812Shibler 
12159812Shibler #ifdef HAVE_TERMIO
12259812Shibler #ifdef IBMR2AIX
12359812Shibler #include <termio.h>
12459812Shibler #include <termios.h>
12559812Shibler #ifdef TIOCGETP
12659812Shibler #undef TIOCGETP
12759812Shibler #endif
12859812Shibler #define TIOCGETP TCGETS
12959812Shibler #undef TIOCSETN
13059812Shibler #define TIOCSETN TCSETSW
13159812Shibler #undef TIOCSETP
13259812Shibler #define TIOCSETP TCSETSF
13359812Shibler #undef TCSETAW
13459812Shibler #define TCSETAW TCSETS
13559812Shibler #else
13659812Shibler #include <termio.h>
13759812Shibler #undef TIOCGETP
13859812Shibler #define TIOCGETP TCGETA
13959812Shibler #undef TIOCSETN
14059812Shibler #define TIOCSETN TCSETAW
14159812Shibler #undef TIOCSETP
14259812Shibler #define TIOCSETP TCSETAF
14359812Shibler #endif
14459812Shibler 
14559812Shibler #ifndef IBMR2AIX
14659812Shibler #define TERMINAL struct termio
14759812Shibler #else
14859812Shibler #define TERMINAL struct termios
14959812Shibler #endif
15059812Shibler 
15159812Shibler #define OSPEED(str) (str.c_cflag & CBAUD)
15259812Shibler #define SETOSPEED(str,new) (str.c_cflag = (str.c_cflag & ~CBAUD) | (new))
15359812Shibler #define TABS_OK(str) ((str.c_oflag & TABDLY) != TAB3)
15459812Shibler #endif /* HAVE_TERMIO */
15559812Shibler 
15659812Shibler #ifdef XENIX
15759812Shibler #undef TIOCGETC  /* Avoid confusing some conditionals that test this.  */
15859812Shibler #endif
15959812Shibler 
16059812Shibler #ifdef BROKEN_TIOCGETC
16159812Shibler #undef TIOCGETC
16259812Shibler #endif
16359812Shibler 
16459812Shibler #ifndef HAVE_TERMIO
16559812Shibler #ifndef VMS
16659812Shibler #include <sgtty.h>
16759812Shibler #define TERMINAL struct sgttyb
16859812Shibler #define OSPEED(str) str.sg_ospeed
16959812Shibler #define SETOSPEED(str,new) (str.sg_ospeed = (new))
17059812Shibler #define TABS_OK(str) ((str.sg_flags & XTABS) != XTABS)
17159812Shibler #undef TCSETAW
17259812Shibler #define TCSETAW TIOCSETN
17359812Shibler #endif /* not VMS */
17459812Shibler #endif /* not HAVE_TERMIO */
17559812Shibler 
17659812Shibler #ifdef USG
17759812Shibler #include <sys/utsname.h>
17859812Shibler #include <memory.h>
17959812Shibler #include <string.h>
18059812Shibler #ifdef TIOCGWINSZ
18159812Shibler #ifndef IRIS_4D
18259812Shibler #ifndef mips
18359812Shibler #ifndef aix386
18459812Shibler #ifndef NO_SIOCTL_H
18559812Shibler /* Some USG systems with TIOCGWINSZ need this file; some don't have it.
18659812Shibler    We don't know how to distinguish them.
18759812Shibler    If this #include gets an error, just delete it.  */
18859812Shibler #include <sys/sioctl.h>
18959812Shibler #endif
19059812Shibler #ifdef NEED_PTEM_H
19159812Shibler #include <sys/stream.h>
19259812Shibler #include <sys/ptem.h>
19359812Shibler #endif
19459812Shibler #endif /* not aix386 */
19559812Shibler #endif /* not mips */
19659812Shibler #endif /* not IRIS_4D */
19759812Shibler #endif /* TIOCGWINSZ */
19859812Shibler #ifdef HAVE_TIMEVAL
19959812Shibler #ifdef HPUX
20059812Shibler #include <time.h>
20159812Shibler #else
20259812Shibler #include <sys/time.h>
20359812Shibler #endif
20459812Shibler #endif /* HAVE_TIMEVAL */
20559812Shibler #endif /* USG */
20659812Shibler 
20759812Shibler #ifdef VMS
20859812Shibler #include "window.h"
20959812Shibler #endif
21059812Shibler 
21159812Shibler #ifdef NEED_BSDTTY
21259812Shibler #include <sys/bsdtty.h>
21359812Shibler #endif
21459812Shibler 
21559812Shibler #if defined (HPUX) && defined (HAVE_PTYS)
21659812Shibler #include <sys/ptyio.h>
21759812Shibler #endif
21859812Shibler 
21959812Shibler #ifdef AIX
22059812Shibler #include <sys/pty.h>
22159812Shibler #include <unistd.h>
22259812Shibler #endif /* AIX */
22359812Shibler 
22459812Shibler #ifdef SYSV_PTYS
22559812Shibler #include <sys/tty.h>
22659812Shibler #include <sys/pty.h>
22759812Shibler #endif
22859812Shibler 
22959812Shibler #ifdef BROKEN_FIONREAD
23059812Shibler #undef FIONREAD
23159812Shibler #endif
23259812Shibler 
23359812Shibler extern int quit_char;
23459812Shibler 
23559812Shibler #include "termhooks.h"
23659812Shibler #include "termchar.h"
23759812Shibler #include "termopts.h"
23859812Shibler #include "dispextern.h"
23959812Shibler 
24059812Shibler #ifdef NONSYSTEM_DIR_LIBRARY
24159812Shibler #include "ndir.h"
24259812Shibler #endif /* NONSYSTEM_DIR_LIBRARY */
24359812Shibler 
24459812Shibler #ifndef sigmask
24559812Shibler #define sigmask(no) (1L << ((no) - 1))
24659812Shibler #endif
24759812Shibler 
24859812Shibler /* Define SIGCHLD as an alias for SIGCLD.  There are many conditionals
24959812Shibler    testing SIGCHLD.  */
25059812Shibler 
25159812Shibler #ifndef VMS
25259812Shibler #ifdef SIGCLD
25359812Shibler #ifndef SIGCHLD
25459812Shibler #define SIGCHLD SIGCLD
25559812Shibler #endif /* not SIGCHLD */
25659812Shibler #endif /* SIGCLD */
25759812Shibler #endif /* not VMS */
25859812Shibler 
25959812Shibler static int baud_convert[] =
26059812Shibler #ifdef BAUD_CONVERT
26159812Shibler   BAUD_CONVERT;
26259812Shibler #else
26359812Shibler   {
26459812Shibler     0, 50, 75, 110, 135, 150, 200, 300, 600, 1200,
26559812Shibler     1800, 2400, 4800, 9600, 19200, 38400
26659812Shibler   };
26759812Shibler #endif
26859812Shibler 
26959812Shibler extern short ospeed;
27059812Shibler 
27159812Shibler #ifdef VMS
27259812Shibler static struct iosb
27359812Shibler {
27459812Shibler   short status;
27559812Shibler   short offset;
27659812Shibler   short termlen;
27759812Shibler   short term;
27859812Shibler } input_iosb;
27959812Shibler 
28059812Shibler int kbd_input_ast ();
28159812Shibler 
28259812Shibler int waiting_for_ast;
28359812Shibler int stop_input;
28459812Shibler int input_ef = 0;
28559812Shibler int timer_ef = 0;
28659812Shibler int process_ef = 0;
28759812Shibler int input_eflist;
28859812Shibler int timer_eflist;
28959812Shibler 
29059812Shibler static int input_chan;
29159812Shibler static $DESCRIPTOR (input_dsc, "TT");
29259812Shibler static int terminator_mask[2] = { 0, 0 };
29359812Shibler 
29459812Shibler static struct sensemode {
29559812Shibler   short status;
29659812Shibler   unsigned char xmit_baud;
29759812Shibler   unsigned char rcv_baud;
29859812Shibler   unsigned char crfill;
29959812Shibler   unsigned char lffill;
30059812Shibler   unsigned char parity;
30159812Shibler   unsigned char unused;
30259812Shibler   char class;
30359812Shibler   char type;
30459812Shibler   short scr_wid;
30559812Shibler   unsigned long tt_char : 24, scr_len : 8;
30659812Shibler   unsigned long tt2_char;
30759812Shibler } sensemode_iosb;
30859812Shibler #define TERMINAL struct sensemode
30959812Shibler #define OSPEED(str) (str.xmit_baud)
31059812Shibler #define TABS_OK(str) ((str.tt_char & TT$M_MECHTAB) != 0)
31159812Shibler #endif /* VMS */
31259812Shibler 
31359812Shibler discard_tty_input ()
31459812Shibler {
31559812Shibler   TERMINAL buf;
31659812Shibler 
31759812Shibler   if (noninteractive)
31859812Shibler     return;
31959812Shibler 
32059812Shibler #ifdef VMS
32159812Shibler   end_kbd_input ();
32259812Shibler   SYS$QIOW (0, input_chan, IO$_READVBLK|IO$M_PURGE, input_iosb, 0, 0,
32359812Shibler 	    &buf, 0, 0, terminator_mask, 0, 0);
32459812Shibler   queue_kbd_input ();
32559812Shibler #else /* not VMS */
32659812Shibler   ioctl (0, TIOCGETP, &buf);
32759812Shibler   ioctl (0, TIOCSETP, &buf);
32859812Shibler #endif /* not VMS */
32959812Shibler }
33059812Shibler 
33159812Shibler #ifdef SIGTSTP
33259812Shibler 
33359812Shibler stuff_char (c)
33459812Shibler      char c;
33559812Shibler {
33659812Shibler /* Should perhaps error if in batch mode */
33759812Shibler #ifdef TIOCSTI
33859812Shibler   ioctl (0, TIOCSTI, &c);
33959812Shibler #else /* no TIOCSTI */
34059812Shibler   error ("Cannot stuff terminal input characters in this version of Unix.");
34159812Shibler #endif /* no TIOCSTI */
34259812Shibler }
34359812Shibler 
34459812Shibler #endif /* SIGTSTP */
34559812Shibler 
34659812Shibler init_baud_rate ()
34759812Shibler {
34859812Shibler   TERMINAL sg;
34959812Shibler 
35059812Shibler   if (noninteractive)
35159812Shibler     ospeed = 0;
35259812Shibler   else
35359812Shibler     {
35459812Shibler #ifdef VMS
35559812Shibler       SYS$QIOW (0, input_chan, IO$_SENSEMODE, &sg, 0, 0,
35659812Shibler 		&sg.class, 12, 0, 0, 0, 0 );
35759812Shibler #else
35859812Shibler       SETOSPEED (sg, B9600);
35959812Shibler       ioctl (0, TIOCGETP, &sg);
36059812Shibler #endif /* not VMS */
36159812Shibler       ospeed = OSPEED (sg);
36259812Shibler     }
36359812Shibler 
36459812Shibler   baud_rate = (ospeed < sizeof baud_convert / sizeof baud_convert[0]
36559812Shibler 	       ? baud_convert[ospeed] : 9600);
36659812Shibler   if (baud_rate == 0)
36759812Shibler     baud_rate = 1200;
36859812Shibler }
36959812Shibler 
37059812Shibler /*ARGSUSED*/
37159812Shibler set_exclusive_use (fd)
37259812Shibler      int fd;
37359812Shibler {
37459812Shibler #ifdef FIOCLEX
37559812Shibler   ioctl (fd, FIOCLEX, 0);
37659812Shibler #endif
37759812Shibler   /* Ok to do nothing if this feature does not exist */
37859812Shibler }
37959812Shibler 
38059812Shibler #ifndef subprocesses
38159812Shibler 
38259812Shibler wait_without_blocking ()
38359812Shibler {
38459812Shibler #ifdef BSD
38559812Shibler   wait3 (0, WNOHANG | WUNTRACED, 0);
38659812Shibler #else
38759812Shibler   croak ("wait_without_blocking");
38859812Shibler #endif
38959812Shibler }
39059812Shibler 
39159812Shibler #endif /* not subprocesses */
39259812Shibler 
39359812Shibler int wait_debugging;   /* Set nonzero to make following function work under dbx
39459812Shibler 		         (at least for bsd).  */
39559812Shibler 
39659812Shibler /* Wait for subprocess with process id `pid' to terminate and
39759812Shibler    make sure it will get eliminated (not remain forever as a zombie) */
39859812Shibler 
39959812Shibler wait_for_termination (pid)
40059812Shibler      int pid;
40159812Shibler {
40259812Shibler   while (1)
40359812Shibler     {
40459812Shibler #ifdef subprocesses
40559812Shibler #if defined(BSD) || (defined(HPUX) && !defined(HPUX_5))
40659812Shibler       /* Note that kill returns -1 even if the process is just a zombie now.
40759812Shibler 	 But inevitably a SIGCHLD interrupt should be generated
40859812Shibler 	 and child_sig will do wait3 and make the process go away. */
40959812Shibler       /* There is some indication that there is a bug involved with
41059812Shibler 	 termination of subprocesses, perhaps involving a kernel bug too,
41159812Shibler 	 but no idea what it is.  Just as a hunch we signal SIGCHLD to see
41259812Shibler 	 if that causes the problem to go away or get worse.  */
41359812Shibler #ifdef BSD4_1
41459812Shibler       extern int synch_process_pid;
41559812Shibler       sighold (SIGCHLD);
41659812Shibler       if (synch_process_pid == 0)
41759812Shibler 	{
41859812Shibler           sigrelse (SIGCHLD);
41959812Shibler 	  break;
42059812Shibler 	}
42159812Shibler       if (wait_debugging)
42259812Shibler 	sleep (1);
42359812Shibler       else
42459812Shibler 	sigpause (SIGCHLD);
42559812Shibler #else /* not BSD4_1 */
42659812Shibler       sigsetmask (1 << (SIGCHLD - 1));
42759812Shibler       if (0 > kill (pid, 0))
42859812Shibler         {
42959812Shibler 	  sigsetmask (0);
43059812Shibler 	  kill (getpid (), SIGCHLD);
43159812Shibler 	  break;
43259812Shibler 	}
43359812Shibler       if (wait_debugging)
43459812Shibler 	sleep (1);
43559812Shibler       else
43659812Shibler 	sigpause (0);
43759812Shibler #endif /* not BSD4_1 */
43859812Shibler #else /* not BSD, and not HPUX version >= 6 */
43959812Shibler #ifdef UNIPLUS
44059812Shibler       if (0 > kill (pid, 0))
44159812Shibler 	break;
44259812Shibler       wait (0);
44359812Shibler #else /* neither BSD nor UNIPLUS: random sysV */
44459812Shibler       if (0 > kill (pid, 0))
44559812Shibler 	break;
44659812Shibler       pause ();
44759812Shibler #endif /* not UNIPLUS */
44859812Shibler #endif /* not BSD, and not HPUX version >= 6 */
44959812Shibler #else /* not subprocesses */
45059812Shibler #ifndef BSD4_1
45159812Shibler       if (0 > kill (pid, 0))
45259812Shibler 	break;
45359812Shibler       wait (0);
45459812Shibler #else /* BSD4_1 */
45559812Shibler       int status;
45659812Shibler       status = wait (0);
45759812Shibler       if (status == pid || status == -1)
45859812Shibler 	break;
45959812Shibler #endif /* BSD4_1 */
46059812Shibler #endif /* not subprocesses */
46159812Shibler     }
46259812Shibler }
46359812Shibler 
46459812Shibler #ifdef subprocesses
46559812Shibler 
46659812Shibler /*
46759812Shibler  *	flush any pending output
46859812Shibler  *      (may flush input as well; it does not matter the way we use it)
46959812Shibler  */
47059812Shibler 
47159812Shibler flush_pending_output (channel)
47259812Shibler      int channel;
47359812Shibler {
47459812Shibler #ifdef TCFLSH
47559812Shibler   ioctl (channel, TCFLSH, 1);
47659812Shibler #else
47759812Shibler #ifdef TIOCFLUSH
47859812Shibler   int zero = 0;
47959812Shibler   /* 3rd arg should be ignored
48059812Shibler      but some 4.2 kernels actually want the address of an int
48159812Shibler      and nonzero means something different.  */
48259812Shibler   ioctl (channel, TIOCFLUSH, &zero);
48359812Shibler #endif
48459812Shibler #endif
48559812Shibler }
48659812Shibler 
48759812Shibler /*  Set up the terminal at the other end of a pseudo-terminal that
48859812Shibler     we will be controlling an inferior through.
48959812Shibler     It should not echo or do line-editing, since that is done
49059812Shibler     in Emacs.  No padding needed for insertion into an Emacs buffer.  */
49159812Shibler 
49259812Shibler child_setup_tty (out)
49359812Shibler      int out;
49459812Shibler {
49559812Shibler   TERMINAL s;
49659812Shibler 
49759812Shibler   ioctl (out, TIOCGETP, &s);
49859812Shibler #ifdef HAVE_TERMIO
49959812Shibler   s.c_oflag |= OPOST;		/* Enable output postprocessing */
50059812Shibler   s.c_oflag &= ~ONLCR;		/* Disable map of NL to CR-NL on output */
50159812Shibler   s.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);	/* No output delays */
50259812Shibler   s.c_lflag &= ~ECHO;		/* Disable echo */
50359812Shibler   s.c_lflag |= ISIG;		/* Enable signals */
50459812Shibler   s.c_iflag &= ~IUCLC;		/* Disable map of upper case to lower on input */
50559812Shibler   s.c_oflag &= ~OLCUC;		/* Disable map of lower case to upper on output */
50659812Shibler /* said to be unnecesary
50759812Shibler   s.c_cc[VMIN] = 1;		/* minimum number of characters to accept
50859812Shibler   s.c_cc[VTIME] = 0;		/* wait forever for at least 1 character
50959812Shibler */
51059812Shibler   s.c_lflag |= ICANON;		/* Enable erase/kill and eof processing */
51159812Shibler   s.c_cc[VEOF] = 04;		/* insure that EOF is Control-D */
51259812Shibler   s.c_cc[VERASE] = 0377;	/* disable erase processing */
51359812Shibler   s.c_cc[VKILL] = 0377;		/* disable kill processing */
51459812Shibler #ifdef HPUX
51559812Shibler   s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
51659812Shibler #endif HPUX
51759812Shibler 
51859812Shibler #ifdef AIX
51959812Shibler /* AIX enhanced edit loses NULs, so disable it */
52059812Shibler #ifndef IBMR2AIX
52159812Shibler   s.c_line = 0;
52259812Shibler   s.c_iflag &= ~ASCEDIT;
52359812Shibler #endif
52459812Shibler   /* Also, PTY overloads NUL and BREAK.
52559812Shibler      don't ignore break, but don't signal either, so it looks like NUL.  */
52659812Shibler   s.c_iflag &= ~IGNBRK;
52759812Shibler   s.c_iflag &= ~BRKINT;
52859812Shibler /* QUIT and INTR work better as signals, so disable character forms */
52959812Shibler   s.c_cc[VQUIT] = 0377;
53059812Shibler   s.c_cc[VINTR] = 0377;
53159812Shibler   s.c_cc[VEOL] = 0377;
53259812Shibler   s.c_lflag &= ~ISIG;
53359812Shibler   s.c_cflag = (s.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
53459812Shibler #endif /* AIX */
53559812Shibler 
53659812Shibler #else /* not HAVE_TERMIO */
53759812Shibler   s.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM);
53859812Shibler #endif /* not HAVE_TERMIO */
53959812Shibler 
54059812Shibler   ioctl (out, TIOCSETN, &s);
54159812Shibler 
54259812Shibler #ifdef BSD4_1
54359812Shibler   if (interrupt_input)
54459812Shibler     reset_sigio ();
54559812Shibler #endif /* BSD4_1 */
54659812Shibler #ifdef RTU
54759812Shibler   {
54859812Shibler     int zero = 0;
54959812Shibler     ioctl (out, FIOASYNC, &zero);
55059812Shibler   }
55159812Shibler #endif /* RTU */
55259812Shibler }
55359812Shibler 
55459812Shibler #endif /* subprocesses */
55559812Shibler 
55659812Shibler /*ARGSUSED*/
55759812Shibler setpgrp_of_tty (pid)
55859812Shibler      int pid;
55959812Shibler {
56059812Shibler #ifdef IBMR2AIX
56159812Shibler   tcsetpgrp ( 0, pid);
56259812Shibler #else
56359812Shibler #ifdef TIOCSPGRP
56459812Shibler   ioctl (0, TIOCSPGRP, &pid);
56559812Shibler #else
56659812Shibler   /* Just ignore this for now and hope for the best */
56759812Shibler #endif
56859812Shibler #endif
56959812Shibler }
57059812Shibler 
57159812Shibler /* Record a signal code and the handler for it.  */
57259812Shibler struct save_signal
57359812Shibler {
57459812Shibler   int code;
57559812Shibler   int (*handler) ();
57659812Shibler };
57759812Shibler 
57859812Shibler /* Suspend the Emacs process; give terminal to its superior.  */
57959812Shibler 
58059812Shibler sys_suspend ()
58159812Shibler {
58259812Shibler #ifdef VMS
58359812Shibler   unsigned long parent_id;
58459812Shibler 
58559812Shibler   parent_id = getppid ();
58659812Shibler   if (parent_id && parent_id != 0xffffffff)
58759812Shibler     {
58859812Shibler       int oldsig = signal (SIGINT, SIG_IGN);
58959812Shibler       int status = LIB$ATTACH (&parent_id) & 1;
59059812Shibler       signal (SIGINT, oldsig);
59159812Shibler       return status;
59259812Shibler     }
59359812Shibler   return -1;
59459812Shibler #else
59559812Shibler #ifdef SIGTSTP
59659812Shibler #ifdef BSD
59759812Shibler   killpg (getpgrp (0), SIGTSTP);
59859812Shibler #else
59959812Shibler   kill (-getpgrp (0), SIGTSTP);
60059812Shibler #endif
60159812Shibler 
60259812Shibler #else
60359812Shibler #ifdef USG_JOBCTRL /* If you don't know what this is don't mess with it */
60459812Shibler   ptrace (0, 0, 0, 0);		/* set for ptrace - caught by csh */
60559812Shibler   kill (getpid (), SIGQUIT);
60659812Shibler 
60759812Shibler #else
60859812Shibler 
60959812Shibler /* On a system where suspending is not implemented,
61059812Shibler    instead fork a subshell and let it talk directly to the terminal
61159812Shibler    while we wait.  */
61259812Shibler   int pid = fork ();
61359812Shibler   struct save_signal saved_handlers[5];
61459812Shibler 
61559812Shibler   saved_handlers[0].code = SIGINT;
61659812Shibler   saved_handlers[1].code = SIGQUIT;
61759812Shibler   saved_handlers[2].code = SIGTERM;
61859812Shibler #ifdef SIGIO
61959812Shibler   saved_handlers[3].code = SIGIO;
62059812Shibler   saved_handlers[4].code = 0;
62159812Shibler #else
62259812Shibler   saved_handlers[3].code = 0;
62359812Shibler #endif
62459812Shibler 
62559812Shibler   if (pid == -1)
62659812Shibler     error ("Can't spawn subshell");
62759812Shibler   if (pid == 0)
62859812Shibler     {
62959812Shibler       char *sh;
63059812Shibler 
63159812Shibler       sh = (char *) egetenv ("SHELL");
63259812Shibler       if (sh == 0)
63359812Shibler 	sh = "sh";
63459812Shibler       /* Use our buffer's default directory for the subshell.  */
63559812Shibler       {
63659812Shibler 	Lisp_Object dir;
63759812Shibler 	unsigned char *str;
63859812Shibler 	int len;
63959812Shibler 
64059812Shibler 	/* mentioning current_buffer->buffer would mean including buffer.h,
64159812Shibler 	   which somehow wedges the hp compiler.  So instead... */
64259812Shibler 
64359812Shibler 	dir = intern ("default-directory");
64459812Shibler 	/* Can't use NULL */
64559812Shibler 	if (XFASTINT (Fboundp (dir)) == XFASTINT (Qnil))
64659812Shibler 	  goto xyzzy;
64759812Shibler 	dir = Fsymbol_value (dir);
64859812Shibler 	if (XTYPE (dir) != Lisp_String)
64959812Shibler 	  goto xyzzy;
65059812Shibler 
65159812Shibler 	str = (unsigned char *) alloca (XSTRING (dir)->size + 2);
65259812Shibler 	len = XSTRING (dir)->size;
65359812Shibler 	bcopy (XSTRING (dir)->data, str, len);
65459812Shibler 	if (str[len - 1] != '/') str[len++] = '/';
65559812Shibler 	str[len] = 0;
65659812Shibler 	chdir (str);
65759812Shibler       }
65859812Shibler     xyzzy:
65959812Shibler #ifdef subprocesses
66059812Shibler       close_process_descs ();	/* Close Emacs's pipes/ptys */
66159812Shibler #endif
66259812Shibler       execlp (sh, sh, 0);
66359812Shibler       write (1, "Can't execute subshell", 22);
66459812Shibler       _exit (1);
66559812Shibler     }
66659812Shibler   save_signal_handlers (&saved_handlers);
66759812Shibler   wait_for_termination (pid);
66859812Shibler   restore_signal_handlers (&saved_handlers);
66959812Shibler #endif /* no USG_JOBCTRL */
67059812Shibler #endif /* no SIGTSTP */
67159812Shibler #endif /* not VMS */
67259812Shibler }
67359812Shibler 
67459812Shibler save_signal_handlers (saved_handlers)
67559812Shibler      struct save_signal *saved_handlers;
67659812Shibler {
67759812Shibler   while (saved_handlers->code)
67859812Shibler     {
67959812Shibler       saved_handlers->handler
68059812Shibler 	= (int (*) ()) signal (saved_handlers->code, SIG_IGN);
68159812Shibler       saved_handlers++;
68259812Shibler     }
68359812Shibler }
68459812Shibler 
68559812Shibler restore_signal_handlers (saved_handlers)
68659812Shibler      struct save_signal *saved_handlers;
68759812Shibler {
68859812Shibler   while (saved_handlers->code)
68959812Shibler     {
69059812Shibler       signal (saved_handlers->code, saved_handlers->handler);
69159812Shibler       saved_handlers++;
69259812Shibler     }
69359812Shibler }
69459812Shibler 
69559812Shibler #ifdef F_SETFL
69659812Shibler 
69759812Shibler int old_fcntl_flags;
69859812Shibler 
69959812Shibler init_sigio ()
70059812Shibler {
70159812Shibler #ifdef FASYNC
70259812Shibler   old_fcntl_flags = fcntl (0, F_GETFL, 0) & ~FASYNC;
70359812Shibler #endif
70459812Shibler   request_sigio ();
70559812Shibler }
70659812Shibler 
70759812Shibler reset_sigio ()
70859812Shibler {
70959812Shibler   unrequest_sigio ();
71059812Shibler }
71159812Shibler 
71259812Shibler #ifdef FASYNC		/* F_SETFL does not imply existance of FASYNC */
71359812Shibler 
71459812Shibler request_sigio ()
71559812Shibler {
71659812Shibler #ifdef SIGWINCH
71759812Shibler   int omask = sigblock (0);
71859812Shibler   sigsetmask (omask & ~sigmask (SIGWINCH));
71959812Shibler #endif
72059812Shibler   fcntl (0, F_SETFL, old_fcntl_flags | FASYNC);
72159812Shibler 
72259812Shibler   interrupts_deferred = 0;
72359812Shibler }
72459812Shibler 
72559812Shibler unrequest_sigio ()
72659812Shibler {
72759812Shibler #ifdef SIGWINCH
72859812Shibler   sigblock (sigmask (SIGWINCH));
72959812Shibler #endif
73059812Shibler   fcntl (0, F_SETFL, old_fcntl_flags);
73159812Shibler   interrupts_deferred = 1;
73259812Shibler }
73359812Shibler 
73459812Shibler #else /* no FASYNC */
73559812Shibler #ifdef STRIDE		/* Stride doesn't have FASYNC - use FIOASYNC */
73659812Shibler 
73759812Shibler request_sigio ()
73859812Shibler {
73959812Shibler   int on = 1;
74059812Shibler   ioctl (0, FIOASYNC, &on);
74159812Shibler   interrupts_deferred = 0;
74259812Shibler }
74359812Shibler 
74459812Shibler unrequest_sigio ()
74559812Shibler {
74659812Shibler   int off = 0;
74759812Shibler 
74859812Shibler   ioctl (0, FIOASYNC, &off);
74959812Shibler   interrupts_deferred = 1;
75059812Shibler }
75159812Shibler 
75259812Shibler #else /* not FASYNC, not STRIDE */
75359812Shibler 
75459812Shibler request_sigio ()
75559812Shibler {
75659812Shibler   croak ("request_sigio");
75759812Shibler }
75859812Shibler 
75959812Shibler unrequest_sigio ()
76059812Shibler {
76159812Shibler   croak ("unrequest_sigio");
76259812Shibler }
76359812Shibler 
76459812Shibler #endif /* STRIDE */
76559812Shibler #endif /* FASYNC */
76659812Shibler #endif /* F_SETFL */
76759812Shibler 
76859812Shibler TERMINAL old_gtty;		/* The initial tty mode bits */
76959812Shibler 
77059812Shibler int term_initted;		/* 1 if outer tty status has been recorded */
77159812Shibler 
77259812Shibler #ifdef F_SETOWN
77359812Shibler int old_fcntl_owner;
77459812Shibler #endif /* F_SETOWN */
77559812Shibler 
77659812Shibler #ifdef TIOCGLTC
77759812Shibler struct ltchars old_ltchars;
77859812Shibler #endif /* TIOCGLTC */
77959812Shibler 
78059812Shibler #ifdef TIOCGETC
78159812Shibler struct tchars old_tchars;
78259812Shibler int old_lmode;
78359812Shibler 
78459812Shibler int lmode;			/* Current lmode value. */
78559812Shibler 				/* Needed as global for 4.1 */
78659812Shibler #endif /* TIOCGETC */
78759812Shibler 
78859812Shibler /* This may also be defined in stdio,
78959812Shibler    but if so, this does no harm,
79059812Shibler    and using the same name avoids wasting the other one's space.  */
79159812Shibler 
79259812Shibler #ifdef USG
79359812Shibler unsigned char _sobuf[BUFSIZ+8];
79459812Shibler #else
79559812Shibler char _sobuf[BUFSIZ];
79659812Shibler #endif
79759812Shibler 
79859812Shibler #ifdef TIOCGLTC
79959812Shibler static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1};
80059812Shibler #endif
80159812Shibler #ifdef TIOCGETC
80259812Shibler   static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1};
80359812Shibler #endif
80459812Shibler 
80559812Shibler init_sys_modes ()
80659812Shibler {
80759812Shibler   TERMINAL tty;
80859812Shibler #ifdef TIOCGETC
80959812Shibler   struct tchars tchars;
81059812Shibler #endif
81159812Shibler #ifdef VMS
81259812Shibler #if 0
81359812Shibler   static int oob_chars[2] = {0, 1 << 7}; /* catch C-g's */
81459812Shibler   extern int (*interrupt_signal) ();
81559812Shibler #endif
81659812Shibler #endif
81759812Shibler 
81859812Shibler   if (noninteractive)
81959812Shibler     return;
82059812Shibler 
82159812Shibler #ifdef VMS
82259812Shibler   if (!input_ef)
82359812Shibler     LIB$GET_EF (&input_ef);
82459812Shibler   SYS$CLREF (input_ef);
82559812Shibler   waiting_for_ast = 0;
82659812Shibler   if (!timer_ef)
82759812Shibler     LIB$GET_EF (&timer_ef);
82859812Shibler   SYS$CLREF (timer_ef);
82959812Shibler   if (!process_ef)
83059812Shibler     {
83159812Shibler       LIB$GET_EF (&process_ef);
83259812Shibler       SYS$CLREF (process_ef);
83359812Shibler     }
83459812Shibler   if (input_ef / 32 != process_ef / 32)
83559812Shibler     croak ("Input and process event flags in different clusters.");
83659812Shibler   if (input_ef / 32 != timer_ef / 32)
83759812Shibler     croak ("Input and process event flags in different clusters.");
83859812Shibler   input_eflist = ((unsigned) 1 << (input_ef % 32)) |
83959812Shibler     ((unsigned) 1 << (process_ef % 32));
84059812Shibler   timer_eflist = ((unsigned) 1 << (input_ef % 32)) |
84159812Shibler     ((unsigned) 1 << (timer_ef % 32));
84259812Shibler   SYS$QIOW (0, input_chan, IO$_SENSEMODE, &old_gtty, 0, 0,
84359812Shibler 	    &old_gtty.class, 12, 0, 0, 0, 0);
84459812Shibler #ifndef VMS4_4
84559812Shibler   sys_access_reinit ();
84659812Shibler #endif
84759812Shibler #else /* not VMS */
84859812Shibler   ioctl (0, TIOCGETP, &old_gtty);
84959812Shibler #endif /* not VMS */
85059812Shibler   if (!read_socket_hook)
85159812Shibler     {
85259812Shibler       tty = old_gtty;
85359812Shibler 
85459812Shibler #ifdef HAVE_TERMIO
85559812Shibler       tty.c_iflag |= (IGNBRK);	/* Ignore break condition */
85659812Shibler       tty.c_iflag &= ~ICRNL;	/* Disable map of CR to NL on input */
85759812Shibler #ifdef ISTRIP
85859812Shibler       tty.c_iflag &= ~ISTRIP;	/* don't strip 8th bit on input */
85959812Shibler #endif
86059812Shibler       tty.c_lflag &= ~ECHO;	/* Disable echo */
86159812Shibler       tty.c_lflag &= ~ICANON;	/* Disable erase/kill processing */
86259812Shibler       tty.c_lflag |= ISIG;	/* Enable signals */
86359812Shibler       if (flow_control)
86459812Shibler 	{
86559812Shibler 	  tty.c_iflag |= IXON;	/* Enable start/stop output control */
86659812Shibler #ifdef IXANY
86759812Shibler 	  tty.c_iflag &= ~IXANY;
86859812Shibler #endif /* IXANY */
86959812Shibler 	}
87059812Shibler       else
87159812Shibler 	tty.c_iflag &= ~IXON;	/* Disable start/stop output control */
87259812Shibler       tty.c_oflag &= ~ONLCR;	/* Disable map of NL to CR-NL on output */
87359812Shibler       tty.c_oflag &= ~TAB3;	/* Disable tab expansion */
87459812Shibler #ifdef CS8
87559812Shibler       tty.c_cflag |= CS8;	/* allow 8th bit on input */
87659812Shibler       tty.c_cflag &= ~PARENB;	/* Don't check parity */
87759812Shibler #endif
87859812Shibler       tty.c_cc[VINTR] = quit_char;	/* ^G gives SIGINT */
87959812Shibler       /* Set up C-g (usually) for both SIGQUIT and SIGINT.
88059812Shibler 	 We don't know which we will get, but we handle both alike
88159812Shibler 	 so which one it really gives us does not matter.  */
88259812Shibler       tty.c_cc[VQUIT] = quit_char;
88359812Shibler       tty.c_cc[VMIN] = 1;	/* Input should wait for at least 1 char */
88459812Shibler       tty.c_cc[VTIME] = 0;	/* no matter how long that takes.  */
88559812Shibler #ifdef VSWTCH
88659812Shibler       tty.c_cc[VSWTCH] = CDEL;	/* Turn off shell layering use of C-z */
88759812Shibler #endif /* VSWTCH */
88859812Shibler #ifdef mips  /* The following code looks like the right thing in general,
88959812Shibler 		but it is said to cause a crash on USG V.4.
89059812Shibler 		Let's play safe by turning it on only for the MIPS.  */
89159812Shibler #ifdef VSUSP
89259812Shibler       tty.c_cc[VSUSP] = CDEL;	/* Turn off mips handling of C-z.  */
89359812Shibler #endif /* VSUSP */
89459812Shibler #ifdef V_DSUSP
89559812Shibler       tty.c_cc[V_DSUSP] = CDEL;	/* Turn off mips handling of C-y.  */
89659812Shibler #endif /* V_DSUSP */
89759812Shibler #endif /* mips */
89859812Shibler 
89959812Shibler #ifdef AIX
90059812Shibler #ifndef IBMR2AIX
90159812Shibler       /* AIX enhanced edit loses NULs, so disable it */
90259812Shibler       tty.c_line = 0;
90359812Shibler       tty.c_iflag &= ~ASCEDIT;
90459812Shibler #else
90559812Shibler       tty.c_cc[VSTRT] = 255;
90659812Shibler       tty.c_cc[VSTOP] = 255;
90759812Shibler       tty.c_cc[VSUSP] = 255;
90859812Shibler       tty.c_cc[VDSUSP] = 255;
90959812Shibler #endif /* IBMR2AIX */
91059812Shibler       /* Also, PTY overloads NUL and BREAK.
91159812Shibler 	 don't ignore break, but don't signal either, so it looks like NUL.
91259812Shibler 	 This really serves a purpose only if running in an XTERM window
91359812Shibler 	 or via TELNET or the like, but does no harm elsewhere.  */
91459812Shibler       tty.c_iflag &= ~IGNBRK;
91559812Shibler       tty.c_iflag &= ~BRKINT;
91659812Shibler #endif /* AIX */
91759812Shibler 
91859812Shibler #else /* if not HAVE_TERMIO */
91959812Shibler #ifdef VMS
92059812Shibler       tty.tt_char |= TT$M_NOECHO | TT$M_EIGHTBIT;
92159812Shibler       if (flow_control)
92259812Shibler 	tty.tt_char |= TT$M_TTSYNC;
92359812Shibler       else
92459812Shibler 	tty.tt_char &= ~TT$M_TTSYNC;
92559812Shibler       tty.tt2_char |= TT2$M_PASTHRU | TT2$M_XON;
92659812Shibler #else /* not VMS (BSD, that is) */
92759812Shibler       tty.sg_flags &= ~(ECHO | CRMOD | XTABS);
92859812Shibler       tty.sg_flags |= ANYP;
92959812Shibler       tty.sg_flags |= interrupt_input ? RAW : CBREAK;
93059812Shibler #endif /* not VMS (BSD, that is) */
93159812Shibler #endif /* not HAVE_TERMIO */
93259812Shibler 
93359812Shibler #ifdef VMS
93459812Shibler       SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
93559812Shibler 		&tty.class, 12, 0, 0, 0, 0);
93659812Shibler #else
93759812Shibler       ioctl (0, TIOCSETN, &tty);
93859812Shibler #endif /* not VMS */
93959812Shibler 
94059812Shibler       /* This code added to insure that, if flow-control is not to be used,
94159812Shibler 	 we have an unlocked screen at the start. */
94259812Shibler #ifdef TCXONC
94359812Shibler       if (!flow_control) ioctl (0, TCXONC, 1);
94459812Shibler #endif
94559812Shibler #ifdef TIOCSTART
94659812Shibler       if (!flow_control) ioctl (0, TIOCSTART, 0);
94759812Shibler #endif
94859812Shibler 
94959812Shibler #ifdef AIX
95059812Shibler       hft_init ();
95159812Shibler #ifdef IBMR2AIX
95259812Shibler   {
95359812Shibler     /* IBM's HFT device usually thinks a ^J should be LF/CR.  We need it
95459812Shibler        to be only LF.  This is the way that is done. */
95559812Shibler     struct termio tty;
95659812Shibler 
95759812Shibler     if (ioctl (1, HFTGETID, &tty) != -1)
95859812Shibler       write (1, "\033[20l", 5);
95959812Shibler   }
96059812Shibler #endif
96159812Shibler #endif
96259812Shibler 
96359812Shibler #ifdef F_SETFL
96459812Shibler #ifdef F_GETOWN		/* F_SETFL does not imply existance of F_GETOWN */
96559812Shibler       if (interrupt_input)
96659812Shibler 	{
96759812Shibler 	  old_fcntl_owner = fcntl (0, F_GETOWN, 0);
96859812Shibler 	  fcntl (0, F_SETOWN, getpid ());
96959812Shibler 	  init_sigio ();
97059812Shibler 	}
97159812Shibler #endif /* F_GETOWN */
97259812Shibler #endif /* F_SETFL */
97359812Shibler 
97459812Shibler       /* If going to use CBREAK mode, we must request C-g to interrupt
97559812Shibler 	   and turn off start and stop chars, etc.
97659812Shibler 	   If not going to use CBREAK mode, do this anyway
97759812Shibler 	   so as to turn off local flow control for user coming over
97859812Shibler 	   network on 4.2; in this case, only t_stopc and t_startc really matter.  */
97959812Shibler #ifdef TIOCGLTC
98059812Shibler       ioctl (0, TIOCGLTC, &old_ltchars);
98159812Shibler #endif /* TIOCGLTC */
98259812Shibler #ifndef HAVE_TERMIO
98359812Shibler #ifdef TIOCGETC
98459812Shibler       ioctl (0, TIOCGETC, &old_tchars);
98559812Shibler       ioctl (0, TIOCLGET, &old_lmode);
98659812Shibler 
98759812Shibler       /* Note: if not using CBREAK mode, it makes no difference how we set this */
98859812Shibler       tchars = new_tchars;
98959812Shibler       tchars.t_intrc = quit_char;
99059812Shibler       if (flow_control)
99159812Shibler 	{
99259812Shibler 	  tchars.t_startc = '\021';
99359812Shibler 	  tchars.t_stopc = '\023';
99459812Shibler 	}
99559812Shibler /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits.  */
99659812Shibler #ifndef LPASS8
99759812Shibler #define LPASS8 0
99859812Shibler #endif
99959812Shibler 
100059812Shibler #ifdef BSD4_1
100159812Shibler #define LNOFLSH 0100000
100259812Shibler #endif
100359812Shibler 
100459812Shibler       lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_lmode;
100559812Shibler 
100659812Shibler       ioctl (0, TIOCSETC, &tchars);
100759812Shibler       ioctl (0, TIOCLSET, &lmode);
100859812Shibler #endif /* TIOCGETC */
100959812Shibler #endif /* not HAVE_TERMIO */
101059812Shibler #ifdef TIOCGLTC
101159812Shibler       ioctl (0, TIOCSLTC, &new_ltchars);
101259812Shibler #endif /* TIOCGLTC */
101359812Shibler 
101459812Shibler #ifdef BSD4_1
101559812Shibler       if (interrupt_input)
101659812Shibler 	init_sigio ();
101759812Shibler #endif
101859812Shibler #ifdef VMS
101959812Shibler /*  Appears to do nothing when in PASTHRU mode.
102059812Shibler       SYS$QIOW (0, input_chan, IO$_SETMODE|IO$M_OUTBAND, 0, 0, 0,
102159812Shibler 		interrupt_signal, oob_chars, 0, 0, 0, 0);
102259812Shibler */
102359812Shibler       queue_kbd_input (0);
102459812Shibler #endif /* VMS */
102559812Shibler     }
102659812Shibler #ifdef VMS  /* VMS sometimes has this symbol but lacks setvbuf.  */
102759812Shibler #undef _IOFBF
102859812Shibler #endif
102959812Shibler #ifdef _IOFBF
103059812Shibler   /* This symbol is defined on recent USG systems.
103159812Shibler      Someone says without this call USG won't really buffer the file
103259812Shibler      even with a call to setbuf(). */
103359812Shibler   setvbuf (stdout, _sobuf, _IOFBF, sizeof _sobuf);
103459812Shibler #else
103559812Shibler   setbuf (stdout, _sobuf);
103659812Shibler #endif
103759812Shibler   set_terminal_modes ();
103859812Shibler   if (term_initted && no_redraw_on_reenter)
103959812Shibler     {
104059812Shibler       if (display_completed)
104159812Shibler 	direct_output_forward_char (0);
104259812Shibler     }
104359812Shibler   else
104459812Shibler     screen_garbaged = 1;
104559812Shibler   term_initted = 1;
104659812Shibler }
104759812Shibler 
104859812Shibler /* Return nonzero if safe to use tabs in output.
104959812Shibler    At the time this is called, init_sys_modes has not been done yet.  */
105059812Shibler 
105159812Shibler tabs_safe_p ()
105259812Shibler {
105359812Shibler   TERMINAL tty;
105459812Shibler   if (noninteractive)
105559812Shibler     return 1;
105659812Shibler #ifdef VMS
105759812Shibler   SYS$QIOW (0, input_chan, IO$_SENSEMODE, &tty, 0, 0,
105859812Shibler 	    &tty.class, 12, 0, 0, 0, 0);
105959812Shibler #else
106059812Shibler   ioctl (0, TIOCGETP, &tty);
106159812Shibler #endif /* not VMS */
106259812Shibler   return (TABS_OK(tty));
106359812Shibler }
106459812Shibler 
106559812Shibler /* Get terminal size from system.
106659812Shibler    Store number of lines into *heightp and width into *widthp.
106759812Shibler    If zero or a negative number is stored, the value is not valid.  */
106859812Shibler 
106959812Shibler get_screen_size (widthp, heightp)
107059812Shibler      int *widthp, *heightp;
107159812Shibler {
107259812Shibler /* Define the 4.3 names in terms of the Sun names
107359812Shibler    if the latter exist and the former do not.  */
107459812Shibler #ifdef TIOCGSIZE
107559812Shibler #ifndef TIOCGWINSZ
107659812Shibler #define TIOCGWINSZ TIOCGSIZE
107759812Shibler #define winsize ttysize
107859812Shibler #define ws_row ts_lines
107959812Shibler #define ws_col ts_cols
108059812Shibler #endif
108159812Shibler #endif /* Sun */
108259812Shibler 
108359812Shibler /* Do it using the 4.3 names if possible.  */
108459812Shibler #ifdef TIOCGWINSZ
108559812Shibler   struct winsize size;
108659812Shibler   *widthp = 0;
108759812Shibler   *heightp = 0;
108859812Shibler   if (ioctl (0, TIOCGWINSZ, &size) < 0)
108959812Shibler     return;
109059812Shibler   *widthp = size.ws_col;
109159812Shibler   *heightp = size.ws_row;
109259812Shibler #else /* not TIOCGWNSIZ */
109359812Shibler #ifdef VMS
109459812Shibler   TERMINAL tty;
109559812Shibler   SYS$QIOW (0, input_chan, IO$_SENSEMODE, &tty, 0, 0,
109659812Shibler 	    &tty.class, 12, 0, 0, 0, 0);
109759812Shibler   *widthp = tty.scr_wid;
109859812Shibler   *heightp = tty.scr_len;
109959812Shibler #else /* system doesn't know size */
110059812Shibler   *widthp = 0;
110159812Shibler   *heightp = 0;
110259812Shibler #endif /* system does not know size */
110359812Shibler #endif /* not TIOCGWINSZ */
110459812Shibler }
110559812Shibler 
110659812Shibler reset_sys_modes ()
110759812Shibler {
110859812Shibler   if (noninteractive)
110959812Shibler     {
111059812Shibler       fflush (stdout);
111159812Shibler       return;
111259812Shibler     }
111359812Shibler   if (!term_initted)
111459812Shibler     return;
111559812Shibler   if (read_socket_hook)
111659812Shibler     return;
111759812Shibler   move_cursor (screen_height - 1, 0);
111859812Shibler   clear_end_of_line (screen_width);
111959812Shibler   /* clear_end_of_line may move the cursor */
112059812Shibler   move_cursor (screen_height - 1, 0);
112159812Shibler   /* Output raw CR so kernel can track the cursor hpos.  */
112259812Shibler   cmputc ('\r');
112359812Shibler #ifdef IBMR2AIX
112459812Shibler   {
112559812Shibler     /* HFT devices normally use ^J as a LF/CR.  We forced it to
112659812Shibler        do the LF only.  Now, we need to reset it. */
112759812Shibler     struct termio tty;
112859812Shibler 
112959812Shibler     if (ioctl (1, HFTGETID, &tty) != -1)
113059812Shibler       write (1, "\033[20h", 5);
113159812Shibler   }
113259812Shibler #endif
113359812Shibler 
113459812Shibler   reset_terminal_modes ();
113559812Shibler   fflush (stdout);
113659812Shibler #ifdef BSD
113759812Shibler #ifndef BSD4_1
113859812Shibler   /* Avoid possible loss of output when changing terminal modes.  */
113959812Shibler   fsync (fileno (stdout));
114059812Shibler #endif
114159812Shibler #endif
114259812Shibler #ifdef TIOCGLTC
114359812Shibler   ioctl (0, TIOCSLTC, &old_ltchars);
114459812Shibler #endif /* TIOCGLTC */
114559812Shibler #ifndef HAVE_TERMIO
114659812Shibler #ifdef TIOCGETC
114759812Shibler   ioctl (0, TIOCSETC, &old_tchars);
114859812Shibler   ioctl (0, TIOCLSET, &old_lmode);
114959812Shibler #endif /* TIOCGETC */
115059812Shibler #endif /* not HAVE_TERMIO */
115159812Shibler #ifdef F_SETFL
115259812Shibler #ifdef F_SETOWN		/* F_SETFL does not imply existance of F_SETOWN */
115359812Shibler   if (interrupt_input)
115459812Shibler     {
115559812Shibler       reset_sigio ();
115659812Shibler       fcntl (0, F_SETOWN, old_fcntl_owner);
115759812Shibler     }
115859812Shibler #endif /* F_SETOWN */
115959812Shibler #endif /* F_SETFL */
116059812Shibler #ifdef BSD4_1
116159812Shibler   if (interrupt_input)
116259812Shibler     reset_sigio ();
116359812Shibler #endif /* BSD4_1 */
116459812Shibler #ifdef VMS
116559812Shibler   end_kbd_input ();
116659812Shibler   SYS$QIOW (0, input_chan, IO$_SETMODE, &input_iosb, 0, 0,
116759812Shibler 	    &old_gtty.class, 12, 0, 0, 0, 0);
116859812Shibler #else /* not VMS */
116959812Shibler   while (ioctl (0, TCSETAW, &old_gtty) < 0 && errno == EINTR);
117059812Shibler #endif /* not VMS */
117159812Shibler 
117259812Shibler #ifdef AIX
117359812Shibler   hft_reset ();
117459812Shibler #endif
117559812Shibler }
117659812Shibler 
117759812Shibler #ifdef HAVE_PTYS
117859812Shibler 
117959812Shibler /* Set up the proper status flags for use of a pty.  */
118059812Shibler 
118159812Shibler setup_pty (fd)
118259812Shibler      int fd;
118359812Shibler {
118459812Shibler   /* I'm told that TOICREMOTE does not mean control chars
118559812Shibler      "can't be sent" but rather that they don't have
118659812Shibler      input-editing or signaling effects.
118759812Shibler      That should be good, because we have other ways
118859812Shibler      to do those things in Emacs.
118959812Shibler      However, telnet mode seems not to work on 4.2.
119059812Shibler      So TIOCREMOTE is turned off now. */
119159812Shibler 
119259812Shibler   /* Under hp-ux, if TIOCREMOTE is turned on, some calls
119359812Shibler      will hang.  In particular, the "timeout" feature (which
119459812Shibler      causes a read to return if there is no data available)
119559812Shibler      does this.  Also it is known that telnet mode will hang
119659812Shibler      in such a way that Emacs must be stopped (perhaps this
119759812Shibler      is the same problem).
119859812Shibler 
119959812Shibler      If TIOCREMOTE is turned off, then there is a bug in
120059812Shibler      hp-ux which sometimes loses data.  Apparently the
120159812Shibler      code which blocks the master process when the internal
120259812Shibler      buffer fills up does not work.  Other than this,
120359812Shibler      though, everything else seems to work fine.
120459812Shibler 
120559812Shibler      Since the latter lossage is more benign, we may as well
120659812Shibler      lose that way.  -- cph */
120759812Shibler #ifdef FIONBIO
120859812Shibler #ifdef SYSV_PTYS
120959812Shibler   {
121059812Shibler     int on = 1;
121159812Shibler     ioctl (fd, FIONBIO, &on);
121259812Shibler   }
121359812Shibler #endif
121459812Shibler #endif
121559812Shibler #ifdef IBMRTAIX
121659812Shibler   /* On AIX, the parent gets SIGHUP when a pty attached child dies.  So, we */
121759812Shibler   /* ignore SIGHUP once we've started a child on a pty.  Note that this may */
121859812Shibler   /* cause EMACS not to die when it should, i.e., when its own controlling  */
121959812Shibler   /* tty goes away.  I've complained to the AIX developers, and they may    */
122059812Shibler   /* change this behavior, but I'm not going to hold my breath.             */
122159812Shibler   signal (SIGHUP, SIG_IGN);
122259812Shibler #endif
122359812Shibler }
122459812Shibler #endif /* HAVE_PTYS */
122559812Shibler 
122659812Shibler #ifdef VMS
122759812Shibler 
122859812Shibler /* Assigning an input channel is done at the start of Emacs execution.
122959812Shibler    This is called each time Emacs is resumed, also, but does nothing
123059812Shibler    because input_chain is no longer zero.  */
123159812Shibler 
123259812Shibler init_vms_input()
123359812Shibler {
123459812Shibler   int status;
123559812Shibler 
123659812Shibler   if (input_chan == 0)
123759812Shibler     {
123859812Shibler       status = SYS$ASSIGN (&input_dsc, &input_chan, 0, 0);
123959812Shibler       if (! (status & 1))
124059812Shibler 	LIB$STOP (status);
124159812Shibler     }
124259812Shibler }
124359812Shibler 
124459812Shibler /* Deassigning the input channel is done before exiting.  */
124559812Shibler 
124659812Shibler stop_vms_input ()
124759812Shibler {
124859812Shibler   return SYS$DASSGN (input_chan);
124959812Shibler }
125059812Shibler 
125159812Shibler short input_buffer;
125259812Shibler 
125359812Shibler /* Request reading one character into the keyboard buffer.
125459812Shibler    This is done as soon as the buffer becomes empty.  */
125559812Shibler 
125659812Shibler queue_kbd_input ()
125759812Shibler {
125859812Shibler   int status;
125959812Shibler   waiting_for_ast = 0;
126059812Shibler   stop_input = 0;
126159812Shibler   status = SYS$QIO (0, input_chan, IO$_READVBLK,
126259812Shibler 		    &input_iosb, kbd_input_ast, 1,
126359812Shibler 		    &input_buffer, 1, 0, terminator_mask, 0, 0);
126459812Shibler }
126559812Shibler 
126659812Shibler int input_count;
126759812Shibler 
126859812Shibler /* Ast routine that is called when keyboard input comes in
126959812Shibler    in accord with the SYS$QIO above.  */
127059812Shibler 
127159812Shibler kbd_input_ast ()
127259812Shibler {
127359812Shibler   register int c = -1;
127459812Shibler   int old_errno = errno;
127559812Shibler 
127659812Shibler   if (waiting_for_ast)
127759812Shibler     SYS$SETEF (input_ef);
127859812Shibler   waiting_for_ast = 0;
127959812Shibler   input_count++;
128059812Shibler #ifdef ASTDEBUG
128159812Shibler   if (input_count == 25)
128259812Shibler     exit (1);
128359812Shibler   printf ("Ast # %d,", input_count);
128459812Shibler   printf (" iosb = %x, %x, %x, %x",
128559812Shibler 	  input_iosb.offset, input_iosb.status, input_iosb.termlen,
128659812Shibler 	  input_iosb.term);
128759812Shibler #endif
128859812Shibler   if (input_iosb.offset)
128959812Shibler     {
129059812Shibler       c = input_buffer;
129159812Shibler #ifdef ASTDEBUG
129259812Shibler       printf (", char = 0%o", c);
129359812Shibler #endif
129459812Shibler     }
129559812Shibler #ifdef ASTDEBUG
129659812Shibler   printf ("\n");
129759812Shibler   fflush (stdout);
129859812Shibler   sleep (1);
129959812Shibler #endif
130059812Shibler   if (! stop_input)
130159812Shibler     queue_kbd_input ();
130259812Shibler   if (c >= 0)
130359812Shibler     kbd_buffer_store_char (c);
130459812Shibler 
130559812Shibler   errno = old_errno;
130659812Shibler }
130759812Shibler 
130859812Shibler /* Wait until there is something in kbd_buffer.  */
130959812Shibler 
131059812Shibler wait_for_kbd_input ()
131159812Shibler {
131259812Shibler   extern int have_process_input, process_exited;
131359812Shibler 
131459812Shibler   /* If already something, avoid doing system calls.  */
131559812Shibler   if (detect_input_pending ())
131659812Shibler     {
131759812Shibler       return;
131859812Shibler     }
131959812Shibler   /* Clear a flag, and tell ast routine above to set it.  */
132059812Shibler   SYS$CLREF (input_ef);
132159812Shibler   waiting_for_ast = 1;
132259812Shibler   /* Check for timing error: ast happened while we were doing that.  */
132359812Shibler   if (!detect_input_pending ())
132459812Shibler     {
132559812Shibler       /* No timing error: wait for flag to be set.  */
132659812Shibler       set_waiting_for_input (0);
132759812Shibler       SYS$WFLOR (input_ef, input_eflist);
132859812Shibler       clear_waiting_for_input (0);
132959812Shibler       if (!detect_input_pending ())
133059812Shibler 	/* Check for subprocess input availability */
133159812Shibler 	{
133259812Shibler 	  int dsp = have_process_input || process_exited;
133359812Shibler 
133459812Shibler 	  sys$clref (process_ef);
133559812Shibler 	  if (have_process_input)
133659812Shibler 	    process_command_input ();
133759812Shibler 	  if (process_exited)
133859812Shibler 	    process_exit ();
133959812Shibler 	  if (dsp)
134059812Shibler 	    {
134159812Shibler 	      update_mode_lines++;
134259812Shibler 	      redisplay_preserve_echo_area ();
134359812Shibler 	    }
134459812Shibler 	}
134559812Shibler     }
134659812Shibler   waiting_for_ast = 0;
134759812Shibler }
134859812Shibler 
134959812Shibler /* Get rid of any pending QIO, when we are about to suspend
135059812Shibler    or when we want to throw away pending input.
135159812Shibler    We wait for a positive sign that the AST routine has run
135259812Shibler    and therefore there is no I/O request queued when we return.
135359812Shibler    SYS$SETAST is used to avoid a timing error.  */
135459812Shibler 
135559812Shibler end_kbd_input()
135659812Shibler {
135759812Shibler #ifdef ASTDEBUG
135859812Shibler   printf ("At end_kbd_input.\n");
135959812Shibler   fflush (stdout);
136059812Shibler   sleep (1);
136159812Shibler #endif
136259812Shibler   if (LIB$AST_IN_PROG ())  /* Don't wait if suspending from kbd_buffer_store_char! */
136359812Shibler     {
136459812Shibler       SYS$CANCEL (input_chan);
136559812Shibler       return;
136659812Shibler     }
136759812Shibler 
136859812Shibler   SYS$SETAST (0);
136959812Shibler   /* Clear a flag, and tell ast routine above to set it.  */
137059812Shibler   SYS$CLREF (input_ef);
137159812Shibler   waiting_for_ast = 1;
137259812Shibler   stop_input = 1;
137359812Shibler   SYS$CANCEL (input_chan);
137459812Shibler   SYS$SETAST (1);
137559812Shibler   SYS$WAITFR (input_ef);
137659812Shibler   waiting_for_ast = 0;
137759812Shibler }
137859812Shibler 
137959812Shibler /* Wait for either input available or time interval expiry.  */
138059812Shibler 
138159812Shibler input_wait_timeout (timeval)
138259812Shibler      int timeval;		/* Time to wait, in seconds */
138359812Shibler {
138459812Shibler   int time [2];
138559812Shibler 
138659812Shibler   LIB$EMUL (&timeval, &-10000000, &0, time); 	  /* Convert to VMS format */
138759812Shibler 
138859812Shibler   /* If already something, avoid doing system calls.  */
138959812Shibler   if (detect_input_pending ())
139059812Shibler     {
139159812Shibler       return;
139259812Shibler     }
139359812Shibler   /* Clear a flag, and tell ast routine above to set it.  */
139459812Shibler   SYS$CLREF (input_ef);
139559812Shibler   waiting_for_ast = 1;
139659812Shibler   /* Check for timing error: ast happened while we were doing that.  */
139759812Shibler   if (!detect_input_pending ())
139859812Shibler     {
139959812Shibler       /* No timing error: wait for flag to be set.  */
140059812Shibler       SYS$CANTIM (1, 0);
140159812Shibler       if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
140259812Shibler 	SYS$WFLOR (timer_ef, timer_eflist);	  /* Wait for timer expiry or input */
140359812Shibler     }
140459812Shibler   waiting_for_ast = 0;
140559812Shibler }
140659812Shibler 
140759812Shibler /* The standard `sleep' routine works some other way
140859812Shibler    and it stops working if you have ever quit out of it.
140959812Shibler    This one continues to work.  */
141059812Shibler 
141159812Shibler sys_sleep (timeval)
141259812Shibler      int timeval;
141359812Shibler {
141459812Shibler   int time [2];
141559812Shibler 
141659812Shibler   LIB$EMUL (&timeval, &-10000000, &0, time); 	  /* Convert to VMS format */
141759812Shibler 
141859812Shibler   SYS$CANTIM (1, 0);
141959812Shibler   if (SYS$SETIMR (timer_ef, time, 0, 1) & 1) /* Set timer */
142059812Shibler     SYS$WAITFR (timer_ef);	  /* Wait for timer expiry only */
142159812Shibler }
142259812Shibler 
142359812Shibler init_sigio ()
142459812Shibler {
142559812Shibler   request_sigio ();
142659812Shibler }
142759812Shibler 
142859812Shibler reset_sigio ()
142959812Shibler {
143059812Shibler   unrequest_sigio ();
143159812Shibler }
143259812Shibler 
143359812Shibler request_sigio ()
143459812Shibler {
143559812Shibler   croak ("request sigio");
143659812Shibler }
143759812Shibler 
143859812Shibler unrequest_sigio ()
143959812Shibler {
144059812Shibler   croak ("unrequest sigio");
144159812Shibler }
144259812Shibler 
144359812Shibler #endif /* VMS */
144459812Shibler 
144559812Shibler /* Note that VMS compiler won't accept defined (CANNOT_DUMP).  */
144659812Shibler #ifndef CANNOT_DUMP
144759812Shibler #define NEED_STARTS
144859812Shibler #endif
144959812Shibler 
145059812Shibler #ifndef SYSTEM_MALLOC
145159812Shibler #ifndef NEED_STARTS
145259812Shibler #define NEED_STARTS
145359812Shibler #endif
145459812Shibler #endif
145559812Shibler 
145659812Shibler #ifdef NEED_STARTS
145759812Shibler /* Some systems that cannot dump also cannot implement these.  */
145859812Shibler 
145959812Shibler /*
146059812Shibler  *	Return the address of the start of the text segment prior to
146159812Shibler  *	doing an unexec().  After unexec() the return value is undefined.
146259812Shibler  *	See crt0.c for further explanation and _start().
146359812Shibler  *
146459812Shibler  */
146559812Shibler 
146659812Shibler #ifndef CANNOT_UNEXEC
146759812Shibler char *
146859812Shibler start_of_text ()
146959812Shibler {
147059812Shibler #ifdef TEXT_START
147159812Shibler   return ((char *) TEXT_START);
147259812Shibler #else
147359812Shibler #ifdef GOULD
147459812Shibler   extern csrt();
147559812Shibler   return ((char *) csrt);
147659812Shibler #else /* not GOULD */
147759812Shibler   extern int _start ();
147859812Shibler   return ((char *) _start);
147959812Shibler #endif /* GOULD */
148059812Shibler #endif /* TEXT_START */
148159812Shibler }
148259812Shibler #endif /* not CANNOT_UNEXEC */
148359812Shibler 
148459812Shibler /*
148559812Shibler  *	Return the address of the start of the data segment prior to
148659812Shibler  *	doing an unexec().  After unexec() the return value is undefined.
148759812Shibler  *	See crt0.c for further information and definition of data_start.
148859812Shibler  *
148959812Shibler  *	Apparently, on BSD systems this is etext at startup.  On
149059812Shibler  *	USG systems (swapping) this is highly mmu dependent and
149159812Shibler  *	is also dependent on whether or not the program is running
149259812Shibler  *	with shared text.  Generally there is a (possibly large)
149359812Shibler  *	gap between end of text and start of data with shared text.
149459812Shibler  *
149559812Shibler  *	On Uniplus+ systems with shared text, data starts at a
149659812Shibler  *	fixed address.  Each port (from a given oem) is generally
149759812Shibler  *	different, and the specific value of the start of data can
149859812Shibler  *	be obtained via the UniPlus+ specific "uvar(2)" system call,
149959812Shibler  *	however the method outlined in crt0.c seems to be more portable.
150059812Shibler  *
150159812Shibler  *	Probably what will have to happen when a USG unexec is available,
150259812Shibler  *	at least on UniPlus, is temacs will have to be made unshared so
150359812Shibler  *	that text and data are contiguous.  Then once loadup is complete,
150459812Shibler  *	unexec will produce a shared executable where the data can be
150559812Shibler  *	at the normal shared text boundry and the startofdata variable
150659812Shibler  *	will be patched by unexec to the correct value.
150759812Shibler  *
150859812Shibler  */
150959812Shibler 
151059812Shibler char *
151159812Shibler start_of_data ()
151259812Shibler {
151359812Shibler #ifdef DATA_START
151459812Shibler   return ((char *) DATA_START);
151559812Shibler #else
151659812Shibler   extern int data_start;
151759812Shibler   return ((char *) &data_start);
151859812Shibler #endif
151959812Shibler }
152059812Shibler #endif /* NEED_STARTS (not CANNOT_DUMP or not SYSTEM_MALLOC) */
152159812Shibler 
152259812Shibler #ifndef CANNOT_DUMP
152359812Shibler /* Some systems that cannot dump also cannot implement these.  */
152459812Shibler 
152559812Shibler /*
152659812Shibler  *	Return the address of the end of the text segment prior to
152759812Shibler  *	doing an unexec().  After unexec() the return value is undefined.
152859812Shibler  */
152959812Shibler 
153059812Shibler char *
153159812Shibler end_of_text ()
153259812Shibler {
153359812Shibler #ifdef TEXT_END
153459812Shibler   return ((char *) TEXT_END);
153559812Shibler #else
153659812Shibler   extern int etext;
153759812Shibler   return ((char *) &etext);
153859812Shibler #endif
153959812Shibler }
154059812Shibler 
154159812Shibler /*
154259812Shibler  *	Return the address of the end of the data segment prior to
154359812Shibler  *	doing an unexec().  After unexec() the return value is undefined.
154459812Shibler  */
154559812Shibler 
154659812Shibler char *
154759812Shibler end_of_data ()
154859812Shibler {
154959812Shibler #ifdef DATA_END
155059812Shibler   return ((char *) DATA_END);
155159812Shibler #else
155259812Shibler   extern int edata;
155359812Shibler   return ((char *) &edata);
155459812Shibler #endif
155559812Shibler }
155659812Shibler 
155759812Shibler #endif /* not CANNOT_DUMP */
155859812Shibler 
155959812Shibler /* Get_system_name returns as its value
156059812Shibler  a string for the Lisp function system-name to return. */
156159812Shibler 
156259812Shibler #ifdef BSD4_1
156359812Shibler #include <whoami.h>
156459812Shibler #endif
156559812Shibler 
156659812Shibler #ifdef USG
156759812Shibler /* Can't have this within the function since `static' is #defined to nothing */
156859812Shibler static struct utsname get_system_name_name;
156959812Shibler #endif
157059812Shibler 
157159812Shibler char *
157259812Shibler get_system_name ()
157359812Shibler {
157459812Shibler #ifdef USG
157559812Shibler   uname (&get_system_name_name);
157659812Shibler   return (get_system_name_name.nodename);
157759812Shibler #else /* Not USG */
157859812Shibler #ifdef BSD4_1
157959812Shibler   return sysname;
158059812Shibler #else /* not USG, not 4.1 */
158159812Shibler   static char system_name_saved[32];
158259812Shibler #ifdef VMS
158359812Shibler   char *sp;
158459812Shibler   if ((sp = egetenv("SYS$NODE")) == 0)
158559812Shibler     sp = "vax-vms";
158659812Shibler   else
158759812Shibler     {
158859812Shibler       char *end;
158959812Shibler 
159059812Shibler       if ((end = index (sp, ':')) != 0)
159159812Shibler 	*end = '\0';
159259812Shibler     }
159359812Shibler   strcpy (system_name_saved, sp);
159459812Shibler #else /* not VMS */
159559812Shibler   gethostname (system_name_saved, sizeof (system_name_saved));
159659812Shibler #endif /* not VMS */
159759812Shibler   return system_name_saved;
159859812Shibler #endif /* not USG, not 4.1 */
159959812Shibler #endif /* not USG */
160059812Shibler }
160159812Shibler 
160259812Shibler #ifndef HAVE_SELECT
160359812Shibler 
160459812Shibler /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
160559812Shibler  * Only checks read descriptors.
160659812Shibler  */
160759812Shibler /* How long to wait between checking fds in select */
160859812Shibler #define SELECT_PAUSE 1
160959812Shibler int select_alarmed;
161059812Shibler 
161159812Shibler /* For longjmp'ing back to read_input_waiting.  */
161259812Shibler 
161359812Shibler jmp_buf read_alarm_throw;
161459812Shibler 
161559812Shibler /* Nonzero if the alarm signal should throw back to read_input_waiting.
161659812Shibler    The read_socket_hook function sets this to 1 while it is waiting.  */
161759812Shibler 
161859812Shibler int read_alarm_should_throw;
161959812Shibler 
162059812Shibler select_alarm ()
162159812Shibler {
162259812Shibler   select_alarmed = 1;
162359812Shibler #ifdef BSD4_1
162459812Shibler   sigrelse (SIGALRM);
162559812Shibler #else /* not BSD4_1 */
162659812Shibler   signal (SIGALRM, SIG_IGN);
162759812Shibler #endif /* not BSD4_1 */
162859812Shibler   if (read_alarm_should_throw)
162959812Shibler     longjmp (read_alarm_throw, 1);
163059812Shibler }
163159812Shibler 
163259812Shibler /* Only rfds are checked.  */
163359812Shibler int
163459812Shibler select (nfds, rfds, wfds, efds, timeout)
163559812Shibler      int nfds;
163659812Shibler      int *rfds, *wfds, *efds, *timeout;
163759812Shibler {
163859812Shibler   int ravail = 0, orfds = 0, old_alarm;
163959812Shibler   int timeoutval = timeout ? *timeout : 100000;
164059812Shibler   int *local_timeout = &timeoutval;
164159812Shibler   extern int kbd_count;
164259812Shibler   extern int proc_buffered_char[];
164359812Shibler #ifndef subprocesses
164459812Shibler   int process_tick = 0, update_tick = 0;
164559812Shibler #else
164659812Shibler   extern int process_tick, update_tick;
164759812Shibler #endif
164859812Shibler   int (*old_trap) ();
164959812Shibler   char buf;
165059812Shibler 
165159812Shibler   if (rfds)
165259812Shibler     {
165359812Shibler       orfds = *rfds;
165459812Shibler       *rfds = 0;
165559812Shibler     }
165659812Shibler   if (wfds)
165759812Shibler     *wfds = 0;
165859812Shibler   if (efds)
165959812Shibler     *efds = 0;
166059812Shibler 
166159812Shibler   /* If we are looking only for the terminal, with no timeout,
166259812Shibler      just read it and wait -- that's more efficient.  */
166359812Shibler   if (orfds == 1 && (!timeout || *timeout == 100000)
166459812Shibler       && process_tick == update_tick)
166559812Shibler     {
166659812Shibler       if (!kbd_count)
166759812Shibler 	read_input_waiting ();
166859812Shibler       *rfds = 1;
166959812Shibler       return 1;
167059812Shibler     }
167159812Shibler 
167259812Shibler   /* Once a second, till the timer expires, check all the flagged read
167359812Shibler    * descriptors to see if any input is available.  If there is some then
167459812Shibler    * set the corresponding bit in the return copy of rfds.
167559812Shibler    */
167659812Shibler   while (1)
167759812Shibler     {
167859812Shibler       register int to_check, bit, fd;
167959812Shibler 
168059812Shibler       if (rfds)
168159812Shibler 	{
168259812Shibler 	  for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++)
168359812Shibler 	    {
168459812Shibler 	      if (orfds & bit)
168559812Shibler 		{
168659812Shibler 		  int avail = 0, status = 0;
168759812Shibler 
168859812Shibler 		  if (bit == 1)
168959812Shibler 		    avail = detect_input_pending(); /* Special keyboard handler */
169059812Shibler 		  else
169159812Shibler 		    {
169259812Shibler #ifdef FIONREAD
169359812Shibler 		      status = ioctl (fd, FIONREAD, &avail);
169459812Shibler #else /* no FIONREAD */
169559812Shibler 		      /* Hoping it will return -1 if nothing available
169659812Shibler 			 or 0 if all 0 chars requested are read.  */
169759812Shibler 		      if (proc_buffered_char[fd] >= 0)
169859812Shibler 			avail = 1;
169959812Shibler 		      else
170059812Shibler 			{
170159812Shibler 			  avail = read (fd, &buf, 1);
170259812Shibler 			  if (avail > 0)
170359812Shibler 			    proc_buffered_char[fd] = buf;
170459812Shibler 			}
170559812Shibler #endif /* no FIONREAD */
170659812Shibler 		    }
170759812Shibler 		  if (status >= 0 && avail > 0)
170859812Shibler 		    {
170959812Shibler 		      (*rfds) |= bit;
171059812Shibler 		      ravail++;
171159812Shibler 		    }
171259812Shibler 		}
171359812Shibler 	    }
171459812Shibler 	}
171559812Shibler       if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
171659812Shibler 	break;
171759812Shibler       old_alarm = alarm (0);
171859812Shibler       old_trap = (int (*)()) signal (SIGALRM, select_alarm);
171959812Shibler       select_alarmed = 0;
172059812Shibler       alarm (SELECT_PAUSE);
172159812Shibler       /* Wait for a SIGALRM (or maybe a SIGTINT) */
172259812Shibler       while (select_alarmed == 0 && *local_timeout != 0
172359812Shibler 	     && process_tick == update_tick)
172459812Shibler 	{
172559812Shibler 	  /* If we are interested in terminal input,
172659812Shibler 	     wait by reading the terminal.
172759812Shibler 	     That makes instant wakeup for terminal input at least.  */
172859812Shibler 	  if (orfds & 1)
172959812Shibler 	    {
173059812Shibler 	      read_input_waiting ();
173159812Shibler 	      if (kbd_count)
173259812Shibler 		select_alarmed = 1;
173359812Shibler 	    }
173459812Shibler 	  else
173559812Shibler 	    pause();
173659812Shibler 	}
173759812Shibler       (*local_timeout) -= SELECT_PAUSE;
173859812Shibler       /* Reset the old alarm if there was one */
173959812Shibler       alarm (0);
174059812Shibler       signal (SIGALRM, old_trap);
174159812Shibler       if (old_alarm != 0)
174259812Shibler 	{
174359812Shibler 	  /* Reset or forge an interrupt for the original handler. */
174459812Shibler 	  old_alarm -= SELECT_PAUSE;
174559812Shibler 	  if (old_alarm <= 0)
174659812Shibler 	    kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
174759812Shibler 	  else
174859812Shibler 	    alarm (old_alarm);
174959812Shibler 	}
175059812Shibler       if (*local_timeout == 0)  /* Stop on timer being cleared */
175159812Shibler 	break;
175259812Shibler     }
175359812Shibler   return ravail;
175459812Shibler }
175559812Shibler 
175659812Shibler /* Read keyboard input into the standard buffer,
175759812Shibler    waiting for at least one character.  */
175859812Shibler 
175959812Shibler /* Make all keyboard buffers much bigger when using X windows.  */
176059812Shibler #ifdef HAVE_X_WINDOWS
176159812Shibler #define BUFFER_SIZE_FACTOR 16
176259812Shibler #else
176359812Shibler #define BUFFER_SIZE_FACTOR 1
176459812Shibler #endif
176559812Shibler 
176659812Shibler read_input_waiting ()
176759812Shibler {
176859812Shibler   extern int kbd_count;
176959812Shibler   extern unsigned char kbd_buffer[];
177059812Shibler   extern unsigned char *kbd_ptr;
177159812Shibler   int val;
177259812Shibler 
177359812Shibler   if (read_socket_hook)
177459812Shibler     {
177559812Shibler       read_alarm_should_throw = 0;
177659812Shibler       if (! setjmp (read_alarm_throw))
177759812Shibler 	val = (*read_socket_hook) (0, kbd_buffer, 256 * BUFFER_SIZE_FACTOR);
177859812Shibler       else
177959812Shibler 	val = -1;
178059812Shibler     }
178159812Shibler   else
178259812Shibler     val = read (fileno (stdin), kbd_buffer, 1);
178359812Shibler 
178459812Shibler   if (val > 0)
178559812Shibler     {
178659812Shibler       kbd_ptr = kbd_buffer;
178759812Shibler       kbd_count = val;
178859812Shibler     }
178959812Shibler }
179059812Shibler 
179159812Shibler #endif /* not HAVE_SELECT */
179259812Shibler 
179359812Shibler #ifdef BSD4_1
179459812Shibler /* VARARGS */
179559812Shibler setpriority ()
179659812Shibler {
179759812Shibler   return 0;
179859812Shibler }
179959812Shibler 
180059812Shibler /*
180159812Shibler  * Partially emulate 4.2 open call.
180259812Shibler  * open is defined as this in 4.1.
180359812Shibler  *
180459812Shibler  * - added by Michael Bloom @ Citicorp/TTI
180559812Shibler  *
180659812Shibler  */
180759812Shibler 
180859812Shibler int
180959812Shibler sys_open (path, oflag, mode)
181059812Shibler      char *path;
181159812Shibler      int oflag, mode;
181259812Shibler {
181359812Shibler   if (oflag & O_CREAT)
181459812Shibler     return creat (path, mode);
181559812Shibler   else
181659812Shibler     return open (path, oflag);
181759812Shibler }
181859812Shibler 
181959812Shibler init_sigio ()
182059812Shibler {
182159812Shibler   if (noninteractive)
182259812Shibler     return;
182359812Shibler   lmode = LINTRUP | lmode;
182459812Shibler   ioctl (0, TIOCLSET, &lmode);
182559812Shibler }
182659812Shibler 
182759812Shibler reset_sigio ()
182859812Shibler {
182959812Shibler   if (noninteractive)
183059812Shibler     return;
183159812Shibler   lmode = ~LINTRUP & lmode;
183259812Shibler   ioctl (0, TIOCLSET, &lmode);
183359812Shibler }
183459812Shibler 
183559812Shibler request_sigio ()
183659812Shibler {
183759812Shibler   sigrelse (SIGTINT);
183859812Shibler 
183959812Shibler   interrupts_deferred = 0;
184059812Shibler }
184159812Shibler 
184259812Shibler unrequest_sigio ()
184359812Shibler {
184459812Shibler   sighold (SIGTINT);
184559812Shibler 
184659812Shibler   interrupts_deferred = 1;
184759812Shibler }
184859812Shibler 
184959812Shibler /* still inside #ifdef BSD4_1 */
185059812Shibler #ifdef subprocesses
185159812Shibler 
185259812Shibler int sigheld; /* Mask of held signals */
185359812Shibler 
185459812Shibler sigholdx (signum)
185559812Shibler      int signum;
185659812Shibler {
185759812Shibler   sigheld |= sigbit (signum);
185859812Shibler   sighold (signum);
185959812Shibler }
186059812Shibler 
186159812Shibler sigisheld (signum)
186259812Shibler      int signum;
186359812Shibler {
186459812Shibler   sigheld |= sigbit (signum);
186559812Shibler }
186659812Shibler 
186759812Shibler sigunhold (signum)
186859812Shibler      int signum;
186959812Shibler {
187059812Shibler   sigheld &= ~sigbit (signum);
187159812Shibler   sigrelse (signum);
187259812Shibler }
187359812Shibler 
187459812Shibler sigfree ()    /* Free all held signals */
187559812Shibler {
187659812Shibler   int i;
187759812Shibler   for (i = 0; i < NSIG; i++)
187859812Shibler     if (sigheld & sigbit (i))
187959812Shibler       sigrelse (i);
188059812Shibler   sigheld = 0;
188159812Shibler }
188259812Shibler 
188359812Shibler sigbit (i)
188459812Shibler {
188559812Shibler   return 1 << (i - 1);
188659812Shibler }
188759812Shibler #endif /* subprocesses */
188859812Shibler #endif /* BSD4_1 */
188959812Shibler 
189059812Shibler #ifndef BSTRING
189159812Shibler 
189259812Shibler void
189359812Shibler bzero (b, length)
189459812Shibler      register char *b;
189559812Shibler      register int length;
189659812Shibler {
189759812Shibler #ifdef VMS
189859812Shibler   short zero = 0;
189959812Shibler   long max_str = 65535;
190059812Shibler 
190159812Shibler   while (length > max_str) {
190259812Shibler     (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
190359812Shibler     length -= max_str;
190459812Shibler     b += max_str;
190559812Shibler   }
190659812Shibler   (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b);
190759812Shibler #else
190859812Shibler   while (length-- > 0)
190959812Shibler     *b++ = 0;
191059812Shibler #endif /* not VMS */
191159812Shibler }
191259812Shibler 
191359812Shibler /* Saying `void' requires a declaration, above, where bcopy is used
191459812Shibler    and that declaration causes pain for systems where bcopy is a macro.  */
191559812Shibler bcopy (b1, b2, length)
191659812Shibler      register char *b1;
191759812Shibler      register char *b2;
191859812Shibler      register int length;
191959812Shibler {
192059812Shibler #ifdef VMS
192159812Shibler   long max_str = 65535;
192259812Shibler 
192359812Shibler   while (length > max_str) {
192459812Shibler     (void) LIB$MOVC3 (&max_str, b1, b2);
192559812Shibler     length -= max_str;
192659812Shibler     b1 += max_str;
192759812Shibler     b2 += max_str;
192859812Shibler   }
192959812Shibler   (void) LIB$MOVC3 (&length, b1, b2);
193059812Shibler #else
193159812Shibler   while (length-- > 0)
193259812Shibler     *b2++ = *b1++;
193359812Shibler #endif /* not VMS */
193459812Shibler }
193559812Shibler 
193659812Shibler int
193759812Shibler bcmp (b1, b2, length)	/* This could be a macro! */
193859812Shibler      register char *b1;
193959812Shibler      register char *b2;
194059812Shibler      register int length;
194159812Shibler {
194259812Shibler #ifdef VMS
194359812Shibler   struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
194459812Shibler   struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
194559812Shibler 
194659812Shibler   return STR$COMPARE (&src1, &src2);
194759812Shibler #else
194859812Shibler   while (length-- > 0)
194959812Shibler     if (*b1++ != *b2++)
195059812Shibler       return 1;
195159812Shibler 
195259812Shibler   return 0;
195359812Shibler #endif /* not VMS */
195459812Shibler }
195559812Shibler #endif /* not BSTRING */
195659812Shibler 
195759812Shibler #ifdef BSD4_1
195859812Shibler long random ()
195959812Shibler {
196059812Shibler   return (rand ());
196159812Shibler }
196259812Shibler 
196359812Shibler srandom (arg)
196459812Shibler      int arg;
196559812Shibler {
196659812Shibler   srand (arg);
196759812Shibler }
196859812Shibler #endif BSD4_1
196959812Shibler 
197059812Shibler #ifdef HPUX
197159812Shibler #ifdef X11
197259812Shibler #define HAVE_RANDOM
197359812Shibler #endif
197459812Shibler #endif
197559812Shibler 
197659812Shibler #ifdef USG
197759812Shibler #ifndef HAVE_RANDOM
197859812Shibler /*
197959812Shibler  *	The BSD random(3) returns numbers in the range of
198059812Shibler  *	0 to 2e31 - 1.  The USG rand(3C) returns numbers in the
198159812Shibler  *	range of 0 to 2e15 - 1.  This is probably not significant
198259812Shibler  *	in this usage.
198359812Shibler  */
198459812Shibler 
198559812Shibler long
198659812Shibler random ()
198759812Shibler {
198859812Shibler   /* Arrange to return a range centered on zero.  */
198959812Shibler   return rand () - (1 << 14);
199059812Shibler }
199159812Shibler 
199259812Shibler srandom (arg)
199359812Shibler      int arg;
199459812Shibler {
199559812Shibler   srand (arg);
199659812Shibler }
199759812Shibler 
199859812Shibler #endif /* HAVE_RANDOM */
199959812Shibler #endif /* USG */
200059812Shibler 
200159812Shibler 
200259812Shibler #ifdef VMS
200359812Shibler 
200459812Shibler #ifdef getenv
200559812Shibler /* If any place else asks for the TERM variable,
200659812Shibler    allow it to be overridden with the EMACS_TERM variable
200759812Shibler    before attempting to translate the logical name TERM.  As a last
200859812Shibler    resort, ask for VAX C's special idea of the TERM variable.  */
200959812Shibler #undef getenv
201059812Shibler char *
201159812Shibler sys_getenv (name)
201259812Shibler      char *name;
201359812Shibler {
201459812Shibler   register char *val;
201559812Shibler   static char buf[256];
201659812Shibler   static struct dsc$descriptor_s equiv
201759812Shibler     = {sizeof(buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf};
201859812Shibler   static struct dsc$descriptor_s d_name
201959812Shibler     = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
202059812Shibler   short eqlen;
202159812Shibler 
202259812Shibler   if (!strcmp (name, "TERM"))
202359812Shibler     {
202459812Shibler       val = (char *) getenv ("EMACS_TERM");
202559812Shibler       if (val)
202659812Shibler 	return val;
202759812Shibler     }
202859812Shibler 
202959812Shibler   d_name.dsc$w_length = strlen (name);
203059812Shibler   d_name.dsc$a_pointer = name;
203159812Shibler   if (lib$sys_trnlog (&d_name, &eqlen, &equiv) == 1)
203259812Shibler     {
203359812Shibler       char *str = (char *) xmalloc (eqlen + 1);
203459812Shibler       bcopy (buf, str, eqlen);
203559812Shibler       str[eqlen] = '\0';
203659812Shibler       /* This is a storage leak, but a pain to fix.  With luck,
203759812Shibler 	 no one will ever notice.  */
203859812Shibler       return str;
203959812Shibler     }
204059812Shibler   return (char *) getenv (name);
204159812Shibler }
204259812Shibler #endif /* getenv */
204359812Shibler 
204459812Shibler #ifdef abort
204559812Shibler /* Since VMS doesn't believe in core dumps, the only way to debug this beast is
204659812Shibler    to force a call on the debugger from within the image. */
204759812Shibler #undef abort
204859812Shibler sys_abort ()
204959812Shibler {
205059812Shibler   reset_sys_modes ();
205159812Shibler   LIB$SIGNAL (SS$_DEBUG);
205259812Shibler }
205359812Shibler #endif /* abort */
205459812Shibler #endif /* VMS */
205559812Shibler 
205659812Shibler #ifdef VMS
205759812Shibler #ifdef LINK_CRTL_SHARE
205859812Shibler #ifdef SHAREABLE_LIB_BUG
205959812Shibler /* Variables declared noshare and initialized in shareable libraries
206059812Shibler    cannot be shared.  The VMS linker incorrectly forces you to use a private
206159812Shibler    version which is uninitialized... If not for this "feature", we
206259812Shibler    could use the C library definition of sys_nerr and sys_errlist. */
206359812Shibler int sys_nerr = 35;
206459812Shibler char *sys_errlist[] =
206559812Shibler   {
206659812Shibler     "error 0",
206759812Shibler     "not owner",
206859812Shibler     "no such file or directory",
206959812Shibler     "no such process",
207059812Shibler     "interrupted system call",
207159812Shibler     "i/o error",
207259812Shibler     "no such device or address",
207359812Shibler     "argument list too long",
207459812Shibler     "exec format error",
207559812Shibler     "bad file number",
207659812Shibler     "no child process",
207759812Shibler     "no more processes",
207859812Shibler     "not enough memory",
207959812Shibler     "permission denied",
208059812Shibler     "bad address",
208159812Shibler     "block device required",
208259812Shibler     "mount devices busy",
208359812Shibler     "file exists",
208459812Shibler     "cross-device link",
208559812Shibler     "no such device",
208659812Shibler     "not a directory",
208759812Shibler     "is a directory",
208859812Shibler     "invalid argument",
208959812Shibler     "file table overflow",
209059812Shibler     "too many open files",
209159812Shibler     "not a typewriter",
209259812Shibler     "text file busy",
209359812Shibler     "file too big",
209459812Shibler     "no space left on device",
209559812Shibler     "illegal seek",
209659812Shibler     "read-only file system",
209759812Shibler     "too many links",
209859812Shibler     "broken pipe",
209959812Shibler     "math argument",
210059812Shibler     "result too large",
210159812Shibler     "I/O stream empty",
210259812Shibler     "vax/vms specific error code nontranslatable error"
210359812Shibler   };
210459812Shibler #endif /* SHAREABLE_LIB_BUG */
210559812Shibler #endif /* LINK_CRTL_SHARE */
210659812Shibler #endif /* VMS */
210759812Shibler 
210859812Shibler #ifdef INTERRUPTABLE_OPEN
210959812Shibler 
211059812Shibler int
211159812Shibler /* VARARGS 2 */
211259812Shibler sys_open (path, oflag, mode)
211359812Shibler      char *path;
211459812Shibler      int oflag, mode;
211559812Shibler {
211659812Shibler   register int rtnval;
211759812Shibler 
211859812Shibler   while ((rtnval = open (path, oflag, mode)) == -1
211959812Shibler 	 && (errno == EINTR));
212059812Shibler   return (rtnval);
212159812Shibler }
212259812Shibler 
212359812Shibler #endif /* INTERRUPTABLE_OPEN */
212459812Shibler 
212559812Shibler #ifdef INTERRUPTABLE_CLOSE
212659812Shibler 
212759812Shibler sys_close (fd)
212859812Shibler      int fd;
212959812Shibler {
213059812Shibler   register int rtnval;
213159812Shibler 
213259812Shibler   while ((rtnval = close(fd)) == -1
213359812Shibler 	 && (errno == EINTR));
213459812Shibler   return rtnval;
213559812Shibler }
213659812Shibler 
213759812Shibler #endif /* INTERRUPTABLE_CLOSE */
213859812Shibler 
213959812Shibler #ifdef INTERRUPTABLE_IO
214059812Shibler 
214159812Shibler int
214259812Shibler sys_read (fildes, buf, nbyte)
214359812Shibler      int fildes;
214459812Shibler      char *buf;
214559812Shibler      unsigned int nbyte;
214659812Shibler {
214759812Shibler   register int rtnval;
214859812Shibler 
214959812Shibler   while ((rtnval = read (fildes, buf, nbyte)) == -1
215059812Shibler 	 && (errno == EINTR));
215159812Shibler   return (rtnval);
215259812Shibler }
215359812Shibler 
215459812Shibler int
215559812Shibler sys_write (fildes, buf, nbyte)
215659812Shibler      int fildes;
215759812Shibler      char *buf;
215859812Shibler      unsigned int nbyte;
215959812Shibler {
216059812Shibler   register int rtnval;
216159812Shibler 
216259812Shibler   while ((rtnval = write (fildes, buf, nbyte)) == -1
216359812Shibler 	 && (errno == EINTR));
216459812Shibler   return (rtnval);
216559812Shibler }
216659812Shibler 
216759812Shibler #endif /* INTERRUPTABLE_IO */
216859812Shibler 
216959812Shibler #ifdef USG
217059812Shibler /*
217159812Shibler  *	All of the following are for USG.
217259812Shibler  *
217359812Shibler  *	On USG systems the system calls are interruptable by signals
217459812Shibler  *	that the user program has elected to catch.  Thus the system call
217559812Shibler  *	must be retried in these cases.  To handle this without massive
217659812Shibler  *	changes in the source code, we remap the standard system call names
217759812Shibler  *	to names for our own functions in sysdep.c that do the system call
217859812Shibler  *	with retries.  Actually, for portability reasons, it is good
217959812Shibler  *	programming practice, as this example shows, to limit all actual
218059812Shibler  *	system calls to a single occurance in the source.  Sure, this
218159812Shibler  *	adds an extra level of function call overhead but it is almost
218259812Shibler  *	always negligible.   Fred Fish, Unisoft Systems Inc.
218359812Shibler  */
218459812Shibler 
218559812Shibler char *sys_siglist[NSIG + 1] =
218659812Shibler {
218759812Shibler #ifdef AIX
218859812Shibler /* AIX has changed the signals a bit */
218959812Shibler   "bogus signal",			/* 0 */
219059812Shibler   "hangup",				/* 1  SIGHUP */
219159812Shibler   "interrupt",				/* 2  SIGINT */
219259812Shibler   "quit",				/* 3  SIGQUIT */
219359812Shibler   "illegal instruction",		/* 4  SIGILL */
219459812Shibler   "trace trap",				/* 5  SIGTRAP */
219559812Shibler   "IOT instruction",			/* 6  SIGIOT */
219659812Shibler   "crash likely",			/* 7  SIGDANGER */
219759812Shibler   "floating point exception",		/* 8  SIGFPE */
219859812Shibler   "kill",				/* 9  SIGKILL */
219959812Shibler   "bus error",				/* 10 SIGBUS */
220059812Shibler   "segmentation violation",		/* 11 SIGSEGV */
220159812Shibler   "bad argument to system call",	/* 12 SIGSYS */
220259812Shibler   "write on a pipe with no one to read it", /* 13 SIGPIPE */
220359812Shibler   "alarm clock",			/* 14 SIGALRM */
220459812Shibler   "software termination signum",	/* 15 SIGTERM */
220559812Shibler   "user defined signal 1",		/* 16 SIGUSR1 */
220659812Shibler   "user defined signal 2",		/* 17 SIGUSR2 */
220759812Shibler   "death of a child",			/* 18 SIGCLD */
220859812Shibler   "power-fail restart",			/* 19 SIGPWR */
220959812Shibler   "bogus signal",			/* 20 */
221059812Shibler   "bogus signal",			/* 21 */
221159812Shibler   "bogus signal",			/* 22 */
221259812Shibler   "bogus signal",			/* 23 */
221359812Shibler   "bogus signal",			/* 24 */
221459812Shibler   "LAN I/O interrupt",			/* 25 SIGAIO */
221559812Shibler   "PTY I/O interrupt",			/* 26 SIGPTY */
221659812Shibler   "I/O intervention required",		/* 27 SIGIOINT */
221759812Shibler   "HFT grant",				/* 28 SIGGRANT */
221859812Shibler   "HFT retract",			/* 29 SIGRETRACT */
221959812Shibler   "HFT sound done",			/* 30 SIGSOUND */
222059812Shibler   "HFT input ready",			/* 31 SIGMSG */
222159812Shibler #else /* not AIX */
222259812Shibler   "bogus signal",			/* 0 */
222359812Shibler   "hangup",				/* 1  SIGHUP */
222459812Shibler   "interrupt",				/* 2  SIGINT */
222559812Shibler   "quit",				/* 3  SIGQUIT */
222659812Shibler   "illegal instruction",		/* 4  SIGILL */
222759812Shibler   "trace trap",				/* 5  SIGTRAP */
222859812Shibler   "IOT instruction",			/* 6  SIGIOT */
222959812Shibler   "EMT instruction",			/* 7  SIGEMT */
223059812Shibler   "floating point exception",		/* 8  SIGFPE */
223159812Shibler   "kill",				/* 9  SIGKILL */
223259812Shibler   "bus error",				/* 10 SIGBUS */
223359812Shibler   "segmentation violation",		/* 11 SIGSEGV */
223459812Shibler   "bad argument to system call",	/* 12 SIGSYS */
223559812Shibler   "write on a pipe with no one to read it", /* 13 SIGPIPE */
223659812Shibler   "alarm clock",			/* 14 SIGALRM */
223759812Shibler   "software termination signum",	/* 15 SIGTERM */
223859812Shibler   "user defined signal 1",		/* 16 SIGUSR1 */
223959812Shibler   "user defined signal 2",		/* 17 SIGUSR2 */
224059812Shibler   "death of a child",			/* 18 SIGCLD */
224159812Shibler   "power-fail restart",			/* 19 SIGPWR */
224259812Shibler #endif /* not AIX */
224359812Shibler   0
224459812Shibler   };
224559812Shibler 
224659812Shibler /*
224759812Shibler  *	Warning, this function may not duplicate 4.2 action properly
224859812Shibler  *	under error conditions.
224959812Shibler  */
225059812Shibler 
225159812Shibler #ifndef MAXPATHLEN
225259812Shibler /* In 4.1, param.h fails to define this.  */
225359812Shibler #define MAXPATHLEN 1024
225459812Shibler #endif
225559812Shibler 
225659812Shibler #ifndef HAVE_GETWD
225759812Shibler 
225859812Shibler char *
225959812Shibler getwd (pathname)
226059812Shibler      char *pathname;
226159812Shibler {
226259812Shibler   char *npath, *spath;
226359812Shibler   extern char *getcwd ();
226459812Shibler 
226559812Shibler   spath = npath = getcwd ((char *) 0, MAXPATHLEN);
226659812Shibler   /* On Altos 3068, getcwd can return @hostname/dir, so discard
226759812Shibler      up to first slash.  Should be harmless on other systems.  */
226859812Shibler   while (*npath && *npath != '/')
226959812Shibler     npath++;
227059812Shibler   strcpy (pathname, npath);
227159812Shibler   free (spath);			/* getcwd uses malloc */
227259812Shibler   return pathname;
227359812Shibler }
227459812Shibler 
227559812Shibler #endif HAVE_GETWD
227659812Shibler 
227759812Shibler #ifndef HAVE_RENAME
227859812Shibler 
227959812Shibler /*
228059812Shibler  *	Emulate rename using unlink/link.  Note that this is
228159812Shibler  *	only partially correct.  Also, doesn't enforce restriction
228259812Shibler  *	that files be of same type (regular->regular, dir->dir, etc).
228359812Shibler  */
228459812Shibler 
228559812Shibler rename (from, to)
228659812Shibler      char *from;
228759812Shibler      char *to;
228859812Shibler {
228959812Shibler   if (access (from, 0) == 0)
229059812Shibler     {
229159812Shibler       unlink (to);
229259812Shibler       if (link (from, to) == 0)
229359812Shibler 	if (unlink (from) == 0)
229459812Shibler 	  return (0);
229559812Shibler     }
229659812Shibler   return (-1);
229759812Shibler }
229859812Shibler #endif /* not HAVE_RENAME */
229959812Shibler 
230059812Shibler /* VARARGS */
230159812Shibler setpriority ()
230259812Shibler {
230359812Shibler   return (0);
230459812Shibler }
230559812Shibler 
230659812Shibler #ifndef HAVE_VFORK
230759812Shibler 
230859812Shibler /*
230959812Shibler  *	Substitute fork(2) for vfork(2) on USG flavors.
231059812Shibler  */
231159812Shibler 
231259812Shibler vfork ()
231359812Shibler {
231459812Shibler   return (fork ());
231559812Shibler }
231659812Shibler 
231759812Shibler #endif /* not HAVE_VFORK */
231859812Shibler 
231959812Shibler #ifdef MISSING_UTIMES
232059812Shibler 
232159812Shibler /* HPUX (among others) sets HAVE_TIMEVAL but does not implement utimes.  */
232259812Shibler 
232359812Shibler utimes ()
232459812Shibler {
232559812Shibler }
232659812Shibler #endif
232759812Shibler 
232859812Shibler #ifdef IRIS_UTIME
232959812Shibler 
233059812Shibler /* The IRIS (3.5) has timevals, but uses sys V utime, and doesn't have the
233159812Shibler    utimbuf structure defined anywhere but in the man page. */
233259812Shibler 
233359812Shibler struct utimbuf
233459812Shibler  {
233559812Shibler    long actime;
233659812Shibler    long modtime;
233759812Shibler  };
233859812Shibler 
233959812Shibler utimes (name, tvp)
234059812Shibler      char *name;
234159812Shibler      struct timeval tvp[];
234259812Shibler {
234359812Shibler   struct utimbuf utb;
234459812Shibler   utb.actime  = tvp[0].tv_sec;
234559812Shibler   utb.modtime = tvp[1].tv_sec;
234659812Shibler   utime (name, &utb);
234759812Shibler }
234859812Shibler #endif /* IRIS_UTIME */
234959812Shibler 
235059812Shibler 
235159812Shibler #if 0
235259812Shibler #ifdef HPUX
235359812Shibler 
235459812Shibler /* HPUX curses library references perror, but as far as we know
235559812Shibler    it won't be called.  Anyway this definition will do for now.  */
235659812Shibler 
235759812Shibler perror ()
235859812Shibler {
235959812Shibler }
236059812Shibler 
236159812Shibler #endif /* HPUX */
236259812Shibler #endif /* 0 */
236359812Shibler 
236459812Shibler #ifndef HAVE_DUP2
236559812Shibler 
236659812Shibler /*
236759812Shibler  *	Emulate BSD dup2(2).  First close newd if it already exists.
236859812Shibler  *	Then, attempt to dup oldd.  If not successful, call dup2 recursively
236959812Shibler  *	until we are, then close the unsuccessful ones.
237059812Shibler  */
237159812Shibler 
237259812Shibler dup2 (oldd, newd)
237359812Shibler      int oldd;
237459812Shibler      int newd;
237559812Shibler {
237659812Shibler   register int fd;
237759812Shibler 
237859812Shibler   sys_close (newd);
237959812Shibler 
238059812Shibler #ifdef F_DUPFD
238159812Shibler   fd = fcntl (oldd, F_DUPFD, newd);
238259812Shibler   if (fd != newd)
238359812Shibler     error ("cant dup2(%i,%i) : %s", oldd, newd, sys_errlist[errno]);
238459812Shibler #else
238559812Shibler   while ((fd = dup (oldd)) != newd)
238659812Shibler     {
238759812Shibler       dup2 (oldd, newd);
238859812Shibler       sys_close (fd);
238959812Shibler     }
239059812Shibler #endif
239159812Shibler }
239259812Shibler 
239359812Shibler #endif /* not HAVE_DUP2 */
239459812Shibler 
239559812Shibler /*
239659812Shibler  *	Gettimeofday.  Simulate as much as possible.  Only accurate
239759812Shibler  *	to nearest second.  Emacs doesn't use tzp so ignore it for now.
239859812Shibler  *	Only needed when subprocesses are defined.
239959812Shibler  */
240059812Shibler 
240159812Shibler #ifdef subprocesses
240259812Shibler #ifndef HAVE_GETTIMEOFDAY
240359812Shibler #ifdef HAVE_TIMEVAL
240459812Shibler 
240559812Shibler /* ARGSUSED */
240659812Shibler gettimeofday (tp, tzp)
240759812Shibler      struct timeval *tp;
240859812Shibler      struct timezone *tzp;
240959812Shibler {
241059812Shibler   extern long time ();
241159812Shibler 
241259812Shibler   tp->tv_sec = time ((long *)0);
241359812Shibler   tp->tv_usec = 0;
241459812Shibler }
241559812Shibler 
241659812Shibler #endif
241759812Shibler #endif
241859812Shibler #endif /* subprocess && !HAVE_GETTIMEOFDAY && HAVE_TIMEVAL */
241959812Shibler 
242059812Shibler /*
242159812Shibler  *	This function will go away as soon as all the stubs fixed. (fnf)
242259812Shibler  */
242359812Shibler 
242459812Shibler croak (badfunc)
242559812Shibler      char *badfunc;
242659812Shibler {
242759812Shibler   printf ("%s not yet implemented\r\n", badfunc);
242859812Shibler   reset_sys_modes ();
242959812Shibler   exit (1);
243059812Shibler }
243159812Shibler 
243259812Shibler #endif /* USG */
243359812Shibler 
243459812Shibler /* Directory routines for systems that don't have them. */
243559812Shibler 
243659812Shibler #ifdef SYSV_SYSTEM_DIR
243759812Shibler 
243859812Shibler #include <dirent.h>
243959812Shibler 
244059812Shibler #ifndef HAVE_CLOSEDIR
244159812Shibler int
244259812Shibler closedir (dirp)
244359812Shibler      register DIR *dirp;              /* stream from opendir() */
244459812Shibler {
244559812Shibler   sys_close (dirp->dd_fd);
244659812Shibler   free ((char *) dirp->dd_buf);       /* directory block defined in <dirent.h> */
244759812Shibler   free ((char *) dirp);
244859812Shibler }
244959812Shibler #endif /* not HAVE_CLOSEDIR */
245059812Shibler 
245159812Shibler #endif /* SYSV_SYSTEM_DIR */
245259812Shibler 
245359812Shibler #ifdef NONSYSTEM_DIR_LIBRARY
245459812Shibler 
245559812Shibler DIR *
245659812Shibler opendir (filename)
245759812Shibler      char *filename;	/* name of directory */
245859812Shibler {
245959812Shibler   register DIR *dirp;		/* -> malloc'ed storage */
246059812Shibler   register int fd;		/* file descriptor for read */
246159812Shibler   struct stat sbuf;		/* result of fstat() */
246259812Shibler 
246359812Shibler   fd = sys_open (filename, 0);
246459812Shibler   if (fd < 0)
246559812Shibler     return 0;
246659812Shibler 
246759812Shibler   if (fstat (fd, &sbuf) < 0
246859812Shibler       || (sbuf.st_mode & S_IFMT) != S_IFDIR
246959812Shibler       || (dirp = (DIR *) malloc (sizeof (DIR))) == 0)
247059812Shibler     {
247159812Shibler       sys_close (fd);
247259812Shibler       return 0;		/* bad luck today */
247359812Shibler     }
247459812Shibler 
247559812Shibler   dirp->dd_fd = fd;
247659812Shibler   dirp->dd_loc = dirp->dd_size = 0;	/* refill needed */
247759812Shibler 
247859812Shibler   return dirp;
247959812Shibler }
248059812Shibler 
248159812Shibler void
248259812Shibler closedir (dirp)
248359812Shibler      register DIR *dirp;		/* stream from opendir() */
248459812Shibler {
248559812Shibler   sys_close (dirp->dd_fd);
248659812Shibler   free ((char *) dirp);
248759812Shibler }
248859812Shibler 
248959812Shibler 
249059812Shibler #ifndef VMS
249159812Shibler #define DIRSIZ	14
249259812Shibler struct olddir
249359812Shibler   {
249459812Shibler     ino_t od_ino; 		/* inode */
249559812Shibler     char od_name[DIRSIZ];	/* filename */
249659812Shibler   };
249759812Shibler #endif /* not VMS */
249859812Shibler 
249959812Shibler struct direct dir_static;	/* simulated directory contents */
250059812Shibler 
250159812Shibler /* ARGUSED */
250259812Shibler struct direct *
250359812Shibler readdir (dirp)
250459812Shibler      register DIR *dirp;	/* stream from opendir() */
250559812Shibler {
250659812Shibler #ifndef VMS
250759812Shibler   register struct olddir *dp;	/* -> directory data */
250859812Shibler #else /* VMS */
250959812Shibler   register struct dir$_name *dp; /* -> directory data */
251059812Shibler   register struct dir$_version *dv; /* -> version data */
251159812Shibler #endif /* VMS */
251259812Shibler 
251359812Shibler   for (; ;)
251459812Shibler     {
251559812Shibler       if (dirp->dd_loc >= dirp->dd_size)
251659812Shibler 	dirp->dd_loc = dirp->dd_size = 0;
251759812Shibler 
251859812Shibler       if (dirp->dd_size == 0 	/* refill buffer */
251959812Shibler 	  && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
252059812Shibler 	return 0;
252159812Shibler 
252259812Shibler #ifndef VMS
252359812Shibler       dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc];
252459812Shibler       dirp->dd_loc += sizeof (struct olddir);
252559812Shibler 
252659812Shibler       if (dp->od_ino != 0)	/* not deleted entry */
252759812Shibler 	{
252859812Shibler 	  dir_static.d_ino = dp->od_ino;
252959812Shibler 	  strncpy (dir_static.d_name, dp->od_name, DIRSIZ);
253059812Shibler 	  dir_static.d_name[DIRSIZ] = '\0';
253159812Shibler 	  dir_static.d_namlen = strlen (dir_static.d_name);
253259812Shibler 	  dir_static.d_reclen = sizeof (struct direct)
253359812Shibler 	    - MAXNAMLEN + 3
253459812Shibler 	      + dir_static.d_namlen - dir_static.d_namlen % 4;
253559812Shibler 	  return &dir_static;	/* -> simulated structure */
253659812Shibler 	}
253759812Shibler #else /* VMS */
253859812Shibler       dp = (struct dir$_name *) dirp->dd_buf;
253959812Shibler       if (dirp->dd_loc == 0)
254059812Shibler 	dirp->dd_loc = (dp->dir$b_namecount&1) ? dp->dir$b_namecount + 1
254159812Shibler 	  : dp->dir$b_namecount;
254259812Shibler       dv = (struct dir$_version *)&dp->dir$t_name[dirp->dd_loc];
254359812Shibler       dir_static.d_ino = dv->dir$w_fid_num;
254459812Shibler       dir_static.d_namlen = dp->dir$b_namecount;
254559812Shibler       dir_static.d_reclen = sizeof (struct direct)
254659812Shibler 	- MAXNAMLEN + 3
254759812Shibler 	  + dir_static.d_namlen - dir_static.d_namlen % 4;
254859812Shibler       strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
254959812Shibler       dir_static.d_name[dir_static.d_namlen] = '\0';
255059812Shibler       dirp->dd_loc = dirp->dd_size; /* only one record at a time */
255159812Shibler       return &dir_static;
255259812Shibler #endif /* VMS */
255359812Shibler     }
255459812Shibler }
255559812Shibler 
255659812Shibler #ifdef VMS
255759812Shibler /* readdirver is just like readdir except it returns all versions of a file
255859812Shibler    as separate entries.  */
255959812Shibler 
256059812Shibler /* ARGUSED */
256159812Shibler struct direct *
256259812Shibler readdirver (dirp)
256359812Shibler      register DIR *dirp;	/* stream from opendir() */
256459812Shibler {
256559812Shibler   register struct dir$_name *dp; /* -> directory data */
256659812Shibler   register struct dir$_version *dv; /* -> version data */
256759812Shibler 
256859812Shibler   if (dirp->dd_loc >= dirp->dd_size - sizeof (struct dir$_name))
256959812Shibler     dirp->dd_loc = dirp->dd_size = 0;
257059812Shibler 
257159812Shibler   if (dirp->dd_size == 0 	/* refill buffer */
257259812Shibler       && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0)
257359812Shibler     return 0;
257459812Shibler 
257559812Shibler   dp = (struct dir$_name *) dirp->dd_buf;
257659812Shibler   if (dirp->dd_loc == 0)
257759812Shibler     dirp->dd_loc = (dp->dir$b_namecount & 1) ? dp->dir$b_namecount + 1
257859812Shibler 		   : dp->dir$b_namecount;
257959812Shibler   dv = (struct dir$_version *) &dp->dir$t_name[dirp->dd_loc];
258059812Shibler   strncpy (dir_static.d_name, dp->dir$t_name, dp->dir$b_namecount);
258159812Shibler   sprintf (&dir_static.d_name[dp->dir$b_namecount], ";%d", dv->dir$w_version);
258259812Shibler   dir_static.d_namlen = strlen (dir_static.d_name);
258359812Shibler   dir_static.d_ino = dv->dir$w_fid_num;
258459812Shibler   dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3
258559812Shibler 			+ dir_static.d_namlen - dir_static.d_namlen % 4;
258659812Shibler   dirp->dd_loc = ((char *) (++dv) - dp->dir$t_name);
258759812Shibler   return &dir_static;
258859812Shibler }
258959812Shibler 
259059812Shibler #endif /* VMS */
259159812Shibler 
259259812Shibler #endif /* NONSYSTEM_DIR_LIBRARY */
259359812Shibler 
259459812Shibler /* Functions for VMS */
259559812Shibler #ifdef VMS
259659812Shibler #include <pwd.h>
259759812Shibler #include <acldef.h>
259859812Shibler #include <chpdef.h>
259959812Shibler #include <jpidef.h>
260059812Shibler 
260159812Shibler /* Return as a string the VMS error string pertaining to STATUS.
260259812Shibler    Reuses the same static buffer each time it is called.  */
260359812Shibler 
260459812Shibler char *
260559812Shibler vmserrstr (status)
260659812Shibler      int status;		/* VMS status code */
260759812Shibler {
260859812Shibler   int bufadr[2];
260959812Shibler   short len;
261059812Shibler   static char buf[257];
261159812Shibler 
261259812Shibler   bufadr[0] = sizeof buf - 1;
261359812Shibler   bufadr[1] = buf;
261459812Shibler   if (! (SYS$GETMSG (status, &len, bufadr, 0x1, 0) & 1))
261559812Shibler     return "untranslatable VMS error status";
261659812Shibler   buf[len] = '\0';
261759812Shibler   return buf;
261859812Shibler }
261959812Shibler 
262059812Shibler #ifdef access
262159812Shibler #undef access
262259812Shibler 
262359812Shibler /* The following is necessary because 'access' emulation by VMS C (2.0) does
262459812Shibler  * not work correctly.  (It also doesn't work well in version 2.3.)
262559812Shibler  */
262659812Shibler 
262759812Shibler #ifdef VMS4_4
262859812Shibler 
262959812Shibler #define DESCRIPTOR(name,string) struct dsc$descriptor_s name = \
263059812Shibler 	{ strlen(string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string }
263159812Shibler 
263259812Shibler typedef union {
263359812Shibler     struct {
263459812Shibler 	unsigned short s_buflen;
263559812Shibler 	unsigned short s_code;
263659812Shibler 	char *s_bufadr;
263759812Shibler 	unsigned short *s_retlenadr;
263859812Shibler     } s;
263959812Shibler     int end;
264059812Shibler } item;
264159812Shibler #define buflen s.s_buflen
264259812Shibler #define code s.s_code
264359812Shibler #define bufadr s.s_bufadr
264459812Shibler #define retlenadr s.s_retlenadr
264559812Shibler 
264659812Shibler #define R_OK 4	/* test for read permission */
264759812Shibler #define W_OK 2	/* test for write permission */
264859812Shibler #define X_OK 1	/* test for execute (search) permission */
264959812Shibler #define F_OK 0	/* test for presence of file */
265059812Shibler 
265159812Shibler int
265259812Shibler sys_access (path, mode)
265359812Shibler      char *path;
265459812Shibler      int mode;
265559812Shibler {
265659812Shibler   static char *user = NULL;
265759812Shibler   char dir_fn[512];
265859812Shibler 
265959812Shibler   /* translate possible directory spec into .DIR file name, so brain-dead
266059812Shibler    * access() can treat the directory like a file.  */
266159812Shibler   if (directory_file_name (path, dir_fn))
266259812Shibler     path = dir_fn;
266359812Shibler 
266459812Shibler   if (mode == F_OK)
266559812Shibler     return access (path, mode);
266659812Shibler   if (user == NULL && (user = getenv ("USER")) == NULL)
266759812Shibler     return -1;
266859812Shibler   {
266959812Shibler 	int stat;
267059812Shibler 	int flags;
267159812Shibler 	int acces;
267259812Shibler 	int dummy;
267359812Shibler 	item itemlst[3];
267459812Shibler 	DESCRIPTOR(path_desc, path);
267559812Shibler 	DESCRIPTOR(user_desc, user);
267659812Shibler 
267759812Shibler 	flags = 0;
267859812Shibler 	acces = 0;
267959812Shibler 	if ((mode & X_OK) && ((stat = access(path, mode)) < 0 || mode == X_OK))
268059812Shibler 	    return stat;
268159812Shibler 	if (mode & R_OK)
268259812Shibler 	    acces |= CHP$M_READ;
268359812Shibler 	if (mode & W_OK)
268459812Shibler 	    acces |= CHP$M_WRITE;
268559812Shibler 	itemlst[0].buflen = sizeof (int);
268659812Shibler 	itemlst[0].code = CHP$_FLAGS;
268759812Shibler 	itemlst[0].bufadr = &flags;
268859812Shibler 	itemlst[0].retlenadr = &dummy;
268959812Shibler 	itemlst[1].buflen = sizeof (int);
269059812Shibler 	itemlst[1].code = CHP$_ACCESS;
269159812Shibler 	itemlst[1].bufadr = &acces;
269259812Shibler 	itemlst[1].retlenadr = &dummy;
269359812Shibler 	itemlst[2].end = CHP$_END;
269459812Shibler 	stat = SYS$CHECK_ACCESS(&ACL$C_FILE, &path_desc, &user_desc, itemlst);
269559812Shibler 	return stat == SS$_NORMAL ? 0 : -1;
269659812Shibler     }
269759812Shibler }
269859812Shibler 
269959812Shibler #else /* not VMS4_4 */
270059812Shibler 
270159812Shibler #include <prvdef.h>
270259812Shibler #define	ACE$M_WRITE	2
270359812Shibler #define	ACE$C_KEYID	1
270459812Shibler 
270559812Shibler static unsigned short memid, grpid;
270659812Shibler static unsigned int uic;
270759812Shibler 
270859812Shibler /* Called from init_sys_modes, so it happens not very often
270959812Shibler    but at least each time Emacs is loaded.  */
271059812Shibler sys_access_reinit ()
271159812Shibler {
271259812Shibler   uic = 0;
271359812Shibler }
271459812Shibler 
271559812Shibler int
271659812Shibler sys_access (filename, type)
271759812Shibler      char * filename;
271859812Shibler      int type;
271959812Shibler {
272059812Shibler   struct FAB fab;
272159812Shibler   struct XABPRO xab;
272259812Shibler   int status, prvmask[2], size, i, typecode, acl_controlled;
272359812Shibler   unsigned int *aclptr, *aclend, aclbuf[60];
272459812Shibler 
272559812Shibler   /* Get UIC and GRP values for protection checking.  */
272659812Shibler   if (uic == 0)
272759812Shibler     {
272859812Shibler       status = LIB$GETJPI (&JPI$_UIC, 0, 0, &uic, 0, 0);
272959812Shibler       if (! (status & 1))
273059812Shibler 	return -1;
273159812Shibler       memid = uic & 0xFFFF;
273259812Shibler       grpid = uic >> 16;
273359812Shibler     }
273459812Shibler 
273559812Shibler   if (type != 2)		/* not checking write access */
273659812Shibler     return access (filename, type);
273759812Shibler 
273859812Shibler   /* Check write protection. */
273959812Shibler 
274059812Shibler #define	CHECKPRIV(bit)    (prvmask[bit / 32] & (1 << (bit % 32)))
274159812Shibler #define	WRITEABLE(field)  (! ((xab.xab$w_pro >> field) & XAB$M_NOWRITE))
274259812Shibler 
274359812Shibler   /* Find privilege bits */
274459812Shibler   status = sys$setprv (0, 0, 0, prvmask);
274559812Shibler   if (! (status & 1))
274659812Shibler     error ("Unable to find privileges: %s", vmserrstr (status));
274759812Shibler   if (CHECKPRIV (PRV$V_BYPASS))
274859812Shibler     return 0;			/* BYPASS enabled */
274959812Shibler   fab = cc$rms_fab;
275059812Shibler   fab.fab$b_fac = FAB$M_GET;
275159812Shibler   fab.fab$l_fna = filename;
275259812Shibler   fab.fab$b_fns = strlen (filename);
275359812Shibler   fab.fab$l_xab = &xab;
275459812Shibler   xab = cc$rms_xabpro;
275559812Shibler   xab.xab$l_aclbuf = aclbuf;
275659812Shibler   xab.xab$w_aclsiz = sizeof (aclbuf);
275759812Shibler   status = sys$open (&fab, 0, 0);
275859812Shibler   if (! (status & 1))
275959812Shibler     return -1;
276059812Shibler   sys$close (&fab, 0, 0);
276159812Shibler   /* Check system access */
276259812Shibler   if (CHECKPRIV (PRV$V_SYSPRV) && WRITEABLE (XAB$V_SYS))
276359812Shibler     return 0;
276459812Shibler   /* Check ACL entries, if any */
276559812Shibler   acl_controlled = 0;
276659812Shibler   if (xab.xab$w_acllen > 0)
276759812Shibler     {
276859812Shibler       aclptr = aclbuf;
276959812Shibler       aclend = &aclbuf[xab.xab$w_acllen / 4];
277059812Shibler       while (*aclptr && aclptr < aclend)
277159812Shibler 	{
277259812Shibler 	  size = (*aclptr & 0xff) / 4;
277359812Shibler 	  typecode = (*aclptr >> 8) & 0xff;
277459812Shibler 	  if (typecode == ACE$C_KEYID)
277559812Shibler 	    for (i = size - 1; i > 1; i--)
277659812Shibler 	      if (aclptr[i] == uic)
277759812Shibler 		{
277859812Shibler 		  acl_controlled = 1;
277959812Shibler 		  if (aclptr[1] & ACE$M_WRITE)
278059812Shibler 		    return 0;	/* Write access through ACL */
278159812Shibler 		}
278259812Shibler 	  aclptr = &aclptr[size];
278359812Shibler 	}
278459812Shibler       if (acl_controlled)	/* ACL specified, prohibits write access */
278559812Shibler 	return -1;
278659812Shibler     }
278759812Shibler   /* No ACL entries specified, check normal protection */
278859812Shibler   if (WRITEABLE (XAB$V_WLD))	/* World writeable */
278959812Shibler     return 0;
279059812Shibler   if (WRITEABLE (XAB$V_GRP) &&
279159812Shibler       (unsigned short) (xab.xab$l_uic >> 16) == grpid)
279259812Shibler     return 0;			/* Group writeable */
279359812Shibler   if (WRITEABLE (XAB$V_OWN) &&
279459812Shibler       (xab.xab$l_uic & 0xFFFF) == memid)
279559812Shibler     return 0;			/* Owner writeable */
279659812Shibler 
279759812Shibler   return -1;	/* Not writeable */
279859812Shibler }
279959812Shibler #endif /* not VMS4_4 */
280059812Shibler #endif /* access */
280159812Shibler 
280259812Shibler static char vtbuf[NAM$C_MAXRSS+1];
280359812Shibler 
280459812Shibler /* translate a vms file spec to a unix path */
280559812Shibler char *
280659812Shibler sys_translate_vms (vfile)
280759812Shibler      char * vfile;
280859812Shibler {
280959812Shibler   char * p;
281059812Shibler   char * targ;
281159812Shibler 
281259812Shibler   if (!vfile)
281359812Shibler     return 0;
281459812Shibler 
281559812Shibler   targ = vtbuf;
281659812Shibler 
281759812Shibler   /* leading device or logical name is a root directory */
281859812Shibler   if (p = strchr (vfile, ':'))
281959812Shibler     {
282059812Shibler       *targ++ = '/';
282159812Shibler       while (vfile < p)
282259812Shibler 	*targ++ = *vfile++;
282359812Shibler       vfile++;
282459812Shibler       *targ++ = '/';
282559812Shibler     }
282659812Shibler   p = vfile;
282759812Shibler   if (*p == '[' || *p == '<')
282859812Shibler     {
282959812Shibler       while (*++vfile != *p + 2)
283059812Shibler 	switch (*vfile)
283159812Shibler 	  {
283259812Shibler 	  case '.':
283359812Shibler 	    if (vfile[-1] == *p)
283459812Shibler 	      *targ++ = '.';
283559812Shibler 	    *targ++ = '/';
283659812Shibler 	    break;
283759812Shibler 
283859812Shibler 	  case '-':
283959812Shibler 	    *targ++ = '.';
284059812Shibler 	    *targ++ = '.';
284159812Shibler 	    break;
284259812Shibler 
284359812Shibler 	  default:
284459812Shibler 	    *targ++ = *vfile;
284559812Shibler 	    break;
284659812Shibler 	  }
284759812Shibler       vfile++;
284859812Shibler       *targ++ = '/';
284959812Shibler     }
285059812Shibler   while (*vfile)
285159812Shibler     *targ++ = *vfile++;
285259812Shibler 
285359812Shibler   return vtbuf;
285459812Shibler }
285559812Shibler 
285659812Shibler static char utbuf[NAM$C_MAXRSS+1];
285759812Shibler 
285859812Shibler /* translate a unix path to a VMS file spec */
285959812Shibler char *
286059812Shibler sys_translate_unix (ufile)
286159812Shibler      char * ufile;
286259812Shibler {
286359812Shibler   int slash_seen = 0;
286459812Shibler   char *p;
286559812Shibler   char * targ;
286659812Shibler 
286759812Shibler   if (!ufile)
286859812Shibler     return 0;
286959812Shibler 
287059812Shibler   targ = utbuf;
287159812Shibler 
287259812Shibler   if (*ufile == '/')
287359812Shibler     {
287459812Shibler       ufile++;
287559812Shibler     }
287659812Shibler 
287759812Shibler   while (*ufile)
287859812Shibler     {
287959812Shibler       switch (*ufile)
288059812Shibler 	{
288159812Shibler 	case '/':
288259812Shibler 	  if (slash_seen)
288359812Shibler 	    if (index (&ufile[1], '/'))
288459812Shibler 	      *targ++ = '.';
288559812Shibler 	    else
288659812Shibler 	      *targ++ = ']';
288759812Shibler 	  else
288859812Shibler 	    {
288959812Shibler 	      *targ++ = ':';
289059812Shibler 	      if (index (&ufile[1], '/'))
289159812Shibler 		*targ++ = '[';
289259812Shibler 	      slash_seen = 1;
289359812Shibler 	    }
289459812Shibler 	  break;
289559812Shibler 
289659812Shibler 	case '.':
289759812Shibler 	  if (strncmp (ufile, "./", 2) == 0)
289859812Shibler 	    {
289959812Shibler 	      if (!slash_seen)
290059812Shibler 		{
290159812Shibler 		  *targ++ = '[';
290259812Shibler 		  slash_seen = 1;
290359812Shibler 		}
290459812Shibler 	      ufile++;		/* skip the dot */
290559812Shibler 	      if (index (&ufile[1], '/'))
290659812Shibler 		*targ++ = '.';
290759812Shibler 	      else
290859812Shibler 		*targ++ = ']';
290959812Shibler 	    }
291059812Shibler 	  else if (strncmp (ufile, "../", 3) == 0)
291159812Shibler 	    {
291259812Shibler 	      if (!slash_seen)
291359812Shibler 		{
291459812Shibler 		  *targ++ = '[';
291559812Shibler 		  slash_seen = 1;
291659812Shibler 		}
291759812Shibler 	      *targ++ = '-';
291859812Shibler 	      ufile += 2;	/* skip the dots */
291959812Shibler 	      if (index (&ufile[1], '/'))
292059812Shibler 		*targ++ = '.';
292159812Shibler 	      else
292259812Shibler 		*targ++ = ']';
292359812Shibler 	    }
292459812Shibler 	  else
292559812Shibler 	    *targ++ = *ufile;
292659812Shibler 	  break;
292759812Shibler 
292859812Shibler 	default:
292959812Shibler 	  *targ++ = *ufile;
293059812Shibler 	  break;
293159812Shibler 	}
293259812Shibler       ufile++;
293359812Shibler     }
293459812Shibler   *targ = '\0';
293559812Shibler 
293659812Shibler   return utbuf;
293759812Shibler }
293859812Shibler 
293959812Shibler char *
294059812Shibler getwd (pathname)
294159812Shibler      char *pathname;
294259812Shibler {
294359812Shibler   char *ptr;
294459812Shibler   strcpy (pathname, egetenv ("PATH"));
294559812Shibler 
294659812Shibler   ptr = pathname;
294759812Shibler   while (*ptr)
294859812Shibler     {
294959812Shibler       if ('a' <= *ptr && *ptr <= 'z')
295059812Shibler 	*ptr -= 040;
295159812Shibler       ptr++;
295259812Shibler     }
295359812Shibler   return pathname;
295459812Shibler }
295559812Shibler 
295659812Shibler getppid ()
295759812Shibler {
295859812Shibler   long item_code = JPI$_OWNER;
295959812Shibler   unsigned long parent_id;
296059812Shibler   int status;
296159812Shibler 
296259812Shibler   if (((status = LIB$GETJPI (&item_code, 0, 0, &parent_id)) & 1) == 0)
296359812Shibler     {
296459812Shibler       errno = EVMSERR;
296559812Shibler       vaxc$errno = status;
296659812Shibler       return -1;
296759812Shibler     }
296859812Shibler   return parent_id;
296959812Shibler }
297059812Shibler 
297159812Shibler #undef getuid
297259812Shibler unsigned
297359812Shibler sys_getuid ()
297459812Shibler {
297559812Shibler   return (getgid () << 16) | getuid ();
297659812Shibler }
297759812Shibler 
297859812Shibler int
297959812Shibler sys_read (fildes, buf, nbyte)
298059812Shibler      int fildes;
298159812Shibler      char *buf;
298259812Shibler      unsigned int nbyte;
298359812Shibler {
298459812Shibler   return read (fildes, buf, (nbyte < MAXIOSIZE ? nbyte : MAXIOSIZE));
298559812Shibler }
298659812Shibler 
298759812Shibler #if 0
298859812Shibler int
298959812Shibler sys_write (fildes, buf, nbyte)
299059812Shibler      int fildes;
299159812Shibler      char *buf;
299259812Shibler      unsigned int nbyte;
299359812Shibler {
299459812Shibler   register int nwrote, rtnval = 0;
299559812Shibler 
299659812Shibler   while (nbyte > MAXIOSIZE && (nwrote = write (fildes, buf, MAXIOSIZE)) > 0) {
299759812Shibler     nbyte -= nwrote;
299859812Shibler     buf += nwrote;
299959812Shibler     rtnval += nwrote;
300059812Shibler   }
300159812Shibler   if (nwrote < 0)
300259812Shibler     return rtnval ? rtnval : -1;
300359812Shibler   if ((nwrote = write (fildes, buf, nbyte)) < 0)
300459812Shibler     return rtnval ? rtnval : -1;
300559812Shibler   return (rtnval + nwrote);
300659812Shibler }
300759812Shibler #endif /* 0 */
300859812Shibler 
300959812Shibler /*
301059812Shibler  *	VAX/VMS VAX C RTL really loses. It insists that records
301159812Shibler  *      end with a newline (carriage return) character, and if they
301259812Shibler  *	don't it adds one (nice of it isn't it!)
301359812Shibler  *
301459812Shibler  *	Thus we do this stupidity below.
301559812Shibler  */
301659812Shibler 
301759812Shibler int
301859812Shibler sys_write (fildes, buf, nbytes)
301959812Shibler      int fildes;
302059812Shibler      char *buf;
302159812Shibler      unsigned int nbytes;
302259812Shibler {
302359812Shibler   register char *p;
302459812Shibler   register char *e;
302559812Shibler   int retval, sum;
302659812Shibler   p = buf;
302759812Shibler   sum = 0;
302859812Shibler   while (nbytes > 0)
302959812Shibler     {
303059812Shibler       e =  p + min (MAXIOSIZE, nbytes) - 1;
303159812Shibler       while (*e != '\n' && e > p) e--;
303259812Shibler       if (p == e)		/* Ok.. so here we add a newline... sigh. */
303359812Shibler 	e = p + min (MAXIOSIZE, nbytes) - 1;
303459812Shibler       retval = write (fildes, p, e - p + 1);
303559812Shibler       if (retval != e - p + 1) return -1;
303659812Shibler       p = e + 1;
303759812Shibler       sum = sum + retval;
303859812Shibler       nbytes -= retval;
303959812Shibler     }
304059812Shibler   return sum;
304159812Shibler }
304259812Shibler 
304359812Shibler /* Create file NEW copying its attributes from file OLD.  If
304459812Shibler    OLD is 0 or does not exist, create based on the value of
304559812Shibler    vms_stmlf_recfm. */
304659812Shibler 
304759812Shibler int
304859812Shibler creat_copy_attrs (old, new)
304959812Shibler      char *old, *new;
305059812Shibler {
305159812Shibler   struct FAB fab = cc$rms_fab;
305259812Shibler   struct XABPRO xabpro;
305359812Shibler   char aclbuf[256];	/* Choice of size is arbitrary.  See below. */
305459812Shibler   extern int vms_stmlf_recfm;
305559812Shibler 
305659812Shibler   if (old)
305759812Shibler     {
305859812Shibler       fab.fab$b_fac = FAB$M_GET;
305959812Shibler       fab.fab$l_fna = old;
306059812Shibler       fab.fab$b_fns = strlen (old);
306159812Shibler       fab.fab$l_xab = &xabpro;
306259812Shibler       xabpro = cc$rms_xabpro;
306359812Shibler       xabpro.xab$l_aclbuf = aclbuf;
306459812Shibler       xabpro.xab$w_aclsiz = sizeof aclbuf;
306559812Shibler       /* Call $OPEN to fill in the fab & xabpro fields. */
306659812Shibler       if (sys$open (&fab, 0, 0) & 1)
306759812Shibler 	{
306859812Shibler 	  sys$close (&fab, 0, 0);
306959812Shibler 	  fab.fab$l_alq = 0;	/* zero the allocation quantity */
307059812Shibler 	  if (xabpro.xab$w_acllen > 0)
307159812Shibler 	    {
307259812Shibler 	      if (xabpro.xab$w_acllen > sizeof aclbuf)
307359812Shibler 		/* If the acl buffer was too short, redo open with longer one.
307459812Shibler 		   Wouldn't need to do this if there were some system imposed
307559812Shibler 		   limit on the size of an ACL, but I can't find any such. */
307659812Shibler 		{
307759812Shibler 		  xabpro.xab$l_aclbuf = alloca (xabpro.xab$w_acllen);
307859812Shibler 		  xabpro.xab$w_aclsiz = xabpro.xab$w_acllen;
307959812Shibler 		  if (sys$open (&fab, 0, 0) & 1)
308059812Shibler 		    sys$close (&fab, 0, 0);
308159812Shibler 		  else
308259812Shibler 		    old = 0;
308359812Shibler 		}
308459812Shibler 	    }
308559812Shibler 	  else
308659812Shibler 	    xabpro.xab$l_aclbuf = 0;
308759812Shibler 	}
308859812Shibler       else
308959812Shibler 	old = 0;
309059812Shibler     }
309159812Shibler   fab.fab$l_fna = new;
309259812Shibler   fab.fab$b_fns = strlen (new);
309359812Shibler   if (!old)
309459812Shibler     {
309559812Shibler       fab.fab$l_xab = 0;
309659812Shibler       fab.fab$b_rfm = vms_stmlf_recfm ? FAB$C_STMLF : FAB$C_VAR;
309759812Shibler       fab.fab$b_rat = FAB$M_CR;
309859812Shibler     }
309959812Shibler   /* Create the new file with either default attrs or attrs copied
310059812Shibler      from old file. */
310159812Shibler   if (!(SYS$CREATE (&fab, 0, 0) & 1))
310259812Shibler     return -1;
310359812Shibler   sys$close (&fab, 0, 0);
310459812Shibler   /* As this is a "replacement" for creat, return a file descriptor
310559812Shibler      opened for writing. */
310659812Shibler   return open (new, O_WRONLY);
310759812Shibler }
310859812Shibler 
310959812Shibler #ifdef creat
311059812Shibler #undef creat
311159812Shibler #include <varargs.h>
311259812Shibler 
311359812Shibler sys_creat (va_alist)
311459812Shibler      va_dcl
311559812Shibler {
311659812Shibler   va_list list_incrementor;
311759812Shibler   char *name;
311859812Shibler   int mode;
311959812Shibler   int rfd;			/* related file descriptor */
312059812Shibler   int fd;			/* Our new file descriptor */
312159812Shibler   int count;
312259812Shibler   struct stat st_buf;
312359812Shibler   char rfm[12];
312459812Shibler   char rat[15];
312559812Shibler   char mrs[13];
312659812Shibler   char fsz[13];
312759812Shibler   extern int vms_stmlf_recfm;
312859812Shibler 
312959812Shibler   va_count (count);
313059812Shibler   va_start (list_incrementor);
313159812Shibler   name = va_arg (list_incrementor, char *);
313259812Shibler   mode = va_arg (list_incrementor, int);
313359812Shibler   if (count > 2)
313459812Shibler     rfd = va_arg (list_incrementor, int);
313559812Shibler   va_end (list_incrementor);
313659812Shibler   if (count > 2)
313759812Shibler     {
313859812Shibler       /* Use information from the related file descriptor to set record
313959812Shibler 	 format of the newly created file. */
314059812Shibler       fstat (rfd, &st_buf);
314159812Shibler       switch (st_buf.st_fab_rfm)
314259812Shibler 	{
314359812Shibler 	case FAB$C_FIX:
314459812Shibler 	  strcpy (rfm, "rfm = fix");
314559812Shibler 	  sprintf (mrs, "mrs = %d", st_buf.st_fab_mrs);
314659812Shibler 	  strcpy (rat, "rat = ");
314759812Shibler 	  if (st_buf.st_fab_rat & FAB$M_CR)
314859812Shibler 	    strcat (rat, "cr");
314959812Shibler 	  else if (st_buf.st_fab_rat & FAB$M_FTN)
315059812Shibler 	    strcat (rat, "ftn");
315159812Shibler 	  else if (st_buf.st_fab_rat & FAB$M_PRN)
315259812Shibler 	    strcat (rat, "prn");
315359812Shibler 	  if (st_buf.st_fab_rat & FAB$M_BLK)
315459812Shibler 	    if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
315559812Shibler 	      strcat (rat, ", blk");
315659812Shibler 	    else
315759812Shibler 	      strcat (rat, "blk");
315859812Shibler 	  return creat (name, 0, rfm, rat, mrs);
315959812Shibler 
316059812Shibler 	case FAB$C_VFC:
316159812Shibler 	  strcpy (rfm, "rfm = vfc");
316259812Shibler 	  sprintf (fsz, "fsz = %d", st_buf.st_fab_fsz);
316359812Shibler 	  strcpy (rat, "rat = ");
316459812Shibler 	  if (st_buf.st_fab_rat & FAB$M_CR)
316559812Shibler 	    strcat (rat, "cr");
316659812Shibler 	  else if (st_buf.st_fab_rat & FAB$M_FTN)
316759812Shibler 	    strcat (rat, "ftn");
316859812Shibler 	  else if (st_buf.st_fab_rat & FAB$M_PRN)
316959812Shibler 	    strcat (rat, "prn");
317059812Shibler 	  if (st_buf.st_fab_rat & FAB$M_BLK)
317159812Shibler 	    if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
317259812Shibler 	      strcat (rat, ", blk");
317359812Shibler 	    else
317459812Shibler 	      strcat (rat, "blk");
317559812Shibler 	  return creat (name, 0, rfm, rat, fsz);
317659812Shibler 
317759812Shibler 	case FAB$C_STM:
317859812Shibler 	  strcpy (rfm, "rfm = stm");
317959812Shibler 	  break;
318059812Shibler 
318159812Shibler 	case FAB$C_STMCR:
318259812Shibler 	  strcpy (rfm, "rfm = stmcr");
318359812Shibler 	  break;
318459812Shibler 
318559812Shibler 	case FAB$C_STMLF:
318659812Shibler 	  strcpy (rfm, "rfm = stmlf");
318759812Shibler 	  break;
318859812Shibler 
318959812Shibler 	case FAB$C_UDF:
319059812Shibler 	  strcpy (rfm, "rfm = udf");
319159812Shibler 	  break;
319259812Shibler 
319359812Shibler 	case FAB$C_VAR:
319459812Shibler 	  strcpy (rfm, "rfm = var");
319559812Shibler 	  break;
319659812Shibler 	}
319759812Shibler       strcpy (rat, "rat = ");
319859812Shibler       if (st_buf.st_fab_rat & FAB$M_CR)
319959812Shibler 	strcat (rat, "cr");
320059812Shibler       else if (st_buf.st_fab_rat & FAB$M_FTN)
320159812Shibler 	strcat (rat, "ftn");
320259812Shibler       else if (st_buf.st_fab_rat & FAB$M_PRN)
320359812Shibler 	strcat (rat, "prn");
320459812Shibler       if (st_buf.st_fab_rat & FAB$M_BLK)
320559812Shibler 	if (st_buf.st_fab_rat & (FAB$M_CR|FAB$M_FTN|FAB$M_PRN))
320659812Shibler 	  strcat (rat, ", blk");
320759812Shibler 	else
320859812Shibler 	  strcat (rat, "blk");
320959812Shibler     }
321059812Shibler   else
321159812Shibler     {
321259812Shibler       strcpy (rfm, vms_stmlf_recfm ? "rfm = stmlf" : "rfm=var");
321359812Shibler       strcpy (rat, "rat=cr");
321459812Shibler     }
321559812Shibler   /* Until the VAX C RTL fixes the many bugs with modes, always use
321659812Shibler      mode 0 to get the user's default protection. */
321759812Shibler   fd = creat (name, 0, rfm, rat);
321859812Shibler   if (fd < 0 && errno == EEXIST)
321959812Shibler     {
322059812Shibler       if (unlink (name) < 0)
322159812Shibler 	report_file_error ("delete", build_string (name));
322259812Shibler       fd = creat (name, 0, rfm, rat);
322359812Shibler     }
322459812Shibler   return fd;
322559812Shibler }
322659812Shibler #endif /* creat */
322759812Shibler 
322859812Shibler /* fwrite to stdout is S L O W.  Speed it up by using fputc...*/
322959812Shibler sys_fwrite (ptr, size, num, fp)
323059812Shibler      register char * ptr;
323159812Shibler      FILE * fp;
323259812Shibler {
323359812Shibler   register int tot = num * size;
323459812Shibler 
323559812Shibler   while (tot--)
323659812Shibler     fputc (*ptr++, fp);
323759812Shibler }
323859812Shibler 
323959812Shibler /*
324059812Shibler  * The VMS C library routine creat() actually creates a new version of an
324159812Shibler  * existing file rather than truncating the old version.  There are times
324259812Shibler  * when this is not the desired behavior, for instance, when writing an
324359812Shibler  * auto save file (you only want one version), or when you don't have
324459812Shibler  * write permission in the directory containing the file (but the file
324559812Shibler  * itself is writable).  Hence this routine, which is equivalent to
324659812Shibler  * "close (creat (fn, 0));" on Unix if fn already exists.
324759812Shibler  */
324859812Shibler int
324959812Shibler vms_truncate (fn)
325059812Shibler      char *fn;
325159812Shibler {
325259812Shibler   struct FAB xfab = cc$rms_fab;
325359812Shibler   struct RAB xrab = cc$rms_rab;
325459812Shibler   int status;
325559812Shibler 
325659812Shibler   xfab.fab$l_fop = FAB$M_TEF;	/* free allocated but unused blocks on close */
325759812Shibler   xfab.fab$b_fac = FAB$M_TRN | FAB$M_GET; /* allow truncate and get access */
325859812Shibler   xfab.fab$b_shr = FAB$M_NIL;	/* allow no sharing - file must be locked */
325959812Shibler   xfab.fab$l_fna = fn;
326059812Shibler   xfab.fab$b_fns = strlen (fn);
326159812Shibler   xfab.fab$l_dna = ";0";	/* default to latest version of the file */
326259812Shibler   xfab.fab$b_dns = 2;
326359812Shibler   xrab.rab$l_fab = &xfab;
326459812Shibler 
326559812Shibler   /* This gibberish opens the file, positions to the first record, and
326659812Shibler      deletes all records from there until the end of file. */
326759812Shibler   if ((sys$open (&xfab) & 01) == 01)
326859812Shibler     {
326959812Shibler       if ((sys$connect (&xrab) & 01) == 01 &&
327059812Shibler 	  (sys$find (&xrab) & 01) == 01 &&
327159812Shibler 	  (sys$truncate (&xrab) & 01) == 01)
327259812Shibler 	status = 0;
327359812Shibler       else
327459812Shibler 	status = -1;
327559812Shibler     }
327659812Shibler   else
327759812Shibler     status = -1;
327859812Shibler   sys$close (&xfab);
327959812Shibler   return status;
328059812Shibler }
328159812Shibler 
328259812Shibler /* Define this symbol to actually read SYSUAF.DAT.  This requires either
328359812Shibler    SYSPRV or a readable SYSUAF.DAT. */
328459812Shibler 
328559812Shibler #ifdef READ_SYSUAF
328659812Shibler /*
328759812Shibler  * getuaf.c
328859812Shibler  *
328959812Shibler  * Routine to read the VMS User Authorization File and return
329059812Shibler  * a specific user's record.
329159812Shibler  */
329259812Shibler 
329359812Shibler static struct UAF retuaf;
329459812Shibler 
329559812Shibler struct UAF *
329659812Shibler get_uaf_name(uname)
329759812Shibler      char * uname;
329859812Shibler {
329959812Shibler   register status;
330059812Shibler   struct FAB uaf_fab;
330159812Shibler   struct RAB uaf_rab;
330259812Shibler 
330359812Shibler   uaf_fab = cc$rms_fab;
330459812Shibler   uaf_rab = cc$rms_rab;
330559812Shibler   /* initialize fab fields */
330659812Shibler   uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
330759812Shibler   uaf_fab.fab$b_fns = 21;
330859812Shibler   uaf_fab.fab$b_fac = FAB$M_GET;
330959812Shibler   uaf_fab.fab$b_org = FAB$C_IDX;
331059812Shibler   uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
331159812Shibler   /* initialize rab fields */
331259812Shibler   uaf_rab.rab$l_fab = &uaf_fab;
331359812Shibler   /* open the User Authorization File */
331459812Shibler   status = sys$open(&uaf_fab);
331559812Shibler   if (!(status&1))
331659812Shibler     {
331759812Shibler       errno = EVMSERR;
331859812Shibler       vaxc$errno = status;
331959812Shibler       return 0;
332059812Shibler     }
332159812Shibler   status = sys$connect(&uaf_rab);
332259812Shibler   if (!(status&1))
332359812Shibler     {
332459812Shibler       errno = EVMSERR;
332559812Shibler       vaxc$errno = status;
332659812Shibler       return 0;
332759812Shibler     }
332859812Shibler   /* read the requested record - index is in uname */
332959812Shibler   uaf_rab.rab$l_kbf = uname;
333059812Shibler   uaf_rab.rab$b_ksz = strlen (uname);
333159812Shibler   uaf_rab.rab$b_rac = RAB$C_KEY;
333259812Shibler   uaf_rab.rab$l_ubf = (char *)&retuaf;
333359812Shibler   uaf_rab.rab$w_usz = sizeof retuaf;
333459812Shibler   status = sys$get(&uaf_rab);
333559812Shibler   if (!(status&1))
333659812Shibler     {
333759812Shibler       errno = EVMSERR;
333859812Shibler       vaxc$errno = status;
333959812Shibler       return 0;
334059812Shibler     }
334159812Shibler   /* close the User Authorization File */
334259812Shibler   status = sys$disconnect(&uaf_rab);
334359812Shibler   if (!(status&1))
334459812Shibler     {
334559812Shibler       errno = EVMSERR;
334659812Shibler       vaxc$errno = status;
334759812Shibler       return 0;
334859812Shibler     }
334959812Shibler   status = sys$close(&uaf_fab);
335059812Shibler   if (!(status&1))
335159812Shibler     {
335259812Shibler       errno = EVMSERR;
335359812Shibler       vaxc$errno = status;
335459812Shibler       return 0;
335559812Shibler     }
335659812Shibler   return &retuaf;
335759812Shibler }
335859812Shibler 
335959812Shibler struct UAF *
336059812Shibler get_uaf_uic(uic)
336159812Shibler      unsigned long uic;
336259812Shibler {
336359812Shibler   register status;
336459812Shibler   struct FAB uaf_fab;
336559812Shibler   struct RAB uaf_rab;
336659812Shibler 
336759812Shibler   uaf_fab = cc$rms_fab;
336859812Shibler   uaf_rab = cc$rms_rab;
336959812Shibler   /* initialize fab fields */
337059812Shibler   uaf_fab.fab$l_fna = "SYS$SYSTEM:SYSUAF.DAT";
337159812Shibler   uaf_fab.fab$b_fns = 21;
337259812Shibler   uaf_fab.fab$b_fac = FAB$M_GET;
337359812Shibler   uaf_fab.fab$b_org = FAB$C_IDX;
337459812Shibler   uaf_fab.fab$b_shr = FAB$M_GET|FAB$M_PUT|FAB$M_UPD|FAB$M_DEL;
337559812Shibler   /* initialize rab fields */
337659812Shibler   uaf_rab.rab$l_fab = &uaf_fab;
337759812Shibler   /* open the User Authorization File */
337859812Shibler   status = sys$open(&uaf_fab);
337959812Shibler   if (!(status&1))
338059812Shibler     {
338159812Shibler       errno = EVMSERR;
338259812Shibler       vaxc$errno = status;
338359812Shibler       return 0;
338459812Shibler     }
338559812Shibler   status = sys$connect(&uaf_rab);
338659812Shibler   if (!(status&1))
338759812Shibler     {
338859812Shibler       errno = EVMSERR;
338959812Shibler       vaxc$errno = status;
339059812Shibler       return 0;
339159812Shibler     }
339259812Shibler   /* read the requested record - index is in uic */
339359812Shibler   uaf_rab.rab$b_krf = 1;	/* 1st alternate key */
339459812Shibler   uaf_rab.rab$l_kbf = (char *) &uic;
339559812Shibler   uaf_rab.rab$b_ksz = sizeof uic;
339659812Shibler   uaf_rab.rab$b_rac = RAB$C_KEY;
339759812Shibler   uaf_rab.rab$l_ubf = (char *)&retuaf;
339859812Shibler   uaf_rab.rab$w_usz = sizeof retuaf;
339959812Shibler   status = sys$get(&uaf_rab);
340059812Shibler   if (!(status&1))
340159812Shibler     {
340259812Shibler       errno = EVMSERR;
340359812Shibler       vaxc$errno = status;
340459812Shibler       return 0;
340559812Shibler     }
340659812Shibler   /* close the User Authorization File */
340759812Shibler   status = sys$disconnect(&uaf_rab);
340859812Shibler   if (!(status&1))
340959812Shibler     {
341059812Shibler       errno = EVMSERR;
341159812Shibler       vaxc$errno = status;
341259812Shibler       return 0;
341359812Shibler     }
341459812Shibler   status = sys$close(&uaf_fab);
341559812Shibler   if (!(status&1))
341659812Shibler     {
341759812Shibler       errno = EVMSERR;
341859812Shibler       vaxc$errno = status;
341959812Shibler       return 0;
342059812Shibler     }
342159812Shibler   return &retuaf;
342259812Shibler }
342359812Shibler 
342459812Shibler static struct passwd retpw;
342559812Shibler 
342659812Shibler struct passwd *
342759812Shibler cnv_uaf_pw (up)
342859812Shibler      struct UAF * up;
342959812Shibler {
343059812Shibler   char * ptr;
343159812Shibler 
343259812Shibler   /* copy these out first because if the username is 32 chars, the next
343359812Shibler      section will overwrite the first byte of the UIC */
343459812Shibler   retpw.pw_uid = up->uaf$w_mem;
343559812Shibler   retpw.pw_gid = up->uaf$w_grp;
343659812Shibler 
343759812Shibler   /* I suppose this is not the best sytle, to possibly overwrite one
343859812Shibler      byte beyond the end of the field, but what the heck... */
343959812Shibler   ptr = &up->uaf$t_username[UAF$S_USERNAME];
344059812Shibler   while (ptr[-1] == ' ')
344159812Shibler     ptr--;
344259812Shibler   *ptr = '\0';
344359812Shibler   strcpy (retpw.pw_name, up->uaf$t_username);
344459812Shibler 
344559812Shibler   /* the rest of these are counted ascii strings */
344659812Shibler   strncpy (retpw.pw_gecos, &up->uaf$t_owner[1], up->uaf$t_owner[0]);
344759812Shibler   retpw.pw_gecos[up->uaf$t_owner[0]] = '\0';
344859812Shibler   strncpy (retpw.pw_dir, &up->uaf$t_defdev[1], up->uaf$t_defdev[0]);
344959812Shibler   retpw.pw_dir[up->uaf$t_defdev[0]] = '\0';
345059812Shibler   strncat (retpw.pw_dir, &up->uaf$t_defdir[1], up->uaf$t_defdir[0]);
345159812Shibler   retpw.pw_dir[up->uaf$t_defdev[0] + up->uaf$t_defdir[0]] = '\0';
345259812Shibler   strncpy (retpw.pw_shell, &up->uaf$t_defcli[1], up->uaf$t_defcli[0]);
345359812Shibler   retpw.pw_shell[up->uaf$t_defcli[0]] = '\0';
345459812Shibler 
345559812Shibler   return &retpw;
345659812Shibler }
345759812Shibler #else /* not READ_SYSUAF */
345859812Shibler static struct passwd retpw;
345959812Shibler #endif /* not READ_SYSUAF */
346059812Shibler 
346159812Shibler struct passwd *
346259812Shibler getpwnam (name)
346359812Shibler      char * name;
346459812Shibler {
346559812Shibler #ifdef READ_SYSUAF
346659812Shibler   struct UAF *up;
346759812Shibler #else
346859812Shibler   char * user;
346959812Shibler   char * dir;
347059812Shibler   char * full;
347159812Shibler #endif /* READ_SYSUAF */
347259812Shibler   char *ptr = name;
347359812Shibler 
347459812Shibler   while (*ptr)
347559812Shibler     {
347659812Shibler       if ('a' <= *ptr && *ptr <= 'z')
347759812Shibler 	*ptr -= 040;
347859812Shibler       ptr++;
347959812Shibler     }
348059812Shibler #ifdef READ_SYSUAF
348159812Shibler   if (!(up = get_uaf_name (name)))
348259812Shibler     return 0;
348359812Shibler   return cnv_uaf_pw (up);
348459812Shibler #else
348559812Shibler   if (strcmp (name, getenv ("USER")) == 0)
348659812Shibler     {
348759812Shibler       retpw.pw_uid = getuid ();
348859812Shibler       retpw.pw_gid = getgid ();
348959812Shibler       strcpy (retpw.pw_name, name);
349059812Shibler       if (full = egetenv ("FULLNAME"))
349159812Shibler 	strcpy (retpw.pw_gecos, full);
349259812Shibler       else
349359812Shibler 	*retpw.pw_gecos = '\0';
349459812Shibler       strcpy (retpw.pw_dir, egetenv ("HOME"));
349559812Shibler       *retpw.pw_shell = '\0';
349659812Shibler       return &retpw;
349759812Shibler     }
349859812Shibler   else
349959812Shibler     return 0;
350059812Shibler #endif /* not READ_SYSUAF */
350159812Shibler }
350259812Shibler 
350359812Shibler struct passwd *
350459812Shibler getpwuid (uid)
350559812Shibler      unsigned long uid;
350659812Shibler {
350759812Shibler #ifdef READ_SYSUAF
350859812Shibler   struct UAF * up;
350959812Shibler 
351059812Shibler   if (!(up = get_uaf_uic (uid)))
351159812Shibler     return 0;
351259812Shibler   return cnv_uaf_pw (up);
351359812Shibler #else
351459812Shibler   if (uid == sys_getuid ())
351559812Shibler     return getpwnam (egetenv ("USER"));
351659812Shibler   else
351759812Shibler     return 0;
351859812Shibler #endif /* not READ_SYSUAF */
351959812Shibler }
352059812Shibler 
352159812Shibler /* return total address space available to the current process.  This is
352259812Shibler    the sum of the current p0 size, p1 size and free page table entries
352359812Shibler    available. */
352459812Shibler vlimit ()
352559812Shibler {
352659812Shibler   int item_code;
352759812Shibler   unsigned long free_pages;
352859812Shibler   unsigned long frep0va;
352959812Shibler   unsigned long frep1va;
353059812Shibler   register status;
353159812Shibler 
353259812Shibler   item_code = JPI$_FREPTECNT;
353359812Shibler   if (((status = LIB$GETJPI (&item_code, 0, 0, &free_pages)) & 1) == 0)
353459812Shibler     {
353559812Shibler       errno = EVMSERR;
353659812Shibler       vaxc$errno = status;
353759812Shibler       return -1;
353859812Shibler     }
353959812Shibler   free_pages *= 512;
354059812Shibler 
354159812Shibler   item_code = JPI$_FREP0VA;
354259812Shibler   if (((status = LIB$GETJPI (&item_code, 0, 0, &frep0va)) & 1) == 0)
354359812Shibler     {
354459812Shibler       errno = EVMSERR;
354559812Shibler       vaxc$errno = status;
354659812Shibler       return -1;
354759812Shibler     }
354859812Shibler   item_code = JPI$_FREP1VA;
354959812Shibler   if (((status = LIB$GETJPI (&item_code, 0, 0, &frep1va)) & 1) == 0)
355059812Shibler     {
355159812Shibler       errno = EVMSERR;
355259812Shibler       vaxc$errno = status;
355359812Shibler       return -1;
355459812Shibler     }
355559812Shibler 
355659812Shibler   return free_pages + frep0va + (0x7fffffff - frep1va);
355759812Shibler }
355859812Shibler 
355959812Shibler define_logical_name (varname, string)
356059812Shibler      char *varname;
356159812Shibler      char *string;
356259812Shibler {
356359812Shibler   struct dsc$descriptor_s strdsc =
356459812Shibler     {strlen (string), DSC$K_DTYPE_T, DSC$K_CLASS_S, string};
356559812Shibler   struct dsc$descriptor_s envdsc =
356659812Shibler     {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
356759812Shibler   struct dsc$descriptor_s lnmdsc =
356859812Shibler     {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
356959812Shibler 
357059812Shibler   return LIB$SET_LOGICAL (&envdsc, &strdsc, &lnmdsc, 0, 0);
357159812Shibler }
357259812Shibler 
357359812Shibler delete_logical_name (varname)
357459812Shibler      char *varname;
357559812Shibler {
357659812Shibler   struct dsc$descriptor_s envdsc =
357759812Shibler     {strlen (varname), DSC$K_DTYPE_T, DSC$K_CLASS_S, varname};
357859812Shibler   struct dsc$descriptor_s lnmdsc =
357959812Shibler     {7, DSC$K_DTYPE_T, DSC$K_CLASS_S, "LNM$JOB"};
358059812Shibler 
358159812Shibler   return LIB$DELETE_LOGICAL (&envdsc, &lnmdsc);
358259812Shibler }
358359812Shibler 
358459812Shibler ulimit()
358559812Shibler {}
358659812Shibler 
358759812Shibler setpriority()
358859812Shibler {}
358959812Shibler 
359059812Shibler setpgrp()
359159812Shibler {}
359259812Shibler 
359359812Shibler execvp()
359459812Shibler {
359559812Shibler   error ("execvp system call not implemented");
359659812Shibler }
359759812Shibler 
359859812Shibler int
359959812Shibler rename (from, to)
360059812Shibler      char *from, *to;
360159812Shibler {
360259812Shibler   int status;
360359812Shibler   struct FAB from_fab = cc$rms_fab, to_fab = cc$rms_fab;
360459812Shibler   struct NAM from_nam = cc$rms_nam, to_nam = cc$rms_nam;
360559812Shibler   char from_esn[NAM$C_MAXRSS];
360659812Shibler   char to_esn[NAM$C_MAXRSS];
360759812Shibler 
360859812Shibler   from_fab.fab$l_fna = from;
360959812Shibler   from_fab.fab$b_fns = strlen (from);
361059812Shibler   from_fab.fab$l_nam = &from_nam;
361159812Shibler   from_fab.fab$l_fop = FAB$M_NAM;
361259812Shibler 
361359812Shibler   from_nam.nam$l_esa = from_esn;
361459812Shibler   from_nam.nam$b_ess = sizeof from_esn;
361559812Shibler 
361659812Shibler   to_fab.fab$l_fna = to;
361759812Shibler   to_fab.fab$b_fns = strlen (to);
361859812Shibler   to_fab.fab$l_nam = &to_nam;
361959812Shibler   to_fab.fab$l_fop = FAB$M_NAM;
362059812Shibler 
362159812Shibler   to_nam.nam$l_esa = to_esn;
362259812Shibler   to_nam.nam$b_ess = sizeof to_esn;
362359812Shibler 
362459812Shibler   status = SYS$RENAME (&from_fab, 0, 0, &to_fab);
362559812Shibler 
362659812Shibler   if (status & 1)
362759812Shibler     return 0;
362859812Shibler   else
362959812Shibler     {
363059812Shibler       if (status == RMS$_DEV)
363159812Shibler 	errno = EXDEV;
363259812Shibler       else
363359812Shibler 	errno = EVMSERR;
363459812Shibler       vaxc$errno = status;
363559812Shibler       return -1;
363659812Shibler     }
363759812Shibler }
363859812Shibler 
363959812Shibler link (file, new)
364059812Shibler      char * file, * new;
364159812Shibler {
364259812Shibler   register status;
364359812Shibler   struct FAB fab;
364459812Shibler   struct NAM nam;
364559812Shibler   unsigned short fid[3];
364659812Shibler   char esa[NAM$C_MAXRSS];
364759812Shibler 
364859812Shibler   fab = cc$rms_fab;
364959812Shibler   fab.fab$l_fop = FAB$M_OFP;
365059812Shibler   fab.fab$l_fna = file;
365159812Shibler   fab.fab$b_fns = strlen (file);
365259812Shibler   fab.fab$l_nam = &nam;
365359812Shibler 
365459812Shibler   nam = cc$rms_nam;
365559812Shibler   nam.nam$l_esa = esa;
365659812Shibler   nam.nam$b_ess = NAM$C_MAXRSS;
365759812Shibler 
365859812Shibler   status = SYS$PARSE (&fab);
365959812Shibler   if ((status & 1) == 0)
366059812Shibler     {
366159812Shibler       errno = EVMSERR;
366259812Shibler       vaxc$errno = status;
366359812Shibler       return -1;
366459812Shibler     }
366559812Shibler   status = SYS$SEARCH (&fab);
366659812Shibler   if ((status & 1) == 0)
366759812Shibler     {
366859812Shibler       errno = EVMSERR;
366959812Shibler       vaxc$errno = status;
367059812Shibler       return -1;
367159812Shibler     }
367259812Shibler 
367359812Shibler   fid[0] = nam.nam$w_fid[0];
367459812Shibler   fid[1] = nam.nam$w_fid[1];
367559812Shibler   fid[2] = nam.nam$w_fid[2];
367659812Shibler 
367759812Shibler   fab.fab$l_fna = new;
367859812Shibler   fab.fab$b_fns = strlen (new);
367959812Shibler 
368059812Shibler   status = SYS$PARSE (&fab);
368159812Shibler   if ((status & 1) == 0)
368259812Shibler     {
368359812Shibler       errno = EVMSERR;
368459812Shibler       vaxc$errno = status;
368559812Shibler       return -1;
368659812Shibler     }
368759812Shibler 
368859812Shibler   nam.nam$w_fid[0] = fid[0];
368959812Shibler   nam.nam$w_fid[1] = fid[1];
369059812Shibler   nam.nam$w_fid[2] = fid[2];
369159812Shibler 
369259812Shibler   nam.nam$l_esa = nam.nam$l_name;
369359812Shibler   nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;
369459812Shibler 
369559812Shibler   status = SYS$ENTER (&fab);
369659812Shibler   if ((status & 1) == 0)
369759812Shibler     {
369859812Shibler       errno = EVMSERR;
369959812Shibler       vaxc$errno = status;
370059812Shibler       return -1;
370159812Shibler     }
370259812Shibler 
370359812Shibler   return 0;
370459812Shibler }
370559812Shibler 
370659812Shibler croak (badfunc)
370759812Shibler      char *badfunc;
370859812Shibler {
370959812Shibler   printf ("%s not yet implemented\r\n", badfunc);
371059812Shibler   reset_sys_modes ();
371159812Shibler   exit (1);
371259812Shibler }
371359812Shibler 
371459812Shibler long
371559812Shibler random ()
371659812Shibler {
371759812Shibler   /* Arrange to return a range centered on zero.  */
371859812Shibler   return rand () - (1 << 30);
371959812Shibler }
372059812Shibler 
372159812Shibler srandom (seed)
372259812Shibler {
372359812Shibler   srand (seed);
372459812Shibler }
372559812Shibler #endif /* VMS */
372659812Shibler 
372759812Shibler #ifdef AIX
372859812Shibler 
372959812Shibler /* Called from init_sys_modes.  */
373059812Shibler hft_init ()
373159812Shibler {
373259812Shibler   /* If we're not on an HFT we shouldn't do any of this.  We determine
373359812Shibler      if we are on an HFT by trying to get an HFT error code.  If this
373459812Shibler      call fails, we're not on an HFT. */
373559812Shibler #ifdef IBMR2AIX
373659812Shibler   if (ioctl (0, HFQERROR, 0) < 0)
373759812Shibler     return;
373859812Shibler #else /* not IBMR2AIX */
373959812Shibler   if (ioctl (0, HFQEIO, 0) < 0)
374059812Shibler     return;
374159812Shibler #endif /* not IBMR2AIX */
374259812Shibler 
374359812Shibler   /* On AIX the default hft keyboard mapping uses backspace rather than delete
374459812Shibler      as the rubout key's ASCII code.  Here this is changed.  The bug is that
374559812Shibler      there's no way to determine the old mapping, so in reset_sys_modes
374659812Shibler      we need to assume that the normal map had been present.  Of course, this
374759812Shibler      code also doesn't help if on a terminal emulator which doesn't understand
374859812Shibler      HFT VTD's. */
374959812Shibler   {
375059812Shibler     struct hfbuf buf;
375159812Shibler     struct hfkeymap keymap;
375259812Shibler 
375359812Shibler     buf.hf_bufp = (char *)&keymap;
375459812Shibler     buf.hf_buflen = sizeof (keymap);
375559812Shibler     keymap.hf_nkeys = 2;
375659812Shibler     keymap.hfkey[0].hf_kpos = 15;
375759812Shibler     keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
375859812Shibler #ifdef IBMR2AIX
375959812Shibler     keymap.hfkey[0].hf_keyidh = '<';
376059812Shibler #else /* not IBMR2AIX */
376159812Shibler     keymap.hfkey[0].hf_page = '<';
376259812Shibler #endif /* not IBMR2AIX */
376359812Shibler     keymap.hfkey[0].hf_char = 127;
376459812Shibler     keymap.hfkey[1].hf_kpos = 15;
376559812Shibler     keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
376659812Shibler #ifdef IBMR2AIX
376759812Shibler     keymap.hfkey[1].hf_keyidh = '<';
376859812Shibler #else /* not IBMR2AIX */
376959812Shibler     keymap.hfkey[1].hf_page = '<';
377059812Shibler #endif /* not IBMR2AIX */
377159812Shibler     keymap.hfkey[1].hf_char = 127;
377259812Shibler     hftctl (0, HFSKBD, &buf);
377359812Shibler   }
377459812Shibler   /* The HFT system on AIX doesn't optimize for scrolling, so it's really ugly
377559812Shibler      at times. */
377659812Shibler   line_ins_del_ok = char_ins_del_ok = 0;
377759812Shibler }
377859812Shibler 
377959812Shibler /* Reset the rubout key to backspace. */
378059812Shibler 
378159812Shibler hft_reset ()
378259812Shibler {
378359812Shibler   struct hfbuf buf;
378459812Shibler   struct hfkeymap keymap;
378559812Shibler 
378659812Shibler #ifdef IBMR2AIX
378759812Shibler   if (ioctl (0, HFQERROR, 0) < 0)
378859812Shibler     return;
378959812Shibler #else /* not IBMR2AIX */
379059812Shibler   if (ioctl (0, HFQEIO, 0) < 0)
379159812Shibler     return;
379259812Shibler #endif /* not IBMR2AIX */
379359812Shibler 
379459812Shibler   buf.hf_bufp = (char *)&keymap;
379559812Shibler   buf.hf_buflen = sizeof(keymap);
379659812Shibler   keymap.hf_nkeys = 2;
379759812Shibler   keymap.hfkey[0].hf_kpos = 15;
379859812Shibler   keymap.hfkey[0].hf_kstate = HFMAPCHAR | HFSHFNONE;
379959812Shibler #ifdef IBMR2AIX
380059812Shibler   keymap.hfkey[0].hf_keyidh = '<';
380159812Shibler #else /* not IBMR2AIX */
380259812Shibler   keymap.hfkey[0].hf_page = '<';
380359812Shibler #endif /* not IBMR2AIX */
380459812Shibler   keymap.hfkey[0].hf_char = 8;
380559812Shibler   keymap.hfkey[1].hf_kpos = 15;
380659812Shibler   keymap.hfkey[1].hf_kstate = HFMAPCHAR | HFSHFSHFT;
380759812Shibler #ifdef IBMR2AIX
380859812Shibler   keymap.hfkey[1].hf_keyidh = '<';
380959812Shibler #else /* not IBMR2AIX */
381059812Shibler   keymap.hfkey[1].hf_page = '<';
381159812Shibler #endif /* not IBMR2AIX */
381259812Shibler   keymap.hfkey[1].hf_char = 8;
381359812Shibler   hftctl (0, HFSKBD, &buf);
381459812Shibler }
381559812Shibler 
381659812Shibler #endif /* AIX */
3817