/* signal handling Copyright (C) 1995,1996,1997,1998 Free Software Foundation, Inc. This file is part of Gforth. Gforth is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define _GNU_SOURCE #include #include #include #include #if !defined(apollo) && !defined(MSDOS) #include #endif /* #include */ #include #include "config.h" #include "forth.h" #include "io.h" #define DEFAULTCOLS 80 #if defined(MSDOS) || defined (_WIN32) #define DEFAULTROWS 25 #else #define DEFAULTROWS 24 #endif UCell cols=DEFAULTCOLS; UCell rows=DEFAULTROWS; static void graceful_exit (int sig) { deprep_terminal(); fprintf (stderr, "\n\n%s.\n", strsignal (sig)); exit (0x80|sig); } jmp_buf throw_jmp_buf; static void signal_throw(int sig) { int code; struct { int signal; int throwcode; } *p, throwtable[] = { { SIGINT, -28 }, { SIGFPE, -55 }, #ifdef SIGBUS { SIGBUS, -23 }, #endif { SIGSEGV, -9 }, }; signal(sig,signal_throw); for (code=-256-sig, p=throwtable; psignal) { code = p->throwcode; break; } longjmp(throw_jmp_buf,code); /* or use siglongjmp ? */ } #ifdef SIGCONT static void termprep (int sig) { signal(sig,termprep); terminal_prepped=0; } #endif void get_winsize() { #ifdef TIOCGWINSZ struct winsize size; if (ioctl (1, TIOCGWINSZ, (char *) &size) >= 0) { rows = size.ws_row; cols = size.ws_col; } #else char *s; if ((s=getenv("LINES"))) { rows=atoi(s); if (rows==0) rows=DEFAULTROWS; } if ((s=getenv("COLUMNS"))) { rows=atoi(s); if (rows==0) cols=DEFAULTCOLS; } #endif } #ifdef SIGWINCH static void change_winsize(int sig) { signal(sig,change_winsize); #ifdef TIOCGWINSZ get_winsize(); #endif } #endif void install_signal_handler(int sig, void (*simple_handler)(), void (*complex_handler)()) /* installs signal handler for sig. If the system has the necessary support, complex_handler will be invoked upon receipt of a signal, otherwise simple_handler. */ { #ifdef SA_SIGINFO struct sigaction action; action.sa_handler=simple_handler; action.sa_sigaction=complex_handler; sigemptyset(&action.sa_mask); action.sa_flags=SA_SIGINFO; /* use complex_handler */ sigaction(sig, action, NULL); #else /* ANSI C */ signal(sig,simple_handler); #endif } void install_signal_handlers(void) { #if 0 /* these signals are handled right by default, no need to handle them; they are listed here just for fun */ static short sigs_to_default [] = { #ifdef SIGCHLD SIGCHLD, #endif #ifdef SIGINFO SIGINFO, #endif #ifdef SIGIO SIGIO, #endif #ifdef SIGLOST SIGLOST, #endif #ifdef SIGKILL SIGKILL, #endif #ifdef SIGSTOP SIGSTOP, #endif #ifdef SIGPWR SIGPWR, #endif #ifdef SIGMSG SIGMSG, #endif #ifdef SIGDANGER SIGDANGER, #endif #ifdef SIGMIGRATE SIGMIGRATE, #endif #ifdef SIGPRE SIGPRE, #endif #ifdef SIGVIRT SIGVIRT, #endif #ifdef SIGGRANT SIGGRANT, #endif #ifdef SIGRETRACT SIGRETRACT, #endif #ifdef SIGSOUND SIGSOUND, #endif #ifdef SIGSAK SIGSAK, #endif #ifdef SIGTSTP SIGTSTP, #endif #ifdef SIGTTIN SIGTTIN, #endif #ifdef SIGTTOU SIGTTOU, #endif #ifdef SIGSTKFLT SIGSTKFLT, #endif #ifdef SIGUNUSED SIGUNUSED, #endif }; #endif static short sigs_to_throw [] = { #ifdef SIGBREAK SIGBREAK, #endif #ifdef SIGINT SIGINT, #endif #ifdef SIGILL SIGILL, #endif #ifdef SIGEMT SIGEMT, #endif #ifdef SIGFPE SIGFPE, #endif #ifdef SIGIOT SIGIOT, #endif #ifdef SIGSEGV SIGSEGV, #endif #ifdef SIGALRM SIGALRM, #endif #ifdef SIGPIPE SIGPIPE, #endif #ifdef SIGPOLL SIGPOLL, #endif #ifdef SIGPROF SIGPROF, #endif #ifdef SIGBUS SIGBUS, #endif #ifdef SIGSYS SIGSYS, #endif #ifdef SIGTRAP SIGTRAP, #endif #ifdef SIGURG SIGURG, #endif #ifdef SIGUSR1 SIGUSR1, #endif #ifdef SIGUSR2 SIGUSR2, #endif #ifdef SIGVTALRM SIGVTALRM, #endif #ifdef SIGXFSZ SIGXFSZ, #endif }; static short sigs_to_quit [] = { #ifdef SIGHUP SIGHUP, #endif #ifdef SIGQUIT SIGQUIT, #endif #ifdef SIGABRT SIGABRT, #endif #ifdef SIGTERM SIGTERM, #endif #ifdef SIGXCPU SIGXCPU, #endif }; int i; void (*throw_handler)() = die_on_signal ? graceful_exit : signal_throw; #define DIM(X) (sizeof (X) / sizeof *(X)) /* for (i = 0; i < DIM (sigs_to_ignore); i++) signal (sigs_to_ignore [i], SIG_IGN); */ for (i = 0; i < DIM (sigs_to_throw); i++) install_signal_handler(sigs_to_throw [i], throw_handler, throw_handler); for (i = 0; i < DIM (sigs_to_quit); i++) signal (sigs_to_quit [i], graceful_exit); #ifdef SIGCONT signal (SIGCONT, termprep); #endif #ifdef SIGWINCH signal (SIGWINCH, change_winsize); #endif }