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