Annotation of gforth/io.c, revision 1.11
1.11 ! anton 1: /* direct key io driver; signal handler
1.1 anton 2:
1.11 ! anton 3: Copyright (C) 1995 Free Software Foundation, Inc.
! 4:
! 5: This file is part of Gforth.
! 6:
! 7: Gforth is free software; you can redistribute it and/or
! 8: modify it under the terms of the GNU General Public License
! 9: as published by the Free Software Foundation; either version 2
! 10: of the License, or (at your option) any later version.
! 11:
! 12: This program is distributed in the hope that it will be useful,
! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 15: GNU General Public License for more details.
! 16:
! 17: You should have received a copy of the GNU General Public License
! 18: along with this program; if not, write to the Free Software
! 19: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
! 20:
! 21: The following is stolen from the readline library for bash
1.1 anton 22: */
23:
1.8 anton 24: /*
1.2 benschop 25: Use -D_POSIX_VERSION for POSIX systems.
26: */
27:
1.7 anton 28: #include <unistd.h>
29:
1.8 anton 30: #ifdef apollo
1.2 benschop 31: #define _POSIX_VERSION
32: #endif
33:
1.1 anton 34: #include <stdio.h>
35: #include <signal.h>
1.10 anton 36: #include <string.h>
1.1 anton 37: #include <sys/types.h>
1.8 anton 38: #ifndef apollo
1.1 anton 39: #include <sys/ioctl.h>
1.2 benschop 40: #endif
1.1 anton 41: #include <fcntl.h>
42: #include <sys/file.h>
1.4 anton 43: #include <setjmp.h>
44: #include "forth.h"
45: #include "io.h"
1.1 anton 46:
47: #if defined (__GNUC__)
48: # define alloca __builtin_alloca
49: #else
50: # if defined (sparc) || defined (HAVE_ALLOCA_H)
51: # include <alloca.h>
52: # endif
53: #endif
54:
55: #define NEW_TTY_DRIVER
56: #define HAVE_BSD_SIGNALS
1.5 pazsan 57: /*
1.8 anton 58: #ifndef apollo
1.1 anton 59: #define USE_XON_XOFF
1.2 benschop 60: #endif
1.5 pazsan 61: */
1.1 anton 62:
1.5 pazsan 63: #define HANDLE_SIGNALS
64:
1.1 anton 65: /* Some USG machines have BSD signal handling (sigblock, sigsetmask, etc.) */
66: #if defined (USG) && !defined (hpux)
67: #undef HAVE_BSD_SIGNALS
68: #endif
69:
70: /* System V machines use termio. */
71: #if !defined (_POSIX_VERSION)
1.6 pazsan 72: # if defined (USG) || defined (hpux) || defined (Xenix) || defined (sgi) || defined (DGUX) || defined (ultrix) || defined (Solaris)
1.1 anton 73: # undef NEW_TTY_DRIVER
74: # define TERMIO_TTY_DRIVER
75: # include <termio.h>
76: # if !defined (TCOON)
77: # define TCOON 1
78: # endif
79: # endif /* USG || hpux || Xenix || sgi || DUGX || ultrix*/
80: #endif /* !_POSIX_VERSION */
81:
82: /* Posix systems use termios and the Posix signal functions. */
83: #if defined (_POSIX_VERSION)
84: # if !defined (TERMIOS_MISSING)
85: # undef NEW_TTY_DRIVER
86: # define TERMIOS_TTY_DRIVER
87: # include <termios.h>
88: # endif /* !TERMIOS_MISSING */
89: # define HAVE_POSIX_SIGNALS
90: # if !defined (O_NDELAY)
91: # define O_NDELAY O_NONBLOCK /* Posix-style non-blocking i/o */
92: # endif /* O_NDELAY */
93: #endif /* _POSIX_VERSION */
94:
95: /* Other (BSD) machines use sgtty. */
96: #if defined (NEW_TTY_DRIVER)
97: #include <sgtty.h>
98: #endif
99:
100: /* Define _POSIX_VDISABLE if we are not using the `new' tty driver and
101: it is not already defined. It is used both to determine if a
102: special character is disabled and to disable certain special
103: characters. Posix systems should set to 0, USG systems to -1. */
104: #if !defined (NEW_TTY_DRIVER) && !defined (_POSIX_VDISABLE)
105: # if defined (_POSIX_VERSION)
106: # define _POSIX_VDISABLE 0
107: # else /* !_POSIX_VERSION */
108: # define _POSIX_VDISABLE -1
109: # endif /* !_POSIX_VERSION */
110: #endif /* !NEW_TTY_DRIVER && !_POSIX_VDISABLE */
111:
112: #include <errno.h>
113: extern int errno;
114:
115: #if defined (SHELL)
116: # include <posixstat.h>
117: #else
118: # include <sys/stat.h>
119: #endif /* !SHELL */
120: /* #define HACK_TERMCAP_MOTION */
121:
122: #if defined (USG) && defined (hpux)
123: # if !defined (USGr3)
124: # define USGr3
125: # endif /* USGr3 */
126: #endif /* USG && hpux */
127:
1.8 anton 128: #if (defined (_POSIX_VERSION) || defined (USGr3)) && !defined(apollo)
1.1 anton 129: # include <dirent.h>
130: # define direct dirent
131: # if defined (_POSIX_VERSION)
132: # define D_NAMLEN(d) (strlen ((d)->d_name))
133: # else /* !_POSIX_VERSION */
134: # define D_NAMLEN(d) ((d)->d_reclen)
135: # endif /* !_POSIX_VERSION */
136: #else /* !_POSIX_VERSION && !USGr3 */
137: # define D_NAMLEN(d) ((d)->d_namlen)
138: # if !defined (USG)
139: # include <sys/dir.h>
140: # else /* USG */
141: # if defined (Xenix)
142: # include <sys/ndir.h>
143: # else /* !Xenix */
144: # include <ndir.h>
145: # endif /* !Xenix */
146: # endif /* USG */
147: #endif /* !POSIX_VERSION && !USGr3 */
148:
149: #if defined (USG) && defined (TIOCGWINSZ)
150: # include <sys/stream.h>
151: # if defined (USGr4) || defined (USGr3)
152: # if defined (Symmetry) || defined (_SEQUENT_)
153: # include <sys/pte.h>
154: # else
155: # include <sys/ptem.h>
156: # endif /* !Symmetry || _SEQUENT_ */
157: # endif /* USGr4 */
158: #endif /* USG && TIOCGWINSZ */
159:
160: #if defined (TERMIOS_TTY_DRIVER)
161: static struct termios otio;
162: #else
163: static struct termio otio;
164: #endif /* !TERMIOS_TTY_DRIVER */
165:
166: /* Non-zero means echo characters as they are read. */
167: int readline_echoing_p = 1;
168:
169: /* The character that can generate an EOF. Really read from
170: the terminal driver... just defaulted here. */
171:
172: #ifndef CTRL
173: #define CTRL(key) ((key)-'@')
174: #endif
175:
176: static int eof_char = CTRL ('D');
177:
178: /* **************************************************************** */
179: /* */
180: /* Saving and Restoring the TTY */
181: /* */
182: /* **************************************************************** */
183:
184: /* Non-zero means that the terminal is in a prepped state. */
185: static int terminal_prepped = 0;
186:
187: #if defined (NEW_TTY_DRIVER)
188:
189: /* Standard flags, including ECHO. */
190: static int original_tty_flags = 0;
191:
192: /* Local mode flags, like LPASS8. */
193: static int local_mode_flags = 0;
194:
195: /* Terminal characters. This has C-s and C-q in it. */
196: static struct tchars original_tchars;
197:
198: /* Local special characters. This has the interrupt characters in it. */
199: #if defined (TIOCGLTC)
200: static struct ltchars original_ltchars;
201: #endif
202:
203: /* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */
204:
205: #if defined (TIOCGETC)
206: #if defined (USE_XON_XOFF)
207:
208: int
209: bind_key (key, function)
210: int key;
211: Function *function;
212: {
213: if (key < 0)
214: return (key);
215:
216: if (key > 127 && key < 256)
217: {
218: if (keymap[ESC].type == ISKMAP)
219: {
220: Keymap escmap = (Keymap)keymap[ESC].function;
221:
222: key -= 128;
223: escmap[key].type = ISFUNC;
224: escmap[key].function = function;
225: return (0);
226: }
227: return (key);
228: }
229:
230: keymap[key].type = ISFUNC;
231: keymap[key].function = function;
232: return (0);
233: }
234: #endif
235: #endif
236:
237: /* We use this to get and set the tty_flags. */
238: static struct sgttyb the_ttybuff;
239:
240: #if defined (USE_XON_XOFF)
241: /* If the terminal was in xoff state when we got to it, then xon_char
242: contains the character that is supposed to start it again. */
243: static int xon_char, xoff_state;
244: #endif /* USE_XON_XOFF */
245:
246: /* **************************************************************** */
247: /* */
248: /* Bogus Flow Control */
249: /* */
250: /* **************************************************************** */
251:
252: restart_output (count, key)
253: int count, key;
254: {
255: int fildes = fileno (stdin);
256: #if defined (TIOCSTART)
257: #if defined (apollo)
258: ioctl (&fildes, TIOCSTART, 0);
259: #else
260: ioctl (fildes, TIOCSTART, 0);
261: #endif /* apollo */
262:
263: #else
264: # if defined (TERMIOS_TTY_DRIVER)
265: tcflow (fildes, TCOON);
266: # else
267: # if defined (TCXONC)
268: ioctl (fildes, TCXONC, TCOON);
269: # endif /* TCXONC */
270: # endif /* !TERMIOS_TTY_DRIVER */
271: #endif /* TIOCSTART */
272: }
273:
274: /* Put the terminal in CBREAK mode so that we can detect key presses. */
275: void prep_terminal ()
276: {
277: int tty = fileno (stdin);
278: #if defined (HAVE_BSD_SIGNALS)
279: int oldmask;
280: #endif /* HAVE_BSD_SIGNALS */
281:
282: if (terminal_prepped)
283: return;
284:
285: oldmask = sigblock (sigmask (SIGINT));
286:
287: /* We always get the latest tty values. Maybe stty changed them. */
288: ioctl (tty, TIOCGETP, &the_ttybuff);
289: original_tty_flags = the_ttybuff.sg_flags;
290:
291: readline_echoing_p = (original_tty_flags & ECHO);
292:
293: #if defined (TIOCLGET)
294: ioctl (tty, TIOCLGET, &local_mode_flags);
295: #endif
296:
297: #if !defined (ANYP)
298: # define ANYP (EVENP | ODDP)
299: #endif
300:
301: /* If this terminal doesn't care how the 8th bit is used,
302: then we can use it for the meta-key. We check by seeing
303: if BOTH odd and even parity are allowed. */
304: if (the_ttybuff.sg_flags & ANYP)
305: {
306: #if defined (PASS8)
307: the_ttybuff.sg_flags |= PASS8;
308: #endif
309:
310: /* Hack on local mode flags if we can. */
311: #if defined (TIOCLGET) && defined (LPASS8)
312: {
313: int flags;
314: flags = local_mode_flags | LPASS8;
315: ioctl (tty, TIOCLSET, &flags);
316: }
317: #endif /* TIOCLGET && LPASS8 */
318: }
319:
320: #if defined (TIOCGETC)
321: {
322: struct tchars temp;
323:
324: ioctl (tty, TIOCGETC, &original_tchars);
325: temp = original_tchars;
326:
327: #if defined (USE_XON_XOFF)
328: /* Get rid of C-s and C-q.
329: We remember the value of startc (C-q) so that if the terminal is in
330: xoff state, the user can xon it by pressing that character. */
331: xon_char = temp.t_startc;
332: temp.t_stopc = -1;
333: temp.t_startc = -1;
334:
335: /* If there is an XON character, bind it to restart the output. */
336: if (xon_char != -1)
337: bind_key (xon_char, restart_output);
338: #endif /* USE_XON_XOFF */
339:
340: /* If there is an EOF char, bind eof_char to it. */
341: if (temp.t_eofc != -1)
342: eof_char = temp.t_eofc;
343:
344: #if defined (NO_KILL_INTR)
345: /* Get rid of C-\ and C-c. */
346: temp.t_intrc = temp.t_quitc = -1;
347: #endif /* NO_KILL_INTR */
348:
349: ioctl (tty, TIOCSETC, &temp);
350: }
351: #endif /* TIOCGETC */
352:
353: #if defined (TIOCGLTC)
354: {
355: struct ltchars temp;
356:
357: ioctl (tty, TIOCGLTC, &original_ltchars);
358: temp = original_ltchars;
359:
360: /* Make the interrupt keys go away. Just enough to make people
361: happy. */
362: temp.t_dsuspc = -1; /* C-y */
363: temp.t_lnextc = -1; /* C-v */
364:
365: ioctl (tty, TIOCSLTC, &temp);
366: }
367: #endif /* TIOCGLTC */
368:
369: the_ttybuff.sg_flags &= ~(ECHO | CRMOD);
370: the_ttybuff.sg_flags |= CBREAK;
371: ioctl (tty, TIOCSETN, &the_ttybuff);
372:
373: terminal_prepped = 1;
374:
375: #if defined (HAVE_BSD_SIGNALS)
376: sigsetmask (oldmask);
377: #endif
378: }
379:
380: /* Restore the terminal to its original state. */
381: void deprep_terminal ()
382: {
383: int tty = fileno (stdin);
384: #if defined (HAVE_BSD_SIGNALS)
385: int oldmask;
386: #endif
387:
388: if (!terminal_prepped)
389: return;
390:
391: oldmask = sigblock (sigmask (SIGINT));
392:
393: the_ttybuff.sg_flags = original_tty_flags;
394: ioctl (tty, TIOCSETN, &the_ttybuff);
395: readline_echoing_p = 1;
396:
397: #if defined (TIOCLGET)
398: ioctl (tty, TIOCLSET, &local_mode_flags);
399: #endif
400:
401: #if defined (TIOCSLTC)
402: ioctl (tty, TIOCSLTC, &original_ltchars);
403: #endif
404:
405: #if defined (TIOCSETC)
406: ioctl (tty, TIOCSETC, &original_tchars);
407: #endif
408: terminal_prepped = 0;
409:
410: #if defined (HAVE_BSD_SIGNALS)
411: sigsetmask (oldmask);
412: #endif
413: }
414:
415: #else /* !defined (NEW_TTY_DRIVER) */
416:
417: #if !defined (VMIN)
418: #define VMIN VEOF
419: #endif
420:
421: #if !defined (VTIME)
422: #define VTIME VEOL
423: #endif
424:
425: void prep_terminal ()
426: {
427: int tty = fileno (stdin);
428: #if defined (TERMIOS_TTY_DRIVER)
429: struct termios tio;
430: #else
431: struct termio tio;
432: #endif /* !TERMIOS_TTY_DRIVER */
433:
434: #if defined (HAVE_POSIX_SIGNALS)
435: sigset_t set, oset;
436: #else
437: # if defined (HAVE_BSD_SIGNALS)
438: int oldmask;
439: # endif /* HAVE_BSD_SIGNALS */
440: #endif /* !HAVE_POSIX_SIGNALS */
441:
442: if (terminal_prepped)
443: return;
444:
445: /* Try to keep this function from being INTerrupted. We can do it
446: on POSIX and systems with BSD-like signal handling. */
447: #if defined (HAVE_POSIX_SIGNALS)
448: sigemptyset (&set);
449: sigemptyset (&oset);
450: sigaddset (&set, SIGINT);
451: sigprocmask (SIG_BLOCK, &set, &oset);
452: #else /* !HAVE_POSIX_SIGNALS */
453: # if defined (HAVE_BSD_SIGNALS)
454: oldmask = sigblock (sigmask (SIGINT));
455: # endif /* HAVE_BSD_SIGNALS */
456: #endif /* !HAVE_POSIX_SIGNALS */
457:
458: #if defined (TERMIOS_TTY_DRIVER)
459: tcgetattr (tty, &tio);
460: #else
461: ioctl (tty, TCGETA, &tio);
462: #endif /* !TERMIOS_TTY_DRIVER */
463:
464: otio = tio;
465:
466: readline_echoing_p = (tio.c_lflag & ECHO);
467:
468: tio.c_lflag &= ~(ICANON | ECHO);
469:
470: if (otio.c_cc[VEOF] != _POSIX_VDISABLE)
471: eof_char = otio.c_cc[VEOF];
472:
473: #if defined (USE_XON_XOFF)
474: #if defined (IXANY)
475: tio.c_iflag &= ~(IXON | IXOFF | IXANY);
476: #else
477: /* `strict' Posix systems do not define IXANY. */
478: tio.c_iflag &= ~(IXON | IXOFF);
479: #endif /* IXANY */
480: #endif /* USE_XON_XOFF */
481:
482: /* Only turn this off if we are using all 8 bits. */
483: if ((tio.c_cflag & CSIZE) == CS8)
484: tio.c_iflag &= ~(ISTRIP | INPCK);
485:
486: /* Make sure we differentiate between CR and NL on input. */
487: tio.c_iflag &= ~(ICRNL | INLCR);
488:
489: #if !defined (HANDLE_SIGNALS)
490: tio.c_lflag &= ~ISIG;
491: #else
492: tio.c_lflag |= ISIG;
493: #endif
494:
495: tio.c_cc[VMIN] = 1;
496: tio.c_cc[VTIME] = 0;
497:
498: /* Turn off characters that we need on Posix systems with job control,
499: just to be sure. This includes ^Y and ^V. This should not really
500: be necessary. */
501: #if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_JOB_CONTROL)
502:
503: #if defined (VLNEXT)
504: tio.c_cc[VLNEXT] = _POSIX_VDISABLE;
505: #endif
506:
507: #if defined (VDSUSP)
508: tio.c_cc[VDSUSP] = _POSIX_VDISABLE;
509: #endif
510:
511: #endif /* POSIX && JOB_CONTROL */
512:
513: #if defined (TERMIOS_TTY_DRIVER)
514: tcsetattr (tty, TCSADRAIN, &tio);
515: tcflow (tty, TCOON); /* Simulate a ^Q. */
516: #else
517: ioctl (tty, TCSETAW, &tio);
518: ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
519: #endif /* !TERMIOS_TTY_DRIVER */
520:
521: terminal_prepped = 1;
522:
523: #if defined (HAVE_POSIX_SIGNALS)
524: sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
525: #else
526: # if defined (HAVE_BSD_SIGNALS)
527: sigsetmask (oldmask);
528: # endif /* HAVE_BSD_SIGNALS */
529: #endif /* !HAVE_POSIX_SIGNALS */
530: }
531:
532: void deprep_terminal ()
533: {
534: int tty = fileno (stdin);
535:
536: /* Try to keep this function from being INTerrupted. We can do it
537: on POSIX and systems with BSD-like signal handling. */
538: #if defined (HAVE_POSIX_SIGNALS)
539: sigset_t set, oset;
540: #else /* !HAVE_POSIX_SIGNALS */
541: # if defined (HAVE_BSD_SIGNALS)
542: int oldmask;
543: # endif /* HAVE_BSD_SIGNALS */
544: #endif /* !HAVE_POSIX_SIGNALS */
545:
546: if (!terminal_prepped)
547: return;
548:
549: #if defined (HAVE_POSIX_SIGNALS)
550: sigemptyset (&set);
551: sigemptyset (&oset);
552: sigaddset (&set, SIGINT);
553: sigprocmask (SIG_BLOCK, &set, &oset);
554: #else /* !HAVE_POSIX_SIGNALS */
555: # if defined (HAVE_BSD_SIGNALS)
556: oldmask = sigblock (sigmask (SIGINT));
557: # endif /* HAVE_BSD_SIGNALS */
558: #endif /* !HAVE_POSIX_SIGNALS */
559:
560: #if defined (TERMIOS_TTY_DRIVER)
561: tcsetattr (tty, TCSADRAIN, &otio);
562: tcflow (tty, TCOON); /* Simulate a ^Q. */
563: #else /* TERMIOS_TTY_DRIVER */
564: ioctl (tty, TCSETAW, &otio);
565: ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
566: #endif /* !TERMIOS_TTY_DRIVER */
567:
568: terminal_prepped = 0;
569:
570: #if defined (HAVE_POSIX_SIGNALS)
571: sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
572: #else /* !HAVE_POSIX_SIGNALS */
573: # if defined (HAVE_BSD_SIGNALS)
574: sigsetmask (oldmask);
575: # endif /* HAVE_BSD_SIGNALS */
576: #endif /* !HAVE_POSIX_SIGNALS */
577: }
578: #endif /* NEW_TTY_DRIVER */
579:
580: /* If a character is available to be read, then read it
581: and stuff it into IBUFFER. Otherwise, just return. */
582:
583: long pending = -1L;
584:
585: long key_avail (stream)
586: FILE *stream;
587: {
588: int tty = fileno (stream);
589: long chars_avail = pending;
590: int result;
591:
1.9 pazsan 592: if(!terminal_prepped) prep_terminal();
593:
1.1 anton 594: #if defined (FIONREAD)
595: result = ioctl (tty, FIONREAD, &chars_avail);
596: #endif
597:
598: if(chars_avail == -1L)
599: { unsigned char inchar;
600:
601: fcntl(tty, F_SETFL, O_NDELAY);
602: result = read(tty, &inchar, sizeof(char));
603: if(result == sizeof(char))
604: {
605: chars_avail = 1;
606: pending = (long)inchar;
607: }
608: else
609: chars_avail = 0;
610: fcntl(tty, F_SETFL, 0);
611: }
612:
613: return chars_avail;
614: }
615:
616: /* Get a key from the buffer of characters to be read.
617: Return the key in KEY.
618: Result is KEY if there was a key, or 0 if there wasn't. */
619:
620: /* When compiling and running in the `Posix' environment, Ultrix does
621: not restart system calls, so this needs to do it. */
622:
623: unsigned char getkey(stream)
624: FILE *stream;
625: {
626: int result;
627: unsigned char c;
628:
1.9 pazsan 629: if(!terminal_prepped) prep_terminal();
630:
1.1 anton 631: while (pending < 0)
632: {
633: result = read (fileno (stream), &c, sizeof (char));
634:
635: if (result == sizeof (char))
636: return /* (c == 0x7F ? 0x08 :*/ c /*)*/;
637:
638: /* If zero characters are returned, then the file that we are
639: reading from is empty! Return EOF in that case. */
640: if (result == 0)
1.9 pazsan 641: return CTRL('D');
1.1 anton 642:
643: /* If the error that we received was SIGINT, then try again,
644: this is simply an interrupted system call to read ().
645: Otherwise, some error ocurred, also signifying EOF. */
646: if (errno != EINTR)
647: return (EOF);
648: }
649:
650: result = (int) pending;
651: pending = -1L;
652:
653: return result;
654: }
655:
656: #ifdef TEST
657:
658: #include <time.h>
659:
660: int timewait=100000;
661:
662: int main()
663: {
664: unsigned char c;
665:
666: prep_terminal();
667:
668: do
669: {
670: int i=0;
671:
672: while(!key_avail(stdin))
673: {
674: printf("%04d",i);
675: fflush(stdout);
676: {
677: struct timeval timeout;
678: timeout.tv_sec=timewait/1000000;
679: timeout.tv_usec=timewait%1000000;
680: (void)select(0,0,0,0,&timeout);
681: }
682: i++;
683: printf("\b\b\b\b");
684: fflush(stdout);
685: }
686: c = getkey(stdin);
687: printf("%02x,",(int)c);
688: fflush(stdout);
689: } while(c != 0x1B);
690:
691: deprep_terminal();
692: puts("");
693: }
694: #endif
695:
1.10 anton 696:
697: /* signal handling adapted from pfe by Dirk Zoller (Copylefted) - anton */
1.1 anton 698:
699: static void
700: graceful_exit (int sig)
701: {
702: deprep_terminal();
1.10 anton 703: fprintf (stderr, "\n\n%s.\n", strsignal (sig));
1.4 anton 704: exit (0x80|sig);
1.1 anton 705: }
706:
1.4 anton 707: jmp_buf throw_jmp_buf;
708:
709: static void
710: signal_throw(int sig)
711: {
1.10 anton 712: int code;
713: struct {
714: int signal;
715: int throwcode;
716: } *p, throwtable[] = {
717: { SIGINT, -28 },
718: { SIGFPE, -55 },
719: { SIGBUS, -23 },
720: { SIGSEGV, -9 },
1.4 anton 721: };
722: signal(sig,signal_throw);
1.10 anton 723: for (code=-256-sig, p=throwtable; p<throwtable+(sizeof(throwtable)/sizeof(*p)); p++)
724: if (sig == p->signal) {
725: code = p->throwcode;
726: break;
727: }
728: longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */
1.4 anton 729: }
730:
1.5 pazsan 731: static void
732: termprep (int sig)
733: {
1.9 pazsan 734: terminal_prepped=0;
1.5 pazsan 735: signal(sig,termprep);
736: }
737:
1.1 anton 738: void
739: install_signal_handlers (void)
740: {
1.10 anton 741:
742: #if 0
743: /* these signals are handled right by default, no need to handle them;
744: they are listed here just for fun */
745: static short sigs_to_default [] = {
746: #ifdef SIGCHLD
747: SIGCHLD,
748: #endif
749: #ifdef SIGINFO
750: SIGINFO,
751: #endif
752: #ifdef SIGIO
753: SIGIO,
754: #endif
755: #ifdef SIGLOST
756: SIGLOST,
757: #endif
758: #ifdef SIGKILL
759: SIGKILL,
760: #endif
761: #ifdef SIGSTOP
762: SIGSTOP,
763: #endif
764: #ifdef SIGPWR
765: SIGPWR,
766: #endif
767: #ifdef SIGMSG
768: SIGMSG,
769: #endif
770: #ifdef SIGDANGER
771: SIGDANGER,
772: #endif
773: #ifdef SIGMIGRATE
774: SIGMIGRATE,
775: #endif
776: #ifdef SIGPRE
777: SIGPRE,
778: #endif
779: #ifdef SIGVIRT
780: SIGVIRT,
781: #endif
782: #ifdef SIGGRANT
783: SIGGRANT,
784: #endif
785: #ifdef SIGRETRACT
786: SIGRETRACT,
787: #endif
788: #ifdef SIGSOUND
789: SIGSOUND,
790: #endif
791: #ifdef SIGSAK
792: SIGSAK,
793: #endif
794: #ifdef SIGTSTP
795: SIGTSTP,
796: #endif
797: #ifdef SIGTTIN
798: SIGTTIN,
799: #endif
800: #ifdef SIGTTOU
801: SIGTTOU,
802: #endif
803: #ifdef SIGWINCH
804: SIGWINCH,
805: #endif
806: #ifdef SIGSTKFLT
807: SIGSTKFLT,
808: #endif
809: #ifdef SIGUNUSED
810: SIGUNUSED,
811: #endif
812: };
813: #endif
814:
815: static short sigs_to_throw [] = {
816: #ifdef SIGBREAK
817: SIGBREAK,
818: #endif
819: #ifdef SIGINT
820: SIGINT,
821: #endif
822: #ifdef SIGILL
823: SIGILL,
824: #endif
825: #ifdef SIGEMT
826: SIGEMT,
827: #endif
828: #ifdef SIGFPE
829: SIGFPE,
830: #endif
831: #ifdef SIGIOT
832: SIGIOT,
833: #endif
834: #ifdef SIGSEGV
835: SIGSEGV,
836: #endif
837: #ifdef SIGALRM
838: SIGALRM,
839: #endif
840: #ifdef SIGPOLL
841: SIGPOLL,
842: #endif
843: #ifdef SIGPROF
844: SIGPROF,
845: #endif
846: #ifdef SIGBUS
847: SIGBUS,
848: #endif
849: #ifdef SIGSYS
850: SIGSYS,
851: #endif
852: #ifdef SIGTRAP
853: SIGTRAP,
854: #endif
855: #ifdef SIGURG
856: SIGURG,
857: #endif
858: #ifdef SIGUSR1
859: SIGUSR1,
860: #endif
861: #ifdef SIGUSR2
862: SIGUSR2,
863: #endif
864: #ifdef SIGVTALRM
865: SIGVTALRM,
866: #endif
867: #ifdef SIGXFSZ
868: SIGXFSZ,
869: #endif
870: };
871: static short sigs_to_quit [] = {
872: #ifdef SIGHUP
873: SIGHUP,
874: #endif
875: #ifdef SIGQUIT
876: SIGQUIT,
877: #endif
878: #ifdef SIGABRT
879: SIGABRT,
880: #endif
881: #ifdef SIGPIPE
882: SIGPIPE,
883: #endif
884: #ifdef SIGTERM
885: SIGTERM,
886: #endif
887: #ifdef SIGXCPU
888: SIGXCPU,
889: #endif
890: };
891: static short sigs_to_termprep [] = {
892: #ifdef SIGCONT
893: SIGCONT,
894: #endif
895: };
1.1 anton 896: int i;
897:
898: #define DIM(X) (sizeof (X) / sizeof *(X))
1.10 anton 899: /*
1.1 anton 900: for (i = 0; i < DIM (sigs_to_ignore); i++)
1.10 anton 901: signal (sigs_to_ignore [i], SIG_IGN);
902: */
903: for (i = 0; i < DIM (sigs_to_throw); i++)
904: signal (sigs_to_throw [i], signal_throw);
1.1 anton 905: for (i = 0; i < DIM (sigs_to_quit); i++)
906: signal (sigs_to_quit [i], graceful_exit);
1.5 pazsan 907: for (i = 0; i < DIM (sigs_to_termprep); i++)
908: signal (sigs_to_termprep [i], termprep);
1.1 anton 909: }
910: /* end signal handling */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>