13e12c5d1SDavid du Colombier #include "lib.h"
23e12c5d1SDavid du Colombier #include "sys9.h"
33e12c5d1SDavid du Colombier #include <signal.h>
43e12c5d1SDavid du Colombier #include <errno.h>
53e12c5d1SDavid du Colombier #include <string.h>
67dd7cddfSDavid du Colombier #include <setjmp.h>
73e12c5d1SDavid du Colombier
8219b2ee8SDavid du Colombier extern sigset_t _psigblocked;
9219b2ee8SDavid du Colombier
103e12c5d1SDavid du Colombier static struct {
113e12c5d1SDavid du Colombier char *msg; /* just check prefix */
123e12c5d1SDavid du Colombier int num;
133e12c5d1SDavid du Colombier } sigtab[] = {
143e12c5d1SDavid du Colombier {"hangup", SIGHUP},
153e12c5d1SDavid du Colombier {"interrupt", SIGINT},
163e12c5d1SDavid du Colombier {"quit", SIGQUIT},
173e12c5d1SDavid du Colombier {"alarm", SIGALRM},
183e12c5d1SDavid du Colombier {"sys: trap: illegal instruction", SIGILL},
193e12c5d1SDavid du Colombier {"sys: trap: reserved instruction", SIGILL},
203e12c5d1SDavid du Colombier {"sys: trap: reserved", SIGILL},
21219b2ee8SDavid du Colombier {"sys: trap: arithmetic overflow", SIGFPE},
223e12c5d1SDavid du Colombier {"abort", SIGABRT},
233e12c5d1SDavid du Colombier {"sys: fp:", SIGFPE},
243e12c5d1SDavid du Colombier {"exit", SIGKILL},
253e12c5d1SDavid du Colombier {"die", SIGKILL},
263e12c5d1SDavid du Colombier {"kill", SIGKILL},
273e12c5d1SDavid du Colombier {"sys: trap: bus error", SIGSEGV},
283e12c5d1SDavid du Colombier {"sys: trap: address error", SIGSEGV},
293e12c5d1SDavid du Colombier {"sys: trap: TLB", SIGSEGV},
303e12c5d1SDavid du Colombier {"sys: write on closed pipe", SIGPIPE},
313e12c5d1SDavid du Colombier {"alarm", SIGALRM},
323e12c5d1SDavid du Colombier {"term", SIGTERM},
333e12c5d1SDavid du Colombier {"usr1", SIGUSR1},
343e12c5d1SDavid du Colombier {"usr2", SIGUSR2},
353e12c5d1SDavid du Colombier };
363e12c5d1SDavid du Colombier #define NSIGTAB ((sizeof sigtab)/(sizeof (sigtab[0])))
373e12c5d1SDavid du Colombier
38219b2ee8SDavid du Colombier void (*_sighdlr[MAXSIG+1])(int, char*, Ureg*); /* 0 initialized: SIG_DFL */
393e12c5d1SDavid du Colombier
40*781103c4SDavid du Colombier /* must match signal.h: extern void (*signal(int, void (*)()))(); */
41*781103c4SDavid du Colombier //void (*signal(int sig, void (*func)(int, char*, Ureg*)))(int, char*, Ureg*)
423e12c5d1SDavid du Colombier void
signal(int sig,void (* func)())43*781103c4SDavid du Colombier (*signal(int sig, void (*func)()))()
443e12c5d1SDavid du Colombier {
45219b2ee8SDavid du Colombier void(*oldf)(int, char*, Ureg*);
463e12c5d1SDavid du Colombier
473e12c5d1SDavid du Colombier if(sig <= 0 || sig > MAXSIG){
483e12c5d1SDavid du Colombier errno = EINVAL;
493e12c5d1SDavid du Colombier return SIG_ERR;
503e12c5d1SDavid du Colombier }
513e12c5d1SDavid du Colombier oldf = _sighdlr[sig];
523e12c5d1SDavid du Colombier if(sig == SIGKILL)
533e12c5d1SDavid du Colombier return oldf; /* can't catch or ignore SIGKILL */
543e12c5d1SDavid du Colombier _sighdlr[sig] = func;
553e12c5d1SDavid du Colombier return oldf;
563e12c5d1SDavid du Colombier }
573e12c5d1SDavid du Colombier
587dd7cddfSDavid du Colombier /* BAD CODE - see /sys/src/ape/lib/ap/$objtype/setjmp.s for real code
597dd7cddfSDavid du Colombier int
607dd7cddfSDavid du Colombier sigsetjmp(sigjmp_buf buf, int savemask)
617dd7cddfSDavid du Colombier {
627dd7cddfSDavid du Colombier int r;
637dd7cddfSDavid du Colombier
647dd7cddfSDavid du Colombier buf[0] = savemask;
657dd7cddfSDavid du Colombier buf[1] = _psigblocked;
667dd7cddfSDavid du Colombier return setjmp(&buf[2]);
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier */
697dd7cddfSDavid du Colombier
70219b2ee8SDavid du Colombier /*
71219b2ee8SDavid du Colombier * BUG: improper handling of process signal mask
72219b2ee8SDavid du Colombier */
733e12c5d1SDavid du Colombier int
sigaction(int sig,struct sigaction * act,struct sigaction * oact)74219b2ee8SDavid du Colombier sigaction(int sig, struct sigaction *act, struct sigaction *oact)
75219b2ee8SDavid du Colombier {
76219b2ee8SDavid du Colombier if(sig <= 0 || sig > MAXSIG || sig == SIGKILL){
77219b2ee8SDavid du Colombier errno = EINVAL;
78219b2ee8SDavid du Colombier return -1;
79219b2ee8SDavid du Colombier }
80219b2ee8SDavid du Colombier if(oact){
81219b2ee8SDavid du Colombier oact->sa_handler = _sighdlr[sig];
82219b2ee8SDavid du Colombier oact->sa_mask = _psigblocked;
83219b2ee8SDavid du Colombier oact->sa_flags = 0;
84219b2ee8SDavid du Colombier }
85219b2ee8SDavid du Colombier if(act){
86219b2ee8SDavid du Colombier _sighdlr[sig] = act->sa_handler;
87219b2ee8SDavid du Colombier }
88219b2ee8SDavid du Colombier return 0;
89219b2ee8SDavid du Colombier }
90219b2ee8SDavid du Colombier
91219b2ee8SDavid du Colombier /* this is registered in _envsetup */
92219b2ee8SDavid du Colombier int
_notehandler(void * u,char * msg)93*781103c4SDavid du Colombier _notehandler(void *u, char *msg)
943e12c5d1SDavid du Colombier {
953e12c5d1SDavid du Colombier int i;
96219b2ee8SDavid du Colombier void(*f)(int, char*, Ureg*);
97219b2ee8SDavid du Colombier extern void _doatexits(void); /* in stdio/exit.c */
983e12c5d1SDavid du Colombier
993e12c5d1SDavid du Colombier if(_finishing)
1003e12c5d1SDavid du Colombier _finish(0, 0);
1013e12c5d1SDavid du Colombier for(i = 0; i<NSIGTAB; i++){
1023e12c5d1SDavid du Colombier if(strncmp(msg, sigtab[i].msg, strlen(sigtab[i].msg)) == 0){
1033e12c5d1SDavid du Colombier f = _sighdlr[sigtab[i].num];
1043e12c5d1SDavid du Colombier if(f == SIG_DFL || f == SIG_ERR)
1053e12c5d1SDavid du Colombier break;
106219b2ee8SDavid du Colombier if(f != SIG_IGN) {
107219b2ee8SDavid du Colombier _notetramp(sigtab[i].num, f, u);
108219b2ee8SDavid du Colombier /* notetramp is machine-dependent; doesn't return to here */
109219b2ee8SDavid du Colombier }
1103e12c5d1SDavid du Colombier _NOTED(0); /* NCONT */
111*781103c4SDavid du Colombier return 0;
1123e12c5d1SDavid du Colombier }
1133e12c5d1SDavid du Colombier }
114219b2ee8SDavid du Colombier _doatexits();
1153e12c5d1SDavid du Colombier _NOTED(1); /* NDFLT */
116027288c8SDavid du Colombier return 0;
1173e12c5d1SDavid du Colombier }
1183e12c5d1SDavid du Colombier
1193e12c5d1SDavid du Colombier int
_stringsig(char * nam)1203e12c5d1SDavid du Colombier _stringsig(char *nam)
1213e12c5d1SDavid du Colombier {
1223e12c5d1SDavid du Colombier int i;
1233e12c5d1SDavid du Colombier
1243e12c5d1SDavid du Colombier for(i = 0; i<NSIGTAB; i++)
1253e12c5d1SDavid du Colombier if(strncmp(nam, sigtab[i].msg, strlen(sigtab[i].msg)) == 0)
1263e12c5d1SDavid du Colombier return sigtab[i].num;
1273e12c5d1SDavid du Colombier return 0;
1283e12c5d1SDavid du Colombier }
1293e12c5d1SDavid du Colombier
1303e12c5d1SDavid du Colombier char *
_sigstring(int sig)1313e12c5d1SDavid du Colombier _sigstring(int sig)
1323e12c5d1SDavid du Colombier {
1333e12c5d1SDavid du Colombier int i;
1343e12c5d1SDavid du Colombier
1353e12c5d1SDavid du Colombier for(i=0; i<NSIGTAB; i++)
1363e12c5d1SDavid du Colombier if(sigtab[i].num == sig)
1373e12c5d1SDavid du Colombier return sigtab[i].msg;
1383e12c5d1SDavid du Colombier return "unknown signal";
1393e12c5d1SDavid du Colombier }
140