diff options
| author | Byron Rakitzis <byron@archone.tamu.edu> | 1992-05-27 00:00:01 +0100 |
|---|---|---|
| committer | Toby Goodwin <toby@paccrat.org> | 2015-05-16 21:22:56 +0100 |
| commit | 26bb34cf036027dfa22dfae8d8fc2f6bfd6acb75 (patch) | |
| tree | 589705b2492ce4681760846d9ca45600f0af298d /signal.c | |
release: rc-1.4
Diffstat (limited to 'signal.c')
| -rw-r--r-- | signal.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/signal.c b/signal.c new file mode 100644 index 0000000..645fb36 --- /dev/null +++ b/signal.c @@ -0,0 +1,75 @@ +/* signal.c: a Hugh-approved signal handler. */ + +#include <signal.h> +#include <setjmp.h> +#include "rc.h" +#include "sigmsgs.h" +#include "jbwrap.h" + +Jbwrap slowbuf; +volatile SIG_ATOMIC_T slow, interrupt_happened; +void (*sighandlers[NUMOFSIGNALS])(int); + +static volatile SIG_ATOMIC_T sigcount, caught[NUMOFSIGNALS]; + +extern void catcher(int s) { + if (forked) + exit(1); /* exit unconditionally on a signal in a child process */ + if (caught[s] == 0) { + sigcount++; + caught[s] = 1; + } + signal(s, catcher); + interrupt_happened = TRUE; +#ifndef SVSIGS + if (slow) + longjmp(slowbuf.j, 1); +#endif +} + +extern void sigchk() { + void (*h)(int); + int s, i; + if (sigcount == 0) + return; /* ho hum; life as usual */ + if (forked) + exit(1); /* exit unconditionally on a signal in a child process */ + for (i = 0, s = -1; i < NUMOFSIGNALS; i++) + if (caught[i] != 0) { + s = i; + --sigcount; + caught[s] = 0; + break; + } + if (s == -1) + panic("all-zero sig vector with nonzero sigcount"); + if ((h = sighandlers[s]) == SIG_DFL) + panic("caught signal set to SIG_DFL"); + if (h == SIG_IGN) + panic("caught signal set to SIG_IGN"); + (*h)(s); +} + +extern void (*rc_signal(int s, void (*h)(int)))(int) { + void (*old)(int); + SIGCHK; + old = sighandlers[s]; + if (h == SIG_DFL || h == SIG_IGN) { + signal(s, h); + sighandlers[s] = h; + } else { + sighandlers[s] = h; + signal(s, catcher); + } + return old; +} + +extern void initsignal() { + void (*h)(int); + int i; + for (i = 1; i < NUMOFSIGNALS; i++) { + if ((h = signal(i, SIG_DFL)) != SIG_DFL) + signal(i, h); + sighandlers[i] = h; + } +} |