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