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