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