rc

[fork] interactive rc shell
git clone https://hhvn.uk/rc
git clone git://hhvn.uk/rc
Log | Files | Refs | README | LICENSE

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 }