/* signals.c -- Copyright 1988, 1992, 1995 Liam R. E. Quin. * All Rights Reserved. * This code is NOT in the public domain. * See the file COPYRIGHT for full details. */ /* $Id: signals.c,v 1.4 1996/08/14 17:01:50 lee Exp $ * Simple signal handling routines. * * PORTING NOTES: * if there are no errors compiling this file, but signals don't work -- * e.g. interrupting lqaddfile just stops it with no message, or doesn't * stop it at all, see test/signal.c for ideas. * * If this file does not compile, try * man 3 sigaction * or, if you don't have online man-pages, * grep sigaction /usr/lib/ll* /usr/lib/lint/ll* * might work (it might produce binary garbage, though), or * nm /lib/libc.a | grep sigaction * In any case, if you find sigaction, leave HAVE_SIGACTION defined in * h/globals.h. * * If you don't find sigaction, you can try to look for sigvec in the same way. * If you have sigvec but not sigaction, you want in globals.h * (but replace the @-signs with *-signs!): * #ifndef HAVE_SIGACTION * /@ #define HAVE_SIGACTION Not got that one @@/ * #endif * #ifndef HaVE_SIGVEC * # define HAVE_SIGVEC /@ yes, got that one @@/ * #endif * * If you are on V7 Unix, an old System V, or 4.1 BSD (!?), you don't have * either of these, and must comment out both the HAVE_SIGACTION and the * HAVE_SIGVEC lines. Sorry. * * If you are on minix, you can implement your own sigaction() :-) * * Marc Rochkind and Richard Stevens have both written books about * Advanced Unix Programming that cover some of this topic. See them both, * as Marc Rochkind's book is out of date and Richard Stevens' only really * covers POSIX and SunOS 4.1. * * In short, V7 Unix signals and old SysV signals cause system calls to be * interrupted. In this case, we warn the user that the index might * be broken, and then exit. One day I might make read, write, etc, calls * in liblqtext check for EINTR, in which case we can handle these signals. * * BSD Signals don't interrupt system calls, or restarts them when it does * In this case we have no problem. * * Newer System V signals are like the BSD ones only incompatible. * Again, we can handle them. * */ #include "globals.h" #include "emalloc.h" #include "error.h" #include #include /* just in case */ #include #include "lqutil.h" #undef SIGFUNCUSED /* declare SIGTYPE: (see port.h for the definition of SIGTYPEDEF) */ SIGTYPEDEF; static int SignalTable[] = { /* (rather short) list of signals to catch */ SIGINT, 0 }; void lqSetSignals(theSignalHandler) SIGTYPE theSignalHandler; { static SIGTYPE SafeSignal(); int i; for (i = 0; SignalTable[i] > 0; i++) { if (SafeSignal(SignalTable[i], SIG_IGN) != (SIGTYPE) SIG_IGN) { SafeSignal(SignalTable[i], theSignalHandler); } } } #ifdef HAVE_SIGACTION static SIGTYPE SafeSignal(Signal, Handler) int Signal; SIGTYPE Handler; { struct sigaction act, oldact; act.sa_handler = Handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; # ifdef SA_INTERRUPT if (Signal == SIGALRM) { act.sa_flags |= SA_INTERRUPT; /* old SunOS (pre Solaris 2.0?) */ } # endif # ifdef SA_RESTART if (Signal != SIGALRM) { act.sa_flags |= SA_RESTART; /* SysVR4, 4.3+BSD */ } #endif if (sigaction(Signal, &act, &oldact) < 0) { #ifdef HAVE_SIGLIST extern char *sys_siglist[]; Error(E_FATAL|E_SYS, "Signal setup for sig%d [%s] failed in sigaction()", Signal, (Signal < NSIG && sys_siglist[Signal]) ? sys_siglist[Signal] : "unknown" ); #else Error(E_FATAL|E_SYS, "Signal setup for sig%d failed in sigaction()", Signal ); #endif } return oldact.sa_handler; } # define SIGFUNCUSED "sigaction" #endif /* HAVE_SIGACTION */ #ifndef SIGFUNCUSED # ifdef HAVE_SIGVEC static SIGTYPE SafeSignal(Signal, Handler) int Signal; SIGTYPE Handler; { extern int sigvec(/* sig, vec[], ovec[] */); struct sigvec act, oldact; act.sv_handler = Handler; act.sv_mask = 0; act.sv_flags = 0; # ifdef SA_INTERRUPT if (Signal == SIGALRM) { act.sv_flags |= SV_INTERRUPT; /* old SunOS (pre Solaris 2.0?) */ } # endif # ifdef SA_RESTART if (Signal != SIGALRM) { act.sv_flags |= SV_RESTART; /* SysVR4, 4.3+BSD */ } #endif if (sigvec(Signal, &act, &oldact) < 0) { #ifdef HAVE_SIGLIST extern char *sys_siglist[]; Error(E_FATAL|E_SYS, "Signal setup for sig%d [%s] failed in sigvec()", Signal, (Signal < NSIG && sys_siglist[Signal]) ? sys_siglist[Signal] : "unknown" ); #else Error(E_FATAL|E_SYS, "Signal setup for sig%d failed in sigvec()", Signal ); #endif } return oldact.sv_handler; # define SIGFUNCUSED "sigvec" } #endif /* HAVE_SIGVEC */ #endif /* SIGFUNCUSED */ #ifndef SIGFUNCUSED static SIGTYPE SafeSignal(Signal, Handler) int Signal; SIGTYPE Handler; { SIGTYPE OldVal; if ((OldVal = signal(Signal, Handler)) == (SIGTYPE) -1) { #ifdef HAVE_SIGLIST extern char *sys_siglist[]; Error(E_FATAL|E_SYS, "Signal setup for sig%d [%s] failed in sigvec()", Signal, (Signal < NSIG && sys_siglist[Signal]) ? sys_siglist[Signal] : "unknown" ); #else Error(E_FATAL|E_SYS, "Signal setup for sig%d failed in sigvec()", Signal ); #endif } return OldVal; # define SIGFUNCUSED "unreliable-signal" } #endif /* SIGFUNCUSED */ static char * SignalTypeUsed() { return SIGFUNCUSED; }