Annotation of gforth/engine/signals.c, revision 1.4
1.1 anton 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
1.2 anton 33: /* #include <asm/signal.h> */
34: #include <signal.h>
1.1 anton 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;
1.3 anton 65:
66: switch (sig) {
67: case SIGINT: code=-28; break;
68: case SIGFPE: code=-55; break;
1.1 anton 69: #ifdef SIGBUS
1.3 anton 70: case SIGBUS: code=-23; break;
1.1 anton 71: #endif
1.3 anton 72: case SIGSEGV: code=-9; break;
73: default: code=-256-sig; break;
74: }
75: longjmp(throw_jmp_buf,code); /* !! or use siglongjmp ? */
76: }
77:
78: #ifdef SA_SIGINFO
79: static void fpe_handler(int sig, siginfo_t *info, void *_)
80: /* handler for SIGFPE */
81: {
82: int code;
83:
84: switch(info->si_code) {
85: case FPE_INTDIV: code=-10; break; /* integer divide by zero */
86: case FPE_INTOVF: code=-11; break; /* integer overflow */
87: case FPE_FLTDIV: code=-42; break; /* floating point divide by zero */
88: case FPE_FLTOVF: code=-43; break; /* floating point overflow */
89: case FPE_FLTUND: code=-54; break; /* floating point underflow */
90: case FPE_FLTRES: code=-41; break; /* floating point inexact result */
91: case FPE_FLTINV: /* invalid floating point operation */
92: case FPE_FLTSUB: /* subscript out of range */
93: default: code=-55; break;
94: }
95: longjmp(throw_jmp_buf,code);
96: }
97:
98:
99: #define SPILLAGE 128
100: /* if there's a SIGSEGV within SPILLAGE bytes of some stack, we assume
101: that this stack has over/underflowed */
102:
103: #define JUSTUNDER(addr1,addr2) (((UCell)((addr2)-1-(addr1)))<SPILLAGE)
104: /* true is addr1 is just under addr2 */
105:
106: #define JUSTOVER(addr1,addr2) (((UCell)((addr1)-(addr2)))<SPILLAGE)
107:
108: #define NEXTPAGE(addr) ((Address)((((UCell)(addr)-1)&-pagesize)+pagesize))
109:
110: static void segv_handler(int sig, siginfo_t *info, void *_)
111: {
112: int code=-9;
113: Address addr=info->si_addr;
114: ImageHeader *h=gforth_header;
115:
116: if (JUSTUNDER(addr, h->data_stack_base))
117: code=-3;
118: else if (JUSTOVER(addr, NEXTPAGE(h->data_stack_base+h->data_stack_size)))
119: code=-4;
120: else if (JUSTUNDER(addr, h->return_stack_base))
121: code=-5;
122: else if (JUSTOVER(addr, NEXTPAGE(h->return_stack_base+h->return_stack_size)))
123: code=-6;
124: else if (JUSTUNDER(addr, h->fp_stack_base))
125: code=-44;
126: else if (JUSTOVER(addr, NEXTPAGE(h->fp_stack_base+h->fp_stack_size)))
127: code=-45;
128: longjmp(throw_jmp_buf,code);
1.1 anton 129: }
130:
1.3 anton 131: #endif /* defined(SA_SIGINFO) */
132:
1.1 anton 133: #ifdef SIGCONT
134: static void termprep (int sig)
135: {
136: signal(sig,termprep);
137: terminal_prepped=0;
138: }
139: #endif
140:
141: void get_winsize()
142: {
143: #ifdef TIOCGWINSZ
144: struct winsize size;
145:
146: if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) {
147: rows = size.ws_row;
148: cols = size.ws_col;
149: }
150: #else
151: char *s;
152: if ((s=getenv("LINES"))) {
153: rows=atoi(s);
154: if (rows==0)
155: rows=DEFAULTROWS;
156: }
157: if ((s=getenv("COLUMNS"))) {
158: rows=atoi(s);
159: if (rows==0)
160: cols=DEFAULTCOLS;
161: }
162: #endif
163: }
164:
165: #ifdef SIGWINCH
166: static void change_winsize(int sig)
167: {
168: signal(sig,change_winsize);
169: #ifdef TIOCGWINSZ
170: get_winsize();
171: #endif
172: }
173: #endif
174:
1.3 anton 175:
176: #ifdef SA_SIGINFO
177: void install_signal_handler(int sig, void (*handler)(int, siginfo_t *, void *))
178: /* installs three-argument signal handler for sig */
1.2 anton 179: {
180: struct sigaction action;
181:
1.3 anton 182: action.sa_sigaction=handler;
1.2 anton 183: sigemptyset(&action.sa_mask);
1.3 anton 184: action.sa_flags=SA_RESTART|SA_SIGINFO; /* pass siginfo */
185: sigaction(sig, &action, NULL);
186: }
1.2 anton 187: #endif
188:
189: void install_signal_handlers(void)
1.1 anton 190: {
191:
192: #if 0
193: /* these signals are handled right by default, no need to handle them;
194: they are listed here just for fun */
195: static short sigs_to_default [] = {
196: #ifdef SIGCHLD
197: SIGCHLD,
198: #endif
199: #ifdef SIGINFO
200: SIGINFO,
201: #endif
202: #ifdef SIGIO
203: SIGIO,
204: #endif
205: #ifdef SIGLOST
206: SIGLOST,
207: #endif
208: #ifdef SIGKILL
209: SIGKILL,
210: #endif
211: #ifdef SIGSTOP
212: SIGSTOP,
213: #endif
214: #ifdef SIGPWR
215: SIGPWR,
216: #endif
217: #ifdef SIGMSG
218: SIGMSG,
219: #endif
220: #ifdef SIGDANGER
221: SIGDANGER,
222: #endif
223: #ifdef SIGMIGRATE
224: SIGMIGRATE,
225: #endif
226: #ifdef SIGPRE
227: SIGPRE,
228: #endif
229: #ifdef SIGVIRT
230: SIGVIRT,
231: #endif
232: #ifdef SIGGRANT
233: SIGGRANT,
234: #endif
235: #ifdef SIGRETRACT
236: SIGRETRACT,
237: #endif
238: #ifdef SIGSOUND
239: SIGSOUND,
240: #endif
241: #ifdef SIGSAK
242: SIGSAK,
243: #endif
244: #ifdef SIGTSTP
245: SIGTSTP,
246: #endif
247: #ifdef SIGTTIN
248: SIGTTIN,
249: #endif
250: #ifdef SIGTTOU
251: SIGTTOU,
252: #endif
253: #ifdef SIGSTKFLT
254: SIGSTKFLT,
255: #endif
256: #ifdef SIGUNUSED
257: SIGUNUSED,
258: #endif
259: };
260: #endif
261:
262: static short sigs_to_throw [] = {
263: #ifdef SIGBREAK
264: SIGBREAK,
265: #endif
266: #ifdef SIGINT
267: SIGINT,
268: #endif
269: #ifdef SIGILL
270: SIGILL,
271: #endif
272: #ifdef SIGEMT
273: SIGEMT,
274: #endif
275: #ifdef SIGFPE
276: SIGFPE,
277: #endif
278: #ifdef SIGIOT
279: SIGIOT,
280: #endif
281: #ifdef SIGSEGV
282: SIGSEGV,
283: #endif
284: #ifdef SIGALRM
285: SIGALRM,
286: #endif
287: #ifdef SIGPIPE
288: SIGPIPE,
289: #endif
290: #ifdef SIGPOLL
291: SIGPOLL,
292: #endif
293: #ifdef SIGPROF
294: SIGPROF,
295: #endif
296: #ifdef SIGBUS
297: SIGBUS,
298: #endif
299: #ifdef SIGSYS
300: SIGSYS,
301: #endif
302: #ifdef SIGTRAP
303: SIGTRAP,
304: #endif
305: #ifdef SIGURG
306: SIGURG,
307: #endif
308: #ifdef SIGUSR1
309: SIGUSR1,
310: #endif
311: #ifdef SIGUSR2
312: SIGUSR2,
313: #endif
314: #ifdef SIGVTALRM
315: SIGVTALRM,
316: #endif
317: #ifdef SIGXFSZ
318: SIGXFSZ,
319: #endif
320: };
321: static short sigs_to_quit [] = {
1.4 ! pazsan 322: #ifdef SIGQUIT
! 323: SIGQUIT,
! 324: #endif
1.1 anton 325: #ifdef SIGHUP
326: SIGHUP,
327: #endif
328: #ifdef SIGABRT
329: SIGABRT,
330: #endif
331: #ifdef SIGTERM
332: SIGTERM,
333: #endif
334: #ifdef SIGXCPU
335: SIGXCPU,
336: #endif
337: };
338: int i;
1.2 anton 339: void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw;
1.1 anton 340:
341: #define DIM(X) (sizeof (X) / sizeof *(X))
342: /*
343: for (i = 0; i < DIM (sigs_to_ignore); i++)
344: signal (sigs_to_ignore [i], SIG_IGN);
345: */
346: for (i = 0; i < DIM (sigs_to_throw); i++)
1.3 anton 347: signal(sigs_to_throw[i], throw_handler);
1.1 anton 348: for (i = 0; i < DIM (sigs_to_quit); i++)
349: signal (sigs_to_quit [i], graceful_exit);
1.3 anton 350: #ifdef SA_SIGINFO
351: install_signal_handler(SIGFPE, fpe_handler);
352: install_signal_handler(SIGSEGV, segv_handler);
353: #endif
1.1 anton 354: #ifdef SIGCONT
355: signal (SIGCONT, termprep);
356: #endif
357: #ifdef SIGWINCH
358: signal (SIGWINCH, change_winsize);
359: #endif
360: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>