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