|
|
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.