signal.c (2134B)
1 /* signal.c: a Hugh-approved signal handler. */ 2 3 #include "rc.h" 4 5 #include <signal.h> 6 #include <setjmp.h> 7 8 #include "sigmsgs.h" 9 #include "jbwrap.h" 10 11 #if HAVE_SIGACTION 12 void (*sys_signal(int signum, void (*handler)(int)))(int) { 13 struct sigaction new, old; 14 15 new.sa_handler = handler; 16 new.sa_flags = 0; /* clear SA_RESTART */ 17 sigfillset(&new.sa_mask); 18 if (sigaction(signum, &new, &old) == 0) 19 return old.sa_handler; 20 return SIG_DFL; 21 } 22 #else 23 void (*sys_signal(int signum, void (*handler)(int)))(int) { 24 return signal(signum, handler); 25 } 26 #endif 27 28 void (*sighandlers[NUMOFSIGNALS])(int); 29 30 static volatile sig_atomic_t sigcount, caught[NUMOFSIGNALS]; 31 32 extern void catcher(int s) { 33 if (caught[s] == 0) { 34 sigcount++; 35 caught[s] = 1; 36 } 37 sys_signal(s, catcher); 38 39 #if HAVE_RESTARTABLE_SYSCALLS 40 if (slow) { 41 siglongjmp(slowbuf.j, s); 42 } 43 #endif 44 } 45 46 extern void sigchk() { 47 void (*h)(int); 48 int s, i; 49 50 if (sigcount == 0) 51 return; /* ho hum; life as usual */ 52 if (forked) 53 exit(1); /* exit unconditionally on a signal in a child process */ 54 for (i = 0, s = -1; i < NUMOFSIGNALS; i++) 55 if (caught[i] != 0) { 56 s = i; 57 --sigcount; 58 caught[s] = 0; 59 break; 60 } 61 if (s == -1) 62 panic("all-zero sig vector with nonzero sigcount"); 63 if ((h = sighandlers[s]) == SIG_DFL) 64 panic("caught signal set to SIG_DFL"); 65 if (h == SIG_IGN) 66 panic("caught signal set to SIG_IGN"); 67 (*h)(s); 68 } 69 70 extern void (*rc_signal(int s, void (*h)(int)))(int) { 71 void (*old)(int); 72 sigchk(); 73 old = sighandlers[s]; 74 sighandlers[s] = h; 75 if (h == SIG_DFL || h == SIG_IGN) 76 sys_signal(s, h); 77 else 78 sys_signal(s, catcher); 79 return old; 80 } 81 82 extern void initsignal() { 83 void (*h)(int); 84 int i; 85 86 /* Ensure that SIGCHLD is not SIG_IGN. Solaris's rshd does this. :-( */ 87 h = sys_signal(SIGCHLD, SIG_IGN); 88 if (h != SIG_IGN && h != SIG_ERR) 89 sys_signal(SIGCHLD, h); 90 else 91 sys_signal(SIGCHLD, SIG_DFL); 92 93 for (i = 1; i < NUMOFSIGNALS; i++) { 94 #ifdef SIGKILL 95 if (i == SIGKILL) continue; 96 #endif 97 #ifdef SIGSTOP 98 if (i == SIGSTOP) continue; 99 #endif 100 h = sys_signal(i, SIG_IGN); 101 if (h != SIG_IGN && h != SIG_ERR) 102 sys_signal(i, h); 103 sighandlers[i] = h; 104 } 105 }