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