Commit | Line | Data |
---|---|---|
a8fd2d0d KM |
1 | /* |
2 | * Copyright (c) 1988 University of Utah. | |
3 | * Copyright (c) 1990 The Regents of the University of California. | |
4 | * All rights reserved. | |
5 | * | |
6 | * This code is derived from software contributed to Berkeley by | |
7 | * the Systems Programming Group of the University of Utah Computer | |
8 | * Science Department. | |
9 | * | |
10 | * %sccs.include.redist.c% | |
11 | * | |
22d09b27 | 12 | * from: Utah $Hdr: hpux_sig.c 1.1 90/07/09$ |
a8fd2d0d | 13 | * |
22d09b27 | 14 | * @(#)hpux_sig.c 7.5 (Berkeley) %G% |
a8fd2d0d KM |
15 | */ |
16 | ||
17 | /* | |
18 | * Signal related HPUX compatibility routines | |
19 | */ | |
20 | ||
21 | #ifdef HPUXCOMPAT | |
22 | ||
23 | #include "param.h" | |
24 | #include "systm.h" | |
196c0567 | 25 | #include "user.h" |
a8fd2d0d KM |
26 | #include "kernel.h" |
27 | #include "proc.h" | |
28 | #include "hpux.h" | |
29 | ||
30 | /* indexed by HPUX signal number - 1 */ | |
31 | char hpuxtobsdsigmap[NSIG] = { | |
32 | /*01*/ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGIOT, SIGEMT, SIGFPE, | |
33 | /*09*/ SIGKILL, SIGBUS, SIGSEGV, SIGSYS, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, | |
34 | /*17*/ SIGUSR2, SIGCHLD, 0, SIGVTALRM,SIGPROF, SIGIO, SIGWINCH, SIGSTOP, | |
35 | /*25*/ SIGTSTP, SIGCONT,SIGTTIN, SIGTTOU, SIGURG, 0, 0, 0 | |
36 | }; | |
37 | ||
38 | /* indexed by BSD signal number - 1 */ | |
39 | char bsdtohpuxsigmap[NSIG] = { | |
40 | /*01*/ 1, 2, 3, 4, 5, 6, 7, 8, | |
41 | /*09*/ 9, 10, 11, 12, 13, 14, 15, 29, | |
42 | /*17*/ 24, 25, 26, 18, 27, 28, 22, 0, | |
43 | /*25*/ 0, 20, 21, 23, 0, 16, 17, 0 | |
44 | }; | |
45 | ||
46 | /* | |
47 | * XXX: In addition to mapping the signal number we also have | |
48 | * to see if the "old" style signal mechinism is needed. | |
49 | * If so, we set the OUSIG flag. This is not really correct | |
50 | * as under HP-UX "old" style handling can be set on a per | |
51 | * signal basis and we are setting it for all signals in one | |
52 | * swell foop. I suspect we can get away with this since I | |
53 | * doubt any program of interest mixes the two semantics. | |
54 | */ | |
d9bd2b96 MH |
55 | hpuxsigvec(p, uap, retval) |
56 | struct proc *p; | |
57 | register struct args { | |
a8fd2d0d KM |
58 | int signo; |
59 | struct sigvec *nsv; | |
60 | struct sigvec *osv; | |
d9bd2b96 MH |
61 | } *uap; |
62 | int *retval; | |
63 | { | |
a8fd2d0d KM |
64 | struct sigvec vec; |
65 | register struct sigvec *sv; | |
66 | register int sig; | |
d9bd2b96 | 67 | int bit, error; |
a8fd2d0d KM |
68 | |
69 | sig = hpuxtobsdsig(uap->signo); | |
d9bd2b96 | 70 | if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) |
196c0567 | 71 | return (EINVAL); |
a8fd2d0d KM |
72 | sv = &vec; |
73 | if (uap->osv) { | |
74 | sv->sv_handler = u.u_signal[sig]; | |
75 | sv->sv_mask = u.u_sigmask[sig]; | |
76 | bit = sigmask(sig); | |
77 | sv->sv_flags = 0; | |
78 | if ((u.u_sigonstack & bit) != 0) | |
79 | sv->sv_flags |= SV_ONSTACK; | |
80 | if ((u.u_sigintr & bit) != 0) | |
81 | sv->sv_flags |= SV_INTERRUPT; | |
82 | #if 0 | |
83 | /* XXX -- SOUSIG no longer exists, do something here */ | |
d9bd2b96 | 84 | if (p->p_flag & SOUSIG) |
a8fd2d0d KM |
85 | sv->sv_flags |= HPUXSV_RESET; /* XXX */ |
86 | #endif | |
d9bd2b96 MH |
87 | error = copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); |
88 | if (error) | |
196c0567 | 89 | return (error); |
a8fd2d0d KM |
90 | } |
91 | if (uap->nsv) { | |
d9bd2b96 MH |
92 | error = copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); |
93 | if (error) | |
196c0567 | 94 | return (error); |
d9bd2b96 | 95 | if (sig == SIGCONT && sv->sv_handler == SIG_IGN) |
196c0567 | 96 | return (EINVAL); |
d9bd2b96 | 97 | setsigvec(p, sig, (struct sigaction *)sv); |
a8fd2d0d KM |
98 | #if 0 |
99 | /* XXX -- SOUSIG no longer exists, do something here */ | |
100 | if (sv->sv_flags & HPUXSV_RESET) | |
d9bd2b96 | 101 | p->p_flag |= SOUSIG; /* XXX */ |
a8fd2d0d KM |
102 | #endif |
103 | } | |
196c0567 | 104 | return (0); |
a8fd2d0d KM |
105 | } |
106 | ||
d9bd2b96 MH |
107 | hpuxsigblock(p, uap, retval) |
108 | register struct proc *p; | |
109 | struct args { | |
a8fd2d0d | 110 | int mask; |
d9bd2b96 MH |
111 | } *uap; |
112 | int *retval; | |
113 | { | |
a8fd2d0d KM |
114 | |
115 | (void) splhigh(); | |
d9bd2b96 MH |
116 | *retval = bsdtohpuxmask(p->p_sigmask); |
117 | p->p_sigmask |= hpuxtobsdmask(uap->mask) &~ sigcantmask; | |
a8fd2d0d | 118 | (void) spl0(); |
196c0567 | 119 | return (0); |
a8fd2d0d KM |
120 | } |
121 | ||
d9bd2b96 MH |
122 | hpuxsigsetmask(p, uap, retval) |
123 | struct proc *p; | |
124 | struct args { | |
a8fd2d0d | 125 | int mask; |
d9bd2b96 MH |
126 | } *uap; |
127 | int *retval; | |
128 | { | |
a8fd2d0d KM |
129 | |
130 | (void) splhigh(); | |
d9bd2b96 MH |
131 | *retval = bsdtohpuxmask(p->p_sigmask); |
132 | p->p_sigmask = hpuxtobsdmask(uap->mask) &~ sigcantmask; | |
a8fd2d0d | 133 | (void) spl0(); |
196c0567 | 134 | return (0); |
a8fd2d0d KM |
135 | } |
136 | ||
d9bd2b96 MH |
137 | hpuxsigpause(p, uap, retval) |
138 | struct proc *p; | |
139 | struct args { | |
a8fd2d0d | 140 | int mask; |
d9bd2b96 MH |
141 | } *uap; |
142 | int *retval; | |
143 | { | |
a8fd2d0d KM |
144 | |
145 | uap->mask = hpuxtobsdmask(uap->mask); | |
196c0567 | 146 | return (sigsuspend(p, uap, retval)); |
a8fd2d0d KM |
147 | } |
148 | ||
149 | /* not totally correct, but close enuf' */ | |
d9bd2b96 MH |
150 | hpuxkill(p, uap, retval) |
151 | struct proc *p; | |
152 | struct args { | |
a8fd2d0d KM |
153 | int pid; |
154 | int signo; | |
d9bd2b96 MH |
155 | } *uap; |
156 | int *retval; | |
157 | { | |
a8fd2d0d KM |
158 | |
159 | if (uap->signo) { | |
160 | uap->signo = hpuxtobsdsig(uap->signo); | |
161 | if (uap->signo == 0) | |
162 | uap->signo = NSIG; | |
163 | } | |
196c0567 | 164 | return (kill(p, uap, retval)); |
a8fd2d0d KM |
165 | } |
166 | ||
22d09b27 KM |
167 | /* |
168 | * The following (sigprocmask, sigpending, sigsuspend, sigaction are | |
169 | * POSIX calls. Under BSD, the library routine dereferences the sigset_t | |
170 | * pointers before traping. Not so under HP-UX. | |
171 | */ | |
172 | ||
173 | /* | |
174 | * Manipulate signal mask. | |
175 | * Note that we receive new mask, not pointer, | |
176 | * and return old mask as return value; | |
177 | * the library stub does the rest. | |
178 | */ | |
179 | hpuxsigprocmask(p, uap, retval) | |
180 | register struct proc *p; | |
181 | struct args { | |
182 | int how; | |
183 | hpuxsigset_t *set; | |
184 | hpuxsigset_t *oset; | |
185 | } *uap; | |
186 | int *retval; | |
187 | { | |
188 | int mask, error = 0; | |
189 | hpuxsigset_t sigset; | |
190 | ||
191 | /* | |
192 | * Copy out old mask first to ensure no errors. | |
193 | * (proc sigmask should not be changed if call fails for any reason) | |
194 | */ | |
195 | if (uap->oset) { | |
196 | bzero((caddr_t)&sigset, sizeof(sigset)); | |
197 | sigset.sigset[0] = bsdtohpuxmask(p->p_sigmask); | |
198 | if (copyout((caddr_t)&sigset, (caddr_t)uap->oset, sizeof(sigset))) | |
199 | return (EFAULT); | |
200 | } | |
201 | if (uap->set) { | |
202 | if (copyin((caddr_t)uap->set, (caddr_t)&sigset, sizeof(sigset))) | |
203 | return (EFAULT); | |
204 | mask = hpuxtobsdmask(sigset.sigset[0]); | |
205 | (void) splhigh(); | |
206 | switch (uap->how) { | |
207 | case HPUXSIG_BLOCK: | |
208 | p->p_sigmask |= mask &~ sigcantmask; | |
209 | break; | |
210 | case HPUXSIG_UNBLOCK: | |
211 | p->p_sigmask &= ~mask; | |
212 | break; | |
213 | case HPUXSIG_SETMASK: | |
214 | p->p_sigmask = mask &~ sigcantmask; | |
215 | break; | |
216 | default: | |
217 | error = EINVAL; | |
218 | break; | |
219 | } | |
220 | (void) spl0(); | |
221 | } | |
222 | return (error); | |
223 | } | |
224 | ||
225 | hpuxsigpending(p, uap, retval) | |
226 | register struct proc *p; | |
227 | struct args { | |
228 | hpuxsigset_t *set; | |
229 | } *uap; | |
230 | int *retval; | |
231 | { | |
232 | hpuxsigset_t sigset; | |
233 | ||
234 | sigset.sigset[0] = bsdtohpuxmask(p->p_sig); | |
235 | return (copyout((caddr_t)&sigset, (caddr_t)uap->set, sizeof(sigset))); | |
236 | } | |
237 | ||
238 | hpuxsigsuspend(p, uap, retval) | |
239 | register struct proc *p; | |
240 | struct args { | |
241 | hpuxsigset_t *set; | |
242 | } *uap; | |
243 | int *retval; | |
244 | { | |
245 | hpuxsigset_t sigset; | |
246 | int mask; | |
247 | ||
248 | if (copyin((caddr_t)uap->set, (caddr_t)&sigset, sizeof(sigset))) | |
249 | return (EFAULT); | |
250 | mask = hpuxtobsdmask(sigset.sigset[0]); | |
251 | u.u_oldmask = p->p_sigmask; | |
252 | p->p_flag |= SOMASK; | |
253 | p->p_sigmask = mask &~ sigcantmask; | |
254 | (void) tsleep((caddr_t)&u, PPAUSE | PCATCH, "pause", 0); | |
255 | /* always return EINTR rather than ERESTART... */ | |
256 | return (EINTR); | |
257 | } | |
258 | ||
259 | hpuxsigaction(p, uap, retval) | |
260 | struct proc *p; | |
261 | register struct args { | |
262 | int signo; | |
263 | struct hpuxsigaction *nsa; | |
264 | struct hpuxsigaction *osa; | |
265 | } *uap; | |
266 | int *retval; | |
267 | { | |
268 | struct hpuxsigaction action; | |
269 | register struct hpuxsigaction *sa; | |
270 | register int sig; | |
271 | int bit; | |
272 | ||
273 | sig = hpuxtobsdsig(uap->signo); | |
274 | if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) | |
275 | return (EINVAL); | |
276 | ||
277 | sa = &action; | |
278 | if (uap->osa) { | |
279 | sa->sa_handler = u.u_signal[sig]; | |
280 | bzero((caddr_t)&sa->sa_mask, sizeof(sa->sa_mask)); | |
281 | sa->sa_mask.sigset[0] = bsdtohpuxmask(u.u_sigmask[sig]); | |
282 | bit = sigmask(sig); | |
283 | sa->sa_flags = 0; | |
284 | if ((u.u_sigonstack & bit) != 0) | |
285 | sa->sa_flags |= HPUXSA_ONSTACK; | |
286 | #if 0 | |
287 | /* XXX -- SOUSIG no longer exists, do something here */ | |
288 | if (p->p_flag & SOUSIG) | |
289 | sa->sa_flags |= HPUXSA_RESETHAND; /* XXX */ | |
290 | #endif | |
291 | if (p->p_flag & SNOCLDSTOP) | |
292 | sa->sa_flags |= HPUXSA_NOCLDSTOP; | |
293 | if (copyout((caddr_t)sa, (caddr_t)uap->osa, sizeof (action))) | |
294 | return (EFAULT); | |
295 | } | |
296 | if (uap->nsa) { | |
297 | struct sigaction act; | |
298 | ||
299 | if (copyin((caddr_t)uap->nsa, (caddr_t)sa, sizeof (action))) | |
300 | return (EFAULT); | |
301 | if (sig == SIGCONT && sa->sa_handler == SIG_IGN) | |
302 | return (EINVAL); | |
303 | /* | |
304 | * Create a sigaction struct for setsigvec | |
305 | */ | |
306 | act.sa_handler = sa->sa_handler; | |
307 | act.sa_mask = hpuxtobsdmask(sa->sa_mask.sigset[0]); | |
308 | act.sa_flags = 0; | |
309 | if (sa->sa_flags & HPUXSA_ONSTACK) | |
310 | act.sa_flags |= SA_ONSTACK; | |
311 | if (sa->sa_flags & HPUXSA_NOCLDSTOP) | |
312 | act.sa_flags |= SA_NOCLDSTOP; | |
313 | setsigvec(p, sig, &act); | |
314 | #if 0 | |
315 | /* XXX -- SOUSIG no longer exists, do something here */ | |
316 | if (sa->sa_flags & HPUXSA_RESETHAND) | |
317 | p->p_flag |= SOUSIG; /* XXX */ | |
318 | #endif | |
319 | } | |
320 | return (0); | |
321 | } | |
322 | ||
d9bd2b96 MH |
323 | ohpuxssig(p, uap, retval) |
324 | struct proc *p; | |
325 | struct args { | |
a8fd2d0d KM |
326 | int signo; |
327 | sig_t fun; | |
d9bd2b96 MH |
328 | } *uap; |
329 | int *retval; | |
330 | { | |
a8fd2d0d KM |
331 | register int a; |
332 | struct sigvec vec; | |
333 | register struct sigvec *sv = &vec; | |
a8fd2d0d KM |
334 | |
335 | a = hpuxtobsdsig(uap->signo); | |
336 | sv->sv_handler = uap->fun; | |
337 | /* | |
338 | * Kill processes trying to use job control facilities | |
339 | * (this'll help us find any vestiges of the old stuff). | |
340 | */ | |
341 | if ((a &~ 0377) || | |
342 | (sv->sv_handler != SIG_DFL && sv->sv_handler != SIG_IGN && | |
343 | ((int)sv->sv_handler) & 1)) { | |
344 | psignal(p, SIGSYS); | |
196c0567 | 345 | return (0); |
a8fd2d0d KM |
346 | } |
347 | if (a <= 0 || a >= NSIG || a == SIGKILL || a == SIGSTOP || | |
d9bd2b96 | 348 | a == SIGCONT && sv->sv_handler == SIG_IGN) |
196c0567 | 349 | return (EINVAL); |
a8fd2d0d KM |
350 | sv->sv_mask = 0; |
351 | sv->sv_flags = SV_INTERRUPT; | |
d9bd2b96 MH |
352 | *retval = (int)u.u_signal[a]; |
353 | setsigvec(p, a, (struct sigaction *)sv); | |
a8fd2d0d KM |
354 | #if 0 |
355 | p->p_flag |= SOUSIG; /* mark as simulating old stuff */ | |
356 | #endif | |
196c0567 | 357 | return (0); |
a8fd2d0d KM |
358 | } |
359 | ||
360 | /* signal numbers: convert from HPUX to BSD */ | |
361 | hpuxtobsdsig(sig) | |
362 | register int sig; | |
363 | { | |
364 | if (--sig < 0 || sig >= NSIG) | |
365 | return(0); | |
366 | return((int)hpuxtobsdsigmap[sig]); | |
367 | } | |
368 | ||
369 | /* signal numbers: convert from BSD to HPUX */ | |
370 | bsdtohpuxsig(sig) | |
371 | register int sig; | |
372 | { | |
373 | if (--sig < 0 || sig >= NSIG) | |
374 | return(0); | |
375 | return((int)bsdtohpuxsigmap[sig]); | |
376 | } | |
377 | ||
378 | /* signal masks: convert from HPUX to BSD (not pretty or fast) */ | |
379 | hpuxtobsdmask(mask) | |
380 | register int mask; | |
381 | { | |
382 | register int nmask, sig, nsig; | |
383 | ||
384 | if (mask == 0 || mask == -1) | |
385 | return(mask); | |
386 | nmask = 0; | |
387 | for (sig = 1; sig < NSIG; sig++) | |
388 | if ((mask & sigmask(sig)) && (nsig = hpuxtobsdsig(sig))) | |
389 | nmask |= sigmask(nsig); | |
390 | return(nmask); | |
391 | } | |
392 | ||
393 | bsdtohpuxmask(mask) | |
394 | register int mask; | |
395 | { | |
396 | register int nmask, sig, nsig; | |
397 | ||
398 | if (mask == 0 || mask == -1) | |
399 | return(mask); | |
400 | nmask = 0; | |
401 | for (sig = 1; sig < NSIG; sig++) | |
402 | if ((mask & sigmask(sig)) && (nsig = bsdtohpuxsig(sig))) | |
403 | nmask |= sigmask(nsig); | |
404 | return(nmask); | |
405 | } | |
406 | #endif |