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