1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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";
}
|