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