diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/plan9/signal.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/plan9/signal.c')
-rwxr-xr-x | sys/src/ape/lib/ap/plan9/signal.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/plan9/signal.c b/sys/src/ape/lib/ap/plan9/signal.c new file mode 100755 index 000000000..cf8a823ef --- /dev/null +++ b/sys/src/ape/lib/ap/plan9/signal.c @@ -0,0 +1,136 @@ +#include "lib.h" +#include "sys9.h" +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <setjmp.h> + +extern sigset_t _psigblocked; + +static struct { + char *msg; /* just check prefix */ + int num; +} sigtab[] = { + {"hangup", SIGHUP}, + {"interrupt", SIGINT}, + {"quit", SIGQUIT}, + {"alarm", SIGALRM}, + {"sys: trap: illegal instruction", SIGILL}, + {"sys: trap: reserved instruction", SIGILL}, + {"sys: trap: reserved", SIGILL}, + {"sys: trap: arithmetic overflow", SIGFPE}, + {"abort", SIGABRT}, + {"sys: fp:", SIGFPE}, + {"exit", SIGKILL}, + {"die", SIGKILL}, + {"kill", SIGKILL}, + {"sys: trap: bus error", SIGSEGV}, + {"sys: trap: address error", SIGSEGV}, + {"sys: trap: TLB", SIGSEGV}, + {"sys: write on closed pipe", SIGPIPE}, + {"alarm", SIGALRM}, + {"term", SIGTERM}, + {"usr1", SIGUSR1}, + {"usr2", SIGUSR2}, +}; +#define NSIGTAB ((sizeof sigtab)/(sizeof (sigtab[0]))) + +void (*_sighdlr[MAXSIG+1])(int, char*, Ureg*); /* 0 initialized: SIG_DFL */ + +void +(*signal(int sig, void (*func)(int, char*, Ureg*)))(int, char*, Ureg*) +{ + void(*oldf)(int, char*, Ureg*); + + if(sig <= 0 || sig > MAXSIG){ + errno = EINVAL; + return SIG_ERR; + } + oldf = _sighdlr[sig]; + if(sig == SIGKILL) + return oldf; /* can't catch or ignore SIGKILL */ + _sighdlr[sig] = func; + return oldf; +} + +/* BAD CODE - see /sys/src/ape/lib/ap/$objtype/setjmp.s for real code +int +sigsetjmp(sigjmp_buf buf, int savemask) +{ + int r; + + buf[0] = savemask; + buf[1] = _psigblocked; + return setjmp(&buf[2]); +} +*/ + +/* + * BUG: improper handling of process signal mask + */ +int +sigaction(int sig, struct sigaction *act, struct sigaction *oact) +{ + if(sig <= 0 || sig > MAXSIG || sig == SIGKILL){ + errno = EINVAL; + return -1; + } + if(oact){ + oact->sa_handler = _sighdlr[sig]; + oact->sa_mask = _psigblocked; + oact->sa_flags = 0; + } + if(act){ + _sighdlr[sig] = act->sa_handler; + } + return 0; +} + +/* this is registered in _envsetup */ +int +_notehandler(Ureg *u, char *msg) +{ + int i; + void(*f)(int, char*, Ureg*); + extern void _doatexits(void); /* in stdio/exit.c */ + + if(_finishing) + _finish(0, 0); + for(i = 0; i<NSIGTAB; i++){ + if(strncmp(msg, sigtab[i].msg, strlen(sigtab[i].msg)) == 0){ + f = _sighdlr[sigtab[i].num]; + if(f == SIG_DFL || f == SIG_ERR) + break; + if(f != SIG_IGN) { + _notetramp(sigtab[i].num, f, u); + /* notetramp is machine-dependent; doesn't return to here */ + } + _NOTED(0); /* NCONT */ + return; + } + } + _doatexits(); + _NOTED(1); /* NDFLT */ +} + +int +_stringsig(char *nam) +{ + int i; + + for(i = 0; i<NSIGTAB; i++) + if(strncmp(nam, sigtab[i].msg, strlen(sigtab[i].msg)) == 0) + return sigtab[i].num; + return 0; +} + +char * +_sigstring(int sig) +{ + int i; + + for(i=0; i<NSIGTAB; i++) + if(sigtab[i].num == sig) + return sigtab[i].msg; + return "unknown signal"; +} |