xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/signal.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "lib.h"
2 #include "sys9.h"
3 #include <signal.h>
4 #include <errno.h>
5 #include <string.h>
6 
7 extern sigset_t	_psigblocked;
8 
9 static struct {
10 	char	*msg;	/* just check prefix */
11 	int	num;
12 } sigtab[] = {
13 	{"hangup",				SIGHUP},
14 	{"interrupt",				SIGINT},
15 	{"quit",				SIGQUIT},
16 	{"alarm",				SIGALRM},
17 	{"sys: trap: illegal instruction",	SIGILL},
18 	{"sys: trap: reserved instruction",	SIGILL},
19 	{"sys: trap: reserved",			SIGILL},
20 	{"sys: trap: arithmetic overflow",	SIGFPE},
21 	{"abort",				SIGABRT},
22 	{"sys: fp:",				SIGFPE},
23 	{"exit",				SIGKILL},
24 	{"die",					SIGKILL},
25 	{"kill",				SIGKILL},
26 	{"sys: trap: bus error",		SIGSEGV},
27 	{"sys: trap: address error",		SIGSEGV},
28 	{"sys: trap: TLB",			SIGSEGV},
29 	{"sys: write on closed pipe",		SIGPIPE},
30 	{"alarm",				SIGALRM},
31 	{"term",				SIGTERM},
32 	{"usr1",				SIGUSR1},
33 	{"usr2",				SIGUSR2},
34 };
35 #define NSIGTAB ((sizeof sigtab)/(sizeof (sigtab[0])))
36 
37 void	(*_sighdlr[MAXSIG+1])(int, char*, Ureg*); /* 0 initialized: SIG_DFL */
38 
39 void
40 (*signal(int sig, void (*func)(int, char*, Ureg*)))(int, char*, Ureg*)
41 {
42 	void(*oldf)(int, char*, Ureg*);
43 
44 	if(sig <= 0 || sig > MAXSIG){
45 		errno = EINVAL;
46 		return SIG_ERR;
47 	}
48 	oldf = _sighdlr[sig];
49 	if(sig == SIGKILL)
50 		return oldf;	/* can't catch or ignore SIGKILL */
51 	_sighdlr[sig] = func;
52 	return oldf;
53 }
54 
55 /*
56  * BUG: improper handling of process signal mask
57  */
58 int
59 sigaction(int sig, struct sigaction *act, struct sigaction *oact)
60 {
61 	if(sig <= 0 || sig > MAXSIG || sig == SIGKILL){
62 		errno = EINVAL;
63 		return -1;
64 	}
65 	if(oact){
66 		oact->sa_handler = _sighdlr[sig];
67 		oact->sa_mask = _psigblocked;
68 		oact->sa_flags = 0;
69 	}
70 	if(act){
71 		_sighdlr[sig] = act->sa_handler;
72 	}
73 	return 0;
74 }
75 
76 /* this is registered in _envsetup */
77 int
78 _notehandler(Ureg *u, char *msg)
79 {
80 	int i;
81 	void(*f)(int, char*, Ureg*);
82 	extern void _doatexits(void);	/* in stdio/exit.c */
83 
84 	if(_finishing)
85 		_finish(0, 0);
86 	for(i = 0; i<NSIGTAB; i++){
87 		if(strncmp(msg, sigtab[i].msg, strlen(sigtab[i].msg)) == 0){
88 			f = _sighdlr[sigtab[i].num];
89 			if(f == SIG_DFL || f == SIG_ERR)
90 				break;
91 			if(f != SIG_IGN) {
92 				_notetramp(sigtab[i].num, f, u);
93 				/* notetramp is machine-dependent; doesn't return to here */
94 			}
95 			_NOTED(0); /* NCONT */
96 			return;
97 		}
98 	}
99 	_doatexits();
100 	_NOTED(1); /* NDFLT */
101 }
102 
103 int
104 _stringsig(char *nam)
105 {
106 	int i;
107 
108 	for(i = 0; i<NSIGTAB; i++)
109 		if(strncmp(nam, sigtab[i].msg, strlen(sigtab[i].msg)) == 0)
110 			return sigtab[i].num;
111 	return 0;
112 }
113 
114 char *
115 _sigstring(int sig)
116 {
117 	int i;
118 
119 	for(i=0; i<NSIGTAB; i++)
120 		if(sigtab[i].num == sig)
121 			return sigtab[i].msg;
122 	return "unknown signal";
123 }
124