|
|
1.1 ! root 1: /* Interfaces to system-dependent kernel and library entries. ! 2: Copyright (C) 1985 Richard M. Stallman. ! 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: ! 24: #include "config.h" ! 25: #include "lisp.h" ! 26: #undef NULL ! 27: ! 28: /* In this file, open, read and write refer to the system calls, ! 29: not our sugared interfaces sys_open, sys_read and sys_write. ! 30: Contrariwise, for systems where we use the system calls directly, ! 31: define sys_read, etc. here as aliases for them. */ ! 32: #ifndef read ! 33: #define sys_read read ! 34: #define sys_write write ! 35: #endif /* `read' is not a macro */ ! 36: ! 37: #undef read ! 38: #undef write ! 39: ! 40: #ifndef open ! 41: #define sys_open open ! 42: #endif /* `open' is not a macro. */ ! 43: ! 44: #undef open ! 45: ! 46: #include <stdio.h> ! 47: #include <sys/types.h> ! 48: #include <sys/stat.h> ! 49: ! 50: #if defined (USG) || (defined (BSD) && !defined (BSD4_1)) ! 51: #include <fcntl.h> ! 52: #endif ! 53: ! 54: #ifdef BSD ! 55: #include <sys/ioctl.h> ! 56: #ifdef BSD4_1 ! 57: #include <wait.h> ! 58: #else /* not 4.1 */ ! 59: #include <sys/wait.h> ! 60: #endif /* not 4.1 */ ! 61: #include <sgtty.h> ! 62: #define TERMINAL struct sgttyb ! 63: #define OSPEED(str) str.sg_ospeed ! 64: #define TABS_OK(str) ((str.sg_flags & XTABS) != XTABS) ! 65: #endif ! 66: ! 67: /* Get rid of LLITOUT in 4.1, since it is said to stimulate kernel bugs. */ ! 68: #ifdef BSD4_1 ! 69: #undef LLITOUT ! 70: #define LLITOUT 0 ! 71: #endif /* 4.1 */ ! 72: ! 73: #ifdef USG ! 74: #include <termio.h> ! 75: #include <sys/utsname.h> ! 76: #include <memory.h> ! 77: #include <string.h> ! 78: #ifdef HAVE_TIMEVAL ! 79: #ifdef HPUX ! 80: #include <time.h> ! 81: #else ! 82: #include <sys/time.h> ! 83: #endif ! 84: #endif /* HAVE_TIMEVAL */ ! 85: #include <errno.h> ! 86: #define TIOCGETP TCGETA ! 87: #define TIOCSETN TCSETA ! 88: #define TIOCSETP TCSETAF ! 89: #define TERMINAL struct termio ! 90: #define OSPEED(str) (str.c_cflag & CBAUD) ! 91: #define TABS_OK(str) ((str.c_oflag & TABDLY) != TAB3) ! 92: #endif /* USG */ ! 93: ! 94: #include "termhooks.h" ! 95: #include "termchar.h" ! 96: #include "termopts.h" ! 97: #include "dispextern.h" ! 98: ! 99: #ifdef NONSYSTEM_DIR_LIBRARY ! 100: #include "ndir.h" ! 101: #endif /* NONSYSTEM_DIR_LIBRARY */ ! 102: ! 103: /* Define SIGCHLD as an alias for SIGCLD. There are many conditionals ! 104: testing SIGCHLD. */ ! 105: ! 106: #if !defined (SIGCHLD) && defined (SIGCLD) ! 107: #define SIGCHLD SIGCLD ! 108: #endif /* SIGCLD and not SIGCHLD */ ! 109: ! 110: static int baud_convert[] = ! 111: { ! 112: 0, 50, 75, 110, 135, 150, 200, 300, 600, 1200, ! 113: 1800, 2400, 4800, 9600, 19200, 38400 ! 114: }; ! 115: ! 116: extern short ospeed; ! 117: ! 118: discard_tty_input () ! 119: { ! 120: TERMINAL buf; ! 121: ! 122: if (noninteractive) ! 123: return; ! 124: ! 125: ioctl (0, TIOCGETP, &buf); ! 126: ioctl (0, TIOCSETP, &buf); ! 127: } ! 128: ! 129: #ifdef SIGTSTP ! 130: ! 131: stuff_char (c) ! 132: char c; ! 133: { ! 134: /* Should perhaps error if in batch mode */ ! 135: #ifdef TIOCSTI ! 136: ioctl (0, TIOCSTI, &c); ! 137: #else /* no TIOCSTI */ ! 138: error ("Cannot stuff terminal input characters in this version of Unix."); ! 139: #endif /* no TIOCSTI */ ! 140: } ! 141: ! 142: #endif /* SIGTSTP */ ! 143: ! 144: init_baud_rate () ! 145: { ! 146: TERMINAL sg; ! 147: ! 148: if (noninteractive) ! 149: ospeed = 0; ! 150: else ! 151: { ! 152: ioctl (0, TIOCGETP, &sg); ! 153: ospeed = OSPEED (sg); ! 154: } ! 155: baud_rate = ospeed == 0 ? 1200 ! 156: : ospeed < sizeof baud_convert / sizeof baud_convert[0] ! 157: ? baud_convert[ospeed] : 9600; ! 158: } ! 159: ! 160: set_exclusive_use (fd) ! 161: int fd; ! 162: { ! 163: #ifdef FIOCLEX ! 164: ioctl (fd, FIOCLEX, 0); ! 165: #endif ! 166: /* Ok to do nothing if this feature does not exist */ ! 167: } ! 168: ! 169: #ifndef subprocesses ! 170: ! 171: wait_without_blocking () ! 172: { ! 173: #ifndef USG ! 174: wait3 (0, WNOHANG | WUNTRACED, 0); ! 175: #else ! 176: croak ("wait_without_blocking"); ! 177: #endif ! 178: } ! 179: ! 180: #endif /* not subprocesses */ ! 181: ! 182: int wait_debugging; /* Set nonzero to make following function work under dbx ! 183: (at least for bsd). */ ! 184: ! 185: /* Wait for subprocess with process id `pid' to terminate and ! 186: make sure it will get eliminated (not remain forever as a zombie) */ ! 187: ! 188: wait_for_termination (pid) ! 189: int pid; ! 190: { ! 191: int status; ! 192: while (1) ! 193: { ! 194: #ifdef subprocesses ! 195: #ifdef BSD ! 196: /* Note that kill returns -1 even if the process is just a zombie now. ! 197: But inevitably a SIGCHLD interrupt should be generated ! 198: and child_sig will do wait3 and make the process go away. */ ! 199: /* There is some indication that there is a bug involved with ! 200: termination of subprocesses, perhaps involving a kernel bug too, ! 201: but no idea what it is. Just as a hunch we signal SIGCHLD to see ! 202: if that causes the problem to go away or get worse. */ ! 203: #ifdef BSD4_1 ! 204: extern int synch_process_pid; ! 205: sighold (SIGCHLD); ! 206: if (synch_process_pid == 0) ! 207: { ! 208: sigrelse (SIGCHLD); ! 209: break; ! 210: } ! 211: if (wait_debugging) ! 212: sleep (1); ! 213: else ! 214: sigpause (SIGCHLD); ! 215: #else /* not BSD4_1 */ ! 216: sigsetmask (1 << (SIGCHLD - 1)); ! 217: if (0 > kill (pid, 0)) ! 218: { ! 219: sigsetmask (0); ! 220: kill (getpid (), SIGCHLD); ! 221: break; ! 222: } ! 223: if (wait_debugging) ! 224: sleep (1); ! 225: else ! 226: sigpause (0); ! 227: #endif /* not BSD4_1 */ ! 228: #else /* not BSD */ ! 229: #ifdef UNIPLUS ! 230: if (0 > kill (pid, 0)) ! 231: break; ! 232: wait (0); ! 233: #else /* neither BSD nor UNIPLUS: random sysV */ ! 234: if (0 > kill (pid, 0)) ! 235: break; ! 236: pause (); ! 237: #endif /* not UNIPLUS */ ! 238: #endif /* not BSD */ ! 239: #else /* not subprocesses */ ! 240: #ifndef BSD4_1 ! 241: if (0 > kill (pid, 0)) ! 242: break; ! 243: wait (0); ! 244: #else /* BSD4_1 */ ! 245: int status; ! 246: status = wait (0); ! 247: if (status == pid || status == -1) ! 248: break; ! 249: #endif /* BSD4_1 */ ! 250: #endif /* not subprocesses */ ! 251: } ! 252: } ! 253: ! 254: /* ! 255: * Insert description of what this command is really supposed to ! 256: * to (I.E. what state is the child process line to be placed into, ! 257: * and why). I have tried to interpret this as much as possible from ! 258: * the BSD setup and map to an appropriate USG control, but don't ! 259: * guarantee the results. fnf@unisoft ! 260: */ ! 261: ! 262: child_setup_tty (out) ! 263: int out; ! 264: { ! 265: TERMINAL s; ! 266: ! 267: ioctl (out, TIOCGETP, &s); ! 268: #ifdef USG ! 269: s.c_oflag |= OPOST; /* Enable output postprocessing */ ! 270: s.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */ ! 271: s.c_oflag &= ~(NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); /* No output delays */ ! 272: s.c_lflag &= ~ECHO; /* Disable echo */ ! 273: s.c_lflag &= ~ICANON; /* Disable erase/kill processing */ ! 274: s.c_lflag |= ISIG; /* Enable signals */ ! 275: s.c_iflag &= ~IUCLC; /* Disable map of upper case to lower on input */ ! 276: s.c_oflag &= ~OLCUC; /* Disable map of lower case to upper on output */ ! 277: s.c_cc[VMIN] = 1; /* minimum number of characters to accept */ ! 278: s.c_cc[VTIME] = 0; /* wait forever for at least 1 character */ ! 279: #else /* not USG */ ! 280: s.sg_flags &= ~(ECHO | CRMOD | ANYP | ALLDELAY | RAW | LCASE | CBREAK | TANDEM); ! 281: #endif /* not USG */ ! 282: ioctl (out, TIOCSETN, &s); ! 283: ! 284: #ifdef BSD4_1 ! 285: if (interrupt_input) ! 286: reset_sigio (); ! 287: #endif /* BSD4_1 */ ! 288: } ! 289: ! 290: setpgrp_of_tty (pid) ! 291: int pid; ! 292: { ! 293: #ifdef TIOCSPGRP ! 294: ioctl (0, TIOCSPGRP, &pid); ! 295: #else ! 296: /* Just ignore this for now and hope for the best */ ! 297: #endif ! 298: } ! 299: ! 300: #ifdef F_SETFL ! 301: ! 302: init_sigio () ! 303: { ! 304: request_sigio (); ! 305: } ! 306: ! 307: reset_sigio () ! 308: { ! 309: unrequest_sigio (); ! 310: } ! 311: ! 312: #ifdef FASYNC /* F_SETFL does not imply existance of FASYNC */ ! 313: int old_fcntl_flags; ! 314: ! 315: request_sigio () ! 316: { ! 317: old_fcntl_flags = fcntl (0, F_GETFL, 0); ! 318: fcntl (0, F_SETFL, old_fcntl_flags | FASYNC); ! 319: } ! 320: ! 321: unrequest_sigio () ! 322: { ! 323: fcntl (0, F_SETFL, old_fcntl_flags); ! 324: } ! 325: ! 326: #else /* no FASYNC */ ! 327: ! 328: request_sigio () ! 329: { ! 330: croak ("request_sigio"); ! 331: } ! 332: ! 333: unrequest_sigio () ! 334: { ! 335: croak ("unrequest_sigio"); ! 336: } ! 337: ! 338: #endif /* FASYNC */ ! 339: #endif /* F_SETFL */ ! 340: ! 341: TERMINAL old_gtty; /* The initial tty mode bits */ ! 342: ! 343: int term_initted; /* 1 if outer tty status has been recorded */ ! 344: ! 345: #ifdef F_SETOWN ! 346: int old_fcntl_owner; ! 347: #endif /* F_SETOWN */ ! 348: ! 349: #ifdef TIOCGLTC ! 350: struct tchars old_tchars; ! 351: struct ltchars old_ltchars; ! 352: int old_lmode; ! 353: ! 354: int lmode; /* Current lmode value. */ ! 355: /* Needed as global for 4.1 */ ! 356: #endif /* TIOCGLTC */ ! 357: ! 358: /* This may also be defined in stdio, ! 359: but if so, this does no harm, ! 360: and using the same name avoids wasting the other one's space. */ ! 361: ! 362: #ifdef USG ! 363: unsigned char _sobuf[BUFSIZ+8]; ! 364: #else ! 365: char _sobuf[BUFSIZ]; ! 366: #endif ! 367: ! 368: init_sys_modes () ! 369: { ! 370: TERMINAL sg; ! 371: #ifdef TIOCGLTC ! 372: struct tchars tchars; ! 373: static struct tchars new_tchars = {-1,-1,-1,-1,-1,-1}; ! 374: static struct ltchars new_ltchars = {-1,-1,-1,-1,-1,-1}; ! 375: #endif ! 376: ! 377: if (noninteractive) ! 378: return; ! 379: ! 380: ioctl (0, TIOCGETP, &old_gtty); ! 381: if (!read_socket_hook) ! 382: { ! 383: sg = old_gtty; ! 384: ! 385: #ifdef USG ! 386: sg.c_iflag |= (IGNBRK); /* Ignore break condition */ ! 387: sg.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */ ! 388: #ifdef ISTRIP ! 389: sg.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */ ! 390: #endif ! 391: sg.c_lflag &= ~ECHO; /* Disable echo */ ! 392: sg.c_lflag &= ~ICANON; /* Disable erase/kill processing */ ! 393: sg.c_lflag |= ISIG; /* Enable signals */ ! 394: if (flow_control) ! 395: { ! 396: sg.c_iflag |= IXON; /* Enable start/stop output control */ ! 397: #ifdef IXANY ! 398: sg.c_iflag &= ~IXANY; ! 399: #endif /* IXANY */ ! 400: } ! 401: else ! 402: sg.c_iflag &= ~IXON; /* Disable start/stop output control */ ! 403: sg.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL on output */ ! 404: sg.c_oflag &= ~TAB3; /* Disable tab expansion */ ! 405: #ifdef CS8 ! 406: sg.c_cflag |= CS8; /* allow 8th bit on input */ ! 407: sg.c_cflag &= ~PARENB; /* Don't check parity */ ! 408: #endif ! 409: sg.c_cc[VINTR] = '\007'; /* ^G gives SIGINT */ ! 410: #ifdef HPUX ! 411: /* Can't use CDEL as that makes Meta-DEL do SIGQUIT. ! 412: Instead set up C-g for both; we handle both alike ! 413: so which one it really gives us does not matter. */ ! 414: sg.c_cc[VQUIT] = '\007'; ! 415: #else /* not HPUX */ ! 416: sg.c_cc[VQUIT] = CDEL; /* Turn off SIGQUIT */ ! 417: #endif /* not HPUX */ ! 418: sg.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */ ! 419: sg.c_cc[VTIME] = 0; /* no matter how long that takes. */ ! 420: #ifdef VSWTCH ! 421: sg.c_cc[VSWTCH] = CDEL; /* Turn off shell layering use of C-z */ ! 422: #endif /* VSWTCH */ ! 423: #else /* if not USG */ ! 424: sg.sg_flags &= ~(ECHO | CRMOD | XTABS); ! 425: sg.sg_flags |= ANYP; ! 426: sg.sg_flags |= interrupt_input ? RAW : CBREAK; ! 427: #endif /* not USG (BSD, that is) */ ! 428: ! 429: ioctl (0, TIOCSETN, &sg); ! 430: ! 431: #ifdef F_SETFL ! 432: #ifdef F_GETOWN /* F_SETFL does not imply existance of F_GETOWN */ ! 433: if (interrupt_input) ! 434: { ! 435: old_fcntl_owner = fcntl (0, F_GETOWN, 0); ! 436: fcntl (0, F_SETOWN, getpid ()); ! 437: init_sigio (); ! 438: } ! 439: #endif /* F_GETOWN */ ! 440: #endif /* F_SETFL */ ! 441: ! 442: /* If going to use CBREAK mode, we must request C-g to interrupt ! 443: and turn off start and stop chars, etc. ! 444: If not going to use CBREAK mode, do this anyway ! 445: so as to turn off local flow control for user coming over ! 446: network on 4.2; in this case, only t_stopc and t_startc really matter. */ ! 447: #ifdef TIOCGLTC ! 448: ioctl (0, TIOCGETC, &old_tchars); ! 449: ioctl (0, TIOCGLTC, &old_ltchars); ! 450: ioctl (0, TIOCLGET, &old_lmode); ! 451: ! 452: /* Note: if not using CBREAK mode, it makes no difference how we set this */ ! 453: tchars = new_tchars; ! 454: tchars.t_intrc = 07; ! 455: if (flow_control) ! 456: { ! 457: tchars.t_startc = '\021'; ! 458: tchars.t_stopc = '\023'; ! 459: } ! 460: /* LPASS8 is new in 4.3, and makes cbreak mode provide all 8 bits. */ ! 461: #ifndef LPASS8 ! 462: #define LPASS8 0 ! 463: #endif ! 464: ! 465: #ifdef BSD4_1 ! 466: #define LNOFLSH 0100000 ! 467: #endif ! 468: ! 469: lmode = LDECCTQ | LLITOUT | LPASS8 | LNOFLSH | old_lmode; ! 470: ! 471: ioctl (0, TIOCSETC, &tchars); ! 472: ioctl (0, TIOCSLTC, &new_ltchars); ! 473: ioctl (0, TIOCLSET, &lmode); ! 474: #endif TIOCGLTC ! 475: #ifdef BSD4_1 ! 476: if (interrupt_input) ! 477: init_sigio (); ! 478: #endif ! 479: } ! 480: screen_garbaged = 1; ! 481: setbuf (stdout, _sobuf); ! 482: term_initted = 1; ! 483: set_terminal_modes (); ! 484: } ! 485: ! 486: /* Return nonzero if safe to use tabs in output. ! 487: At the time this is called, init_sys_modes has not been done yet. */ ! 488: ! 489: tabs_safe_p () ! 490: { ! 491: TERMINAL sg; ! 492: if (noninteractive) ! 493: return 1; ! 494: ioctl (0, TIOCGETP, &sg); ! 495: return (TABS_OK(sg)); ! 496: } ! 497: ! 498: /* Get terminal size from system. ! 499: Store number of lines into *heightp and width into *widthp. ! 500: If zero or a negative number is stored, the value is not valid. */ ! 501: ! 502: get_screen_size (widthp, heightp) ! 503: int *widthp, *heightp; ! 504: { ! 505: /* Define the 4.3 names in terms of the Sun names ! 506: if the latter exist and the former do not. */ ! 507: #if !defined (TIOCGWINSZ) && defined (TIOCGSIZE) ! 508: #define TIOCGWINSZ TIOCGSIZE ! 509: #define winsize ttysize ! 510: #define ws_row ts_lines ! 511: #define ws_col ts_cols ! 512: #endif /* Sun */ ! 513: ! 514: #ifdef TIOCGWINSZ ! 515: struct winsize size; ! 516: *widthp = 0; ! 517: *heightp = 0; ! 518: if (ioctl (0, TIOCGWINSZ, &size) < 0) ! 519: return; ! 520: *widthp = size.ws_col; ! 521: *heightp = size.ws_row; ! 522: #else /* system doesn't know size */ ! 523: *widthp = 0; ! 524: *heightp = 0; ! 525: #endif /* system does not know size */ ! 526: } ! 527: ! 528: reset_sys_modes () ! 529: { ! 530: if (noninteractive) ! 531: { ! 532: fflush (stdout); ! 533: return; ! 534: } ! 535: if (!term_initted) ! 536: return; ! 537: topos (screen_height - 1, 0); ! 538: clear_end_of_line (screen_width); ! 539: /* clear_end_of_line may move the cursor */ ! 540: topos (screen_height - 1, 0); ! 541: reset_terminal_modes (); ! 542: fflush (stdout); ! 543: if (read_socket_hook) ! 544: return; ! 545: #ifdef TIOCGLTC ! 546: ioctl (0, TIOCSETC, &old_tchars); ! 547: ioctl (0, TIOCSLTC, &old_ltchars); ! 548: ioctl (0, TIOCLSET, &old_lmode); ! 549: #endif /* TIOCGLTC */ ! 550: #ifdef F_SETFL ! 551: #ifdef F_SETOWN /* F_SETFL does not imply existance of F_SETOWN */ ! 552: if (interrupt_input) ! 553: { ! 554: #ifdef FASYNC ! 555: old_fcntl_flags &= ~FASYNC; ! 556: #endif /* FASYNC */ ! 557: reset_sigio (); ! 558: reset_sigio (); ! 559: fcntl (0, F_SETOWN, old_fcntl_owner); ! 560: } ! 561: #endif /* F_SETOWN */ ! 562: #endif /* F_SETFL */ ! 563: #ifdef BSD4_1 ! 564: if (interrupt_input) ! 565: reset_sigio (); ! 566: #endif /* BSD4_1 */ ! 567: ioctl (0, TIOCSETN, &old_gtty); ! 568: } ! 569: ! 570: /* ! 571: * flush any pending output ! 572: */ ! 573: ! 574: flush_pending_output (channel) ! 575: int channel; ! 576: { ! 577: #ifdef USG ! 578: ioctl (channel, TCFLSH, 1); ! 579: #else ! 580: ioctl (channel, TIOCFLUSH, 0); ! 581: #endif ! 582: } ! 583: ! 584: /* ! 585: * Return the address of the start of the text segment prior to ! 586: * doing an unexec(). After unexec() the return value is undefined. ! 587: * See crt0.c for further explanation and _start(). ! 588: * ! 589: */ ! 590: ! 591: char * ! 592: start_of_text () ! 593: { ! 594: #ifdef TEXT_START ! 595: return ((char *) TEXT_START); ! 596: #else ! 597: extern int _start (); ! 598: return ((char *) _start); ! 599: #endif ! 600: } ! 601: ! 602: /* ! 603: * Return the address of the start of the data segment prior to ! 604: * doing an unexec(). After unexec() the return value is undefined. ! 605: * See crt0.c for further information and definition of data_start. ! 606: * ! 607: * Apparently, on BSD systems this is etext at startup. On ! 608: * USG systems (swapping) this is highly mmu dependent and ! 609: * is also dependent on whether or not the program is running ! 610: * with shared text. Generally there is a (possibly large) ! 611: * gap between end of text and start of data with shared text. ! 612: * ! 613: * On Uniplus+ systems with shared text, data starts at a ! 614: * fixed address. Each port (from a given oem) is generally ! 615: * different, and the specific value of the start of data can ! 616: * be obtained via the UniPlus+ specific "uvar(2)" system call, ! 617: * however the method outlined in crt0.c seems to be more portable. ! 618: * ! 619: * Probably what will have to happen when a USG unexec is available, ! 620: * at least on UniPlus, is temacs will have to be made unshared so ! 621: * that text and data are contiguous. Then once loadup is complete, ! 622: * unexec will produce a shared executable where the data can be ! 623: * at the normal shared text boundry and the startofdata variable ! 624: * will be patched by unexec to the correct value. ! 625: * ! 626: */ ! 627: ! 628: char * ! 629: start_of_data () ! 630: { ! 631: #ifdef DATA_START ! 632: return ((char *) DATA_START); ! 633: #else ! 634: extern int data_start; ! 635: return ((char *) &data_start); ! 636: #endif ! 637: } ! 638: ! 639: #ifdef NOTDEF ! 640: ! 641: /* ! 642: * Return the address of the end of the text segment prior to ! 643: * doing an unexec(). After unexec() the return value is undefined. ! 644: */ ! 645: ! 646: char * ! 647: end_of_text () ! 648: { ! 649: #ifdef TEXT_END ! 650: return ((char *) TEXT_END); ! 651: #else ! 652: extern int etext; ! 653: return ((char *) &etext); ! 654: #endif ! 655: } ! 656: ! 657: /* ! 658: * Return the address of the end of the data segment prior to ! 659: * doing an unexec(). After unexec() the return value is undefined. ! 660: */ ! 661: ! 662: char * ! 663: end_of_data () ! 664: { ! 665: #ifdef DATA_END ! 666: return ((char *) DATA_END); ! 667: #else ! 668: extern int edata; ! 669: return ((char *) &edata); ! 670: #endif ! 671: } ! 672: ! 673: #endif NOTDEF ! 674: ! 675: ! 676: /* Get_system_name returns as its value ! 677: a string for the Lisp function system-name to return. */ ! 678: ! 679: #ifdef USG ! 680: struct utsname get_system_name_name; ! 681: #endif ! 682: #ifdef BSD4_1 ! 683: #include <whoami.h> ! 684: #endif ! 685: ! 686: char * ! 687: get_system_name () ! 688: { ! 689: #ifdef USG ! 690: uname (&get_system_name_name); ! 691: return (get_system_name_name.nodename); ! 692: #else /* Not USG */ ! 693: #ifdef BSD4_1 ! 694: return sysname; ! 695: #else /* BSD, not 4.1 */ ! 696: static char system_name_saved[32]; ! 697: (void) gethostname (system_name_saved, sizeof (system_name_saved)); ! 698: return (system_name_saved); ! 699: #endif /* BSD, not 4.1 */ ! 700: #endif /* not USG */ ! 701: } ! 702: ! 703: #ifndef HAVE_SELECT ! 704: ! 705: /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs ! 706: * Only checks read descriptors. ! 707: */ ! 708: /* How long to wait between checking fds in select */ ! 709: #define SELECT_PAUSE 1 ! 710: int select_alarmed; ! 711: ! 712: select_alarm () ! 713: { ! 714: select_alarmed = 1; ! 715: #ifdef BSD4_1 ! 716: sigrelse (SIGALRM); ! 717: #else /* not BSD4_1 */ ! 718: signal (SIGALRM, SIG_IGN); ! 719: #endif /* not BSD4_1 */ ! 720: } ! 721: ! 722: /* Only rfds are checked and timeout must point somewhere */ ! 723: int ! 724: select (nfds, rfds, wfds, efds, timeout) ! 725: int nfds; ! 726: int *rfds, *wfds, *efds, *timeout; ! 727: { ! 728: int ravail = 0, orfds = 0, old_alarm, val; ! 729: extern int kbd_count; ! 730: extern int proc_buffered_char[]; ! 731: extern int child_changed; ! 732: int (*old_trap) (); ! 733: char buf; ! 734: ! 735: if (rfds) ! 736: { ! 737: orfds = *rfds; ! 738: *rfds = 0; ! 739: } ! 740: if (wfds) ! 741: *wfds = 0; ! 742: if (efds) ! 743: *efds = 0; ! 744: ! 745: /* If we are looking only for the terminal, with no timeout, ! 746: just read it and wait -- that's more efficient. */ ! 747: if (orfds == 1 && *timeout == 100000 && !child_changed) ! 748: { ! 749: if (!kbd_count) ! 750: read_input_waiting (); ! 751: *rfds = 1; ! 752: return 1; ! 753: } ! 754: ! 755: /* Once a second, till the timer expires, check all the flagged read ! 756: * descriptors to see if any input is available. If there is some then ! 757: * set the corresponding bit in the return copy of rfds. ! 758: */ ! 759: while (1) ! 760: { ! 761: register int to_check, bit, fd; ! 762: ! 763: if (rfds) ! 764: { ! 765: for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++) ! 766: { ! 767: if (orfds & bit) ! 768: { ! 769: int avail = 0, status = 0; ! 770: ! 771: if (bit == 1) ! 772: avail = detect_input_pending(); /* Special keyboard handler */ ! 773: else ! 774: { ! 775: #ifdef FIONREAD ! 776: status = ioctl (fd, FIONREAD, &avail); ! 777: #else /* no FIONREAD */ ! 778: /* Hoping it will return -1 if nothing available ! 779: or 0 if all 0 chars requested are read. */ ! 780: if (proc_buffered_char[fd] >= 0) ! 781: avail = 1; ! 782: else ! 783: { ! 784: avail = read (fd, &buf, 1); ! 785: if (avail > 0) ! 786: proc_buffered_char[fd] = buf; ! 787: } ! 788: #endif /* no FIONREAD */ ! 789: } ! 790: if (status >= 0 && avail > 0) ! 791: { ! 792: (*rfds) |= bit; ! 793: ravail++; ! 794: } ! 795: } ! 796: } ! 797: } ! 798: if (*timeout == 0 || ravail != 0 || child_changed) ! 799: break; ! 800: old_alarm = alarm (0); ! 801: old_trap = signal (SIGALRM, select_alarm); ! 802: select_alarmed = 0; ! 803: alarm (SELECT_PAUSE); ! 804: /* Wait for a SIGALRM (or maybe a SIGTINT) */ ! 805: while (select_alarmed == 0 && *timeout != 0 && child_changed == 0) ! 806: { ! 807: /* If we are interested in terminal input, ! 808: wait by reading the terminal. ! 809: That makes instant wakeup for terminal input at least. */ ! 810: if (orfds & 1) ! 811: { ! 812: read_input_waiting (); ! 813: if (kbd_count) ! 814: select_alarmed = 1; ! 815: } ! 816: else ! 817: pause(); ! 818: } ! 819: (*timeout) -= SELECT_PAUSE; ! 820: /* Reset the old alarm if there was one */ ! 821: alarm (0); ! 822: signal (SIGALRM, old_trap); ! 823: if (old_alarm != 0) ! 824: { ! 825: /* Reset or forge an interrupt for the original handler. */ ! 826: old_alarm -= SELECT_PAUSE; ! 827: if (old_alarm <= 0) ! 828: kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */ ! 829: else ! 830: alarm (old_alarm); ! 831: } ! 832: if (*timeout == 0) /* Stop on timer being cleared */ ! 833: break; ! 834: } ! 835: return ravail; ! 836: } ! 837: ! 838: /* Read keyboard input into the standard buffer, ! 839: waiting for at least one character. */ ! 840: ! 841: read_input_waiting () ! 842: { ! 843: extern int kbd_count; ! 844: extern unsigned char kbd_buffer[]; ! 845: extern unsigned char *kbd_ptr; ! 846: int val = read (fileno(stdin), kbd_buffer, 1); ! 847: if (val > 0) ! 848: { ! 849: kbd_ptr = kbd_buffer; ! 850: kbd_count = val; ! 851: } ! 852: } ! 853: ! 854: #endif /* not HAVE_SELECT */ ! 855: ! 856: #ifdef BSD4_1 ! 857: /* VARARGS */ ! 858: setpriority () ! 859: { ! 860: return 0; ! 861: } ! 862: ! 863: /* ! 864: * Partially emulate 4.2 open call. ! 865: * open is defined as this in 4.1. ! 866: * ! 867: * - added by Michael Bloom @ Citicorp/TTI ! 868: * ! 869: */ ! 870: ! 871: int ! 872: sys_open (path, oflag, mode) ! 873: char *path; ! 874: int oflag, mode; ! 875: { ! 876: if (oflag & O_CREAT) ! 877: return creat (path, mode); ! 878: else ! 879: return open (path, oflag); ! 880: } ! 881: ! 882: init_sigio () ! 883: { ! 884: if (noninteractive) ! 885: return; ! 886: lmode = LINTRUP | lmode; ! 887: ioctl (0, TIOCLSET, &lmode); ! 888: } ! 889: ! 890: reset_sigio () ! 891: { ! 892: if (noninteractive) ! 893: return; ! 894: lmode = ~LINTRUP & lmode; ! 895: ioctl (0, TIOCLSET, &lmode); ! 896: } ! 897: ! 898: request_sigio () ! 899: { ! 900: sigrelse (SIGTINT); ! 901: } ! 902: ! 903: unrequest_sigio () ! 904: { ! 905: sighold (SIGTINT); ! 906: } ! 907: ! 908: /* still inside #ifdef BSD4_1 */ ! 909: #ifdef subprocesses ! 910: ! 911: int sigheld; /* Mask of held signals */ ! 912: ! 913: sigholdx (signum) ! 914: int signum; ! 915: { ! 916: sigheld |= sigbit (signum); ! 917: sighold (signum); ! 918: } ! 919: ! 920: sigisheld (signum) ! 921: int signum; ! 922: { ! 923: sigheld |= sigbit (signum); ! 924: } ! 925: ! 926: sigunhold (signum) ! 927: int signum; ! 928: { ! 929: sigheld &= ~sigbit (signum); ! 930: sigrelse (signum); ! 931: } ! 932: ! 933: sigfree () /* Free all held signals */ ! 934: { ! 935: int i; ! 936: for (i = 0; i < NSIG; i++) ! 937: if (sigheld & sigbit (i)) ! 938: sigrelse (i); ! 939: sigheld = 0; ! 940: } ! 941: ! 942: sigbit (i) ! 943: { ! 944: return 1 << (i - 1); ! 945: } ! 946: #endif /* subprocesses */ ! 947: #endif /* BSD4_1 */ ! 948: ! 949: #ifndef BSTRING ! 950: ! 951: void ! 952: bzero (b, length) ! 953: register char *b; ! 954: register int length; ! 955: { ! 956: while (length-- > 0) ! 957: *b++ = 0; ! 958: } ! 959: ! 960: void ! 961: bcopy (b1, b2, length) ! 962: register char *b1; ! 963: register char *b2; ! 964: register int length; ! 965: { ! 966: while (length-- > 0) ! 967: *b2++ = *b1++; ! 968: } ! 969: ! 970: int ! 971: bcmp (b1, b2, length) /* This could be a macro! */ ! 972: register char *b1; ! 973: register char *b2; ! 974: register int length; ! 975: { ! 976: while (length-- > 0) ! 977: if (*b1++ != *b2++) ! 978: return 1; ! 979: ! 980: return 0; ! 981: } ! 982: #endif /* not BSTRING */ ! 983: ! 984: #if defined (BSD4_1) || defined (USG) ! 985: ! 986: /* ! 987: * The BSD random(3) returns numbers in the range of ! 988: * 0 to 2e31 - 1. The USG rand(3C) returns numbers in the ! 989: * range of 0 to 2e15 - 1. This is probably not significant ! 990: * in this usage. ! 991: */ ! 992: ! 993: long ! 994: random () ! 995: { ! 996: return (rand ()); ! 997: } ! 998: ! 999: srandom (arg) ! 1000: int arg; ! 1001: { ! 1002: srand (arg); ! 1003: } ! 1004: ! 1005: #endif /* bsd4.1 or any USG */ ! 1006: ! 1007: #ifdef USG ! 1008: /* ! 1009: * All of the following are for USG. ! 1010: * ! 1011: * On USG systems the system calls are interruptable by signals ! 1012: * that the user program has elected to catch. Thus the system call ! 1013: * must be retried in these cases. To handle this without massive ! 1014: * changes in the source code, we remap the standard system call names ! 1015: * to names for our own functions in sysdep.c that do the system call ! 1016: * with retries. Actually, for portability reasons, it is good ! 1017: * programming practice, as this example shows, to limit all actual ! 1018: * system calls to a single occurance in the source. Sure, this ! 1019: * adds an extra level of function call overhead but it is almost ! 1020: * always negligible. Fred Fish, Unisoft Systems Inc. ! 1021: */ ! 1022: ! 1023: char *sys_siglist[NSIG + 1] = ! 1024: { ! 1025: "bogus signal", /* 0 */ ! 1026: "hangup", /* 1 SIGHUP */ ! 1027: "interrupt", /* 2 SIGINT */ ! 1028: "quit", /* 3 SIGQUIT */ ! 1029: "illegal instruction", /* 4 SIGILL */ ! 1030: "trace trap", /* 5 SIGTRAP */ ! 1031: "IOT instruction", /* 6 SIGIOT */ ! 1032: "EMT instruction", /* 7 SIGEMT */ ! 1033: "floating point exception", /* 8 SIGFPE */ ! 1034: "kill", /* 9 SIGKILL */ ! 1035: "bus error", /* 10 SIGBUS */ ! 1036: "segmentation violation", /* 11 SIGSEGV */ ! 1037: "bad argument to system call", /* 12 SIGSYS */ ! 1038: "write on a pipe with no one to read it", /* 13 SIGPIPE */ ! 1039: "alarm clock", /* 14 SIGALRM */ ! 1040: "software termination signum", /* 15 SIGTERM */ ! 1041: "user defined signal 1", /* 16 SIGUSR1 */ ! 1042: "user defined signal 2", /* 17 SIGUSR2 */ ! 1043: "death of a child", /* 18 SIGCLD */ ! 1044: "power-fail restart", /* 19 SIGPWR */ ! 1045: 0 ! 1046: }; ! 1047: ! 1048: int ! 1049: sys_read (fildes, buf, nbyte) ! 1050: int fildes; ! 1051: char *buf; ! 1052: unsigned int nbyte; ! 1053: { ! 1054: register int rtnval; ! 1055: ! 1056: while ((rtnval = read (fildes, buf, nbyte)) == -1 && errno == EINTR); ! 1057: return (rtnval); ! 1058: } ! 1059: ! 1060: int ! 1061: /* VARARGS 2 */ ! 1062: sys_open (path, oflag, mode) ! 1063: char *path; ! 1064: int oflag, mode; ! 1065: { ! 1066: register int rtnval; ! 1067: ! 1068: while ((rtnval = open (path, oflag, mode)) == -1 && errno == EINTR); ! 1069: return (rtnval); ! 1070: } ! 1071: ! 1072: int ! 1073: sys_write (fildes, buf, nbyte) ! 1074: int fildes; ! 1075: char *buf; ! 1076: unsigned int nbyte; ! 1077: { ! 1078: register int rtnval; ! 1079: ! 1080: while ((rtnval = write (fildes, buf, nbyte)) == -1 && errno == EINTR); ! 1081: return (rtnval); ! 1082: } ! 1083: ! 1084: /* ! 1085: * Warning, this function may not duplicate 4.2 action properly ! 1086: * under error conditions. ! 1087: */ ! 1088: ! 1089: #ifndef MAXPATHLEN ! 1090: /* In 4.1, param.h fails to define this. */ ! 1091: #define MAXPATHLEN 1024 ! 1092: #endif ! 1093: ! 1094: char * ! 1095: getwd (pathname) ! 1096: char *pathname; ! 1097: { ! 1098: extern char *getcwd (); ! 1099: ! 1100: return (getcwd (pathname, MAXPATHLEN)); ! 1101: } ! 1102: ! 1103: /* ! 1104: * Emulate rename using unlink/link. Note that this is ! 1105: * only partially correct. Also, doesn't enforce restriction ! 1106: * that files be of same type (regular->regular, dir->dir, etc). ! 1107: */ ! 1108: ! 1109: rename (from, to) ! 1110: char *from; ! 1111: char *to; ! 1112: { ! 1113: if (access (from, 0) == 0) ! 1114: { ! 1115: unlink (to); ! 1116: if (link (from, to) == 0) ! 1117: if (unlink (from) == 0) ! 1118: return (0); ! 1119: } ! 1120: return (-1); ! 1121: } ! 1122: ! 1123: /* VARARGS */ ! 1124: setpriority () ! 1125: { ! 1126: return (0); ! 1127: } ! 1128: ! 1129: #ifndef HPUX ! 1130: ! 1131: /* ! 1132: * Substitute fork(2) for vfork(2) on USG flavors. ! 1133: */ ! 1134: ! 1135: vfork () ! 1136: { ! 1137: return (fork ()); ! 1138: } ! 1139: ! 1140: /* ! 1141: * Emulate BSD dup2(2). First close newd if it already exists. ! 1142: * Then, attempt to dup oldd. If not successful, call dup2 recursively ! 1143: * until we are, then close the unsuccessful ones. ! 1144: */ ! 1145: ! 1146: dup2 (oldd, newd) ! 1147: int oldd; ! 1148: int newd; ! 1149: { ! 1150: register int fd; ! 1151: ! 1152: close (newd); ! 1153: while ((fd = dup (oldd)) != newd) { ! 1154: dup2 (oldd, newd); ! 1155: close (fd); ! 1156: } ! 1157: } ! 1158: ! 1159: /* ! 1160: * Gettimeofday. Simulate as much as possible. Only accurate ! 1161: * to nearest second. Emacs doesn't use tzp so ignore it for now. ! 1162: * Only needed when subprocesses are defined. ! 1163: */ ! 1164: ! 1165: #if defined(subprocesses) && !defined(STRIDE) && defined(HAVE_TIMEVAL) ! 1166: ! 1167: /* ARGSUSED */ ! 1168: gettimeofday (tp, tzp) ! 1169: struct timeval *tp; ! 1170: struct timezone *tzp; ! 1171: { ! 1172: extern long time (); ! 1173: ! 1174: tp->tv_sec = time ((long *)0); ! 1175: tp->tv_usec = 0; ! 1176: } ! 1177: ! 1178: #endif /* subprocess && ~STRIDE && HAVE_TIMEVAL */ ! 1179: #endif /* not HPUX */ ! 1180: ! 1181: /* ! 1182: * This function will go away as soon as all the stubs fixed. (fnf) ! 1183: */ ! 1184: ! 1185: croak (badfunc) ! 1186: char *badfunc; ! 1187: { ! 1188: printf ("%s not yet implemented\r\n", badfunc); ! 1189: reset_sys_modes (); ! 1190: exit (1); ! 1191: } ! 1192: ! 1193: #endif /* USG */ ! 1194: ! 1195: /* Directory routines for systems that don't have them. */ ! 1196: ! 1197: #ifdef NONSYSTEM_DIR_LIBRARY ! 1198: ! 1199: DIR * ! 1200: opendir (filename) ! 1201: char *filename; /* name of directory */ ! 1202: { ! 1203: register DIR *dirp; /* -> malloc'ed storage */ ! 1204: register int fd; /* file descriptor for read */ ! 1205: struct stat sbuf; /* result of fstat() */ ! 1206: ! 1207: fd = sys_open (filename, 0); ! 1208: if (fd < 0) ! 1209: return 0; ! 1210: ! 1211: if (fstat (fd, &sbuf) < 0 ! 1212: || (sbuf.st_mode & S_IFMT) != S_IFDIR ! 1213: || (dirp = (DIR *) malloc (sizeof (DIR))) == 0) ! 1214: { ! 1215: close (fd); ! 1216: return 0; /* bad luck today */ ! 1217: } ! 1218: ! 1219: dirp->dd_fd = fd; ! 1220: dirp->dd_loc = dirp->dd_size = 0; /* refill needed */ ! 1221: ! 1222: return dirp; ! 1223: } ! 1224: ! 1225: void ! 1226: closedir (dirp) ! 1227: register DIR *dirp; /* stream from opendir() */ ! 1228: { ! 1229: close (dirp->dd_fd); ! 1230: free ((char *) dirp); ! 1231: } ! 1232: ! 1233: ! 1234: #define DIRSIZ 14 ! 1235: struct olddir ! 1236: { ! 1237: ino_t od_ino; /* inode */ ! 1238: char od_name[DIRSIZ]; /* filename */ ! 1239: }; ! 1240: ! 1241: struct direct dir_static; /* simulated directory contents */ ! 1242: ! 1243: struct direct * ! 1244: readdir (dirp) ! 1245: register DIR *dirp; /* stream from opendir() */ ! 1246: { ! 1247: register struct olddir *dp; /* -> directory data */ ! 1248: ! 1249: for ( ; ; ) ! 1250: { ! 1251: if (dirp->dd_loc >= dirp->dd_size) ! 1252: dirp->dd_loc = dirp->dd_size = 0; ! 1253: ! 1254: if (dirp->dd_size == 0 /* refill buffer */ ! 1255: && (dirp->dd_size = sys_read (dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ)) <= 0) ! 1256: return 0; ! 1257: ! 1258: dp = (struct olddir *) &dirp->dd_buf[dirp->dd_loc]; ! 1259: dirp->dd_loc += sizeof (struct olddir); ! 1260: ! 1261: if (dp->od_ino != 0) /* not deleted entry */ ! 1262: { ! 1263: dir_static.d_ino = dp->od_ino; ! 1264: strncpy (dir_static.d_name, dp->od_name, DIRSIZ); ! 1265: dir_static.d_name[DIRSIZ] = '\0'; ! 1266: dir_static.d_namlen = strlen (dir_static.d_name); ! 1267: dir_static.d_reclen = sizeof (struct direct) ! 1268: - MAXNAMLEN + 3 ! 1269: + dir_static.d_namlen - dir_static.d_namlen % 4; ! 1270: return &dir_static; /* -> simulated structure */ ! 1271: } ! 1272: } ! 1273: } ! 1274: ! 1275: #endif /* NONSYSTEM_DIR_LIBRARY */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.