1: /* signal handling
2:
3: Copyright (C) 1995,1996,1997,1998 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: */
22:
23:
24: #define _GNU_SOURCE
25:
26: #include <stdio.h>
27: #include <setjmp.h>
28: #include <string.h>
29: #include <stdlib.h>
30: #if !defined(apollo) && !defined(MSDOS)
31: #include <sys/ioctl.h>
32: #endif
33: /* #include <asm/signal.h> */
34: #include <signal.h>
35: #include "config.h"
36: #include "forth.h"
37: #include "io.h"
38:
39:
40: #define DEFAULTCOLS 80
41: #if defined(MSDOS) || defined (_WIN32)
42: #define DEFAULTROWS 25
43: #else
44: #define DEFAULTROWS 24
45: #endif
46:
47: UCell cols=DEFAULTCOLS;
48: UCell rows=DEFAULTROWS;
49:
50:
51: static void
52: graceful_exit (int sig)
53: {
54: deprep_terminal();
55: fprintf (stderr, "\n\n%s.\n", strsignal (sig));
56: exit (0x80|sig);
57: }
58:
59: jmp_buf throw_jmp_buf;
60:
61: static void
62: signal_throw(int sig)
63: {
64: int code;
65: struct {
66: int signal;
67: int throwcode;
68: } *p, throwtable[] = {
69: { SIGINT, -28 },
70: { SIGFPE, -55 },
71: #ifdef SIGBUS
72: { SIGBUS, -23 },
73: #endif
74: { SIGSEGV, -9 },
75: };
76: signal(sig,signal_throw);
77: for (code=-256-sig, p=throwtable; p<throwtable+(sizeof(throwtable)/sizeof(*p)); p++)
78: if (sig == p->signal) {
79: code = p->throwcode;
80: break;
81: }
82: longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */
83: }
84:
85: #ifdef SIGCONT
86: static void termprep (int sig)
87: {
88: signal(sig,termprep);
89: terminal_prepped=0;
90: }
91: #endif
92:
93: void get_winsize()
94: {
95: #ifdef TIOCGWINSZ
96: struct winsize size;
97:
98: if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {
99: rows = size.ws_row;
100: cols = size.ws_col;
101: }
102: #else
103: char *s;
104: if ((s=getenv("LINES"))) {
105: rows=atoi(s);
106: if (rows==0)
107: rows=DEFAULTROWS;
108: }
109: if ((s=getenv("COLUMNS"))) {
110: rows=atoi(s);
111: if (rows==0)
112: cols=DEFAULTCOLS;
113: }
114: #endif
115: }
116:
117: #ifdef SIGWINCH
118: static void change_winsize(int sig)
119: {
120: signal(sig,change_winsize);
121: #ifdef TIOCGWINSZ
122: get_winsize();
123: #endif
124: }
125: #endif
126:
127: void install_signal_handler(int sig, void (*simple_handler)(), void (*complex_handler)())
128: /* installs signal handler for sig. If the system has the
129: necessary support, complex_handler will be invoked upon
130: receipt of a signal, otherwise simple_handler. */
131: {
132: #ifdef SA_SIGINFO
133: struct sigaction action;
134:
135: action.sa_handler=simple_handler;
136: action.sa_sigaction=complex_handler;
137: sigemptyset(&action.sa_mask);
138: action.sa_flags=SA_SIGINFO; /* use complex_handler */
139: sigaction(sig, action, NULL);
140: #else
141: /* ANSI C */
142: signal(sig,simple_handler);
143: #endif
144: }
145:
146: void install_signal_handlers(void)
147: {
148:
149: #if 0
150: /* these signals are handled right by default, no need to handle them;
151: they are listed here just for fun */
152: static short sigs_to_default [] = {
153: #ifdef SIGCHLD
154: SIGCHLD,
155: #endif
156: #ifdef SIGINFO
157: SIGINFO,
158: #endif
159: #ifdef SIGIO
160: SIGIO,
161: #endif
162: #ifdef SIGLOST
163: SIGLOST,
164: #endif
165: #ifdef SIGKILL
166: SIGKILL,
167: #endif
168: #ifdef SIGSTOP
169: SIGSTOP,
170: #endif
171: #ifdef SIGPWR
172: SIGPWR,
173: #endif
174: #ifdef SIGMSG
175: SIGMSG,
176: #endif
177: #ifdef SIGDANGER
178: SIGDANGER,
179: #endif
180: #ifdef SIGMIGRATE
181: SIGMIGRATE,
182: #endif
183: #ifdef SIGPRE
184: SIGPRE,
185: #endif
186: #ifdef SIGVIRT
187: SIGVIRT,
188: #endif
189: #ifdef SIGGRANT
190: SIGGRANT,
191: #endif
192: #ifdef SIGRETRACT
193: SIGRETRACT,
194: #endif
195: #ifdef SIGSOUND
196: SIGSOUND,
197: #endif
198: #ifdef SIGSAK
199: SIGSAK,
200: #endif
201: #ifdef SIGTSTP
202: SIGTSTP,
203: #endif
204: #ifdef SIGTTIN
205: SIGTTIN,
206: #endif
207: #ifdef SIGTTOU
208: SIGTTOU,
209: #endif
210: #ifdef SIGSTKFLT
211: SIGSTKFLT,
212: #endif
213: #ifdef SIGUNUSED
214: SIGUNUSED,
215: #endif
216: };
217: #endif
218:
219: static short sigs_to_throw [] = {
220: #ifdef SIGBREAK
221: SIGBREAK,
222: #endif
223: #ifdef SIGINT
224: SIGINT,
225: #endif
226: #ifdef SIGILL
227: SIGILL,
228: #endif
229: #ifdef SIGEMT
230: SIGEMT,
231: #endif
232: #ifdef SIGFPE
233: SIGFPE,
234: #endif
235: #ifdef SIGIOT
236: SIGIOT,
237: #endif
238: #ifdef SIGSEGV
239: SIGSEGV,
240: #endif
241: #ifdef SIGALRM
242: SIGALRM,
243: #endif
244: #ifdef SIGPIPE
245: SIGPIPE,
246: #endif
247: #ifdef SIGPOLL
248: SIGPOLL,
249: #endif
250: #ifdef SIGPROF
251: SIGPROF,
252: #endif
253: #ifdef SIGBUS
254: SIGBUS,
255: #endif
256: #ifdef SIGSYS
257: SIGSYS,
258: #endif
259: #ifdef SIGTRAP
260: SIGTRAP,
261: #endif
262: #ifdef SIGURG
263: SIGURG,
264: #endif
265: #ifdef SIGUSR1
266: SIGUSR1,
267: #endif
268: #ifdef SIGUSR2
269: SIGUSR2,
270: #endif
271: #ifdef SIGVTALRM
272: SIGVTALRM,
273: #endif
274: #ifdef SIGXFSZ
275: SIGXFSZ,
276: #endif
277: };
278: static short sigs_to_quit [] = {
279: #ifdef SIGHUP
280: SIGHUP,
281: #endif
282: #ifdef SIGQUIT
283: SIGQUIT,
284: #endif
285: #ifdef SIGABRT
286: SIGABRT,
287: #endif
288: #ifdef SIGTERM
289: SIGTERM,
290: #endif
291: #ifdef SIGXCPU
292: SIGXCPU,
293: #endif
294: };
295: int i;
296: void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
297:
298: #define DIM(X) (sizeof (X) / sizeof *(X))
299: /*
300: for (i = 0; i < DIM (sigs_to_ignore); i++)
301: signal (sigs_to_ignore [i], SIG_IGN);
302: */
303: for (i = 0; i < DIM (sigs_to_throw); i++)
304: install_signal_handler(sigs_to_throw [i], throw_handler, throw_handler);
305: for (i = 0; i < DIM (sigs_to_quit); i++)
306: signal (sigs_to_quit [i], graceful_exit);
307: #ifdef SIGCONT
308: signal (SIGCONT, termprep);
309: #endif
310: #ifdef SIGWINCH
311: signal (SIGWINCH, change_winsize);
312: #endif
313: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>