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 */