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