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