1 /*
2 * Copyright (c) 1995 Scott Bartram
3 * Copyright (c) 1995 Steven Wallace
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $FreeBSD: releng/5.0/sys/i386/ibcs2/ibcs2_signal.c 108086 2002-12-19 09:40:13Z alfred $
29 */
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/lock.h>
34 #include <sys/mutex.h>
35 #include <sys/signalvar.h>
36 #include <sys/sysproto.h>
37
38 #include <i386/ibcs2/ibcs2_types.h>
39 #include <i386/ibcs2/ibcs2_signal.h>
40 #include <i386/ibcs2/ibcs2_proto.h>
41 #include <i386/ibcs2/ibcs2_xenix.h>
42 #include <i386/ibcs2/ibcs2_util.h>
43
44 #define sigemptyset(s) SIGEMPTYSET(*(s))
45 #define sigismember(s, n) SIGISMEMBER(*(s), n)
46 #define sigaddset(s, n) SIGADDSET(*(s), n)
47
48 #define ibcs2_sigmask(n) (1 << ((n) - 1))
49 #define ibcs2_sigemptyset(s) bzero((s), sizeof(*(s)))
50 #define ibcs2_sigismember(s, n) (*(s) & ibcs2_sigmask(n))
51 #define ibcs2_sigaddset(s, n) (*(s) |= ibcs2_sigmask(n))
52
53 static void ibcs2_to_bsd_sigset(const ibcs2_sigset_t *, sigset_t *);
54 static void bsd_to_ibcs2_sigset(const sigset_t *, ibcs2_sigset_t *);
55 static void ibcs2_to_bsd_sigaction(struct ibcs2_sigaction *,
56 struct sigaction *);
57 static void bsd_to_ibcs2_sigaction(struct sigaction *,
58 struct ibcs2_sigaction *);
59
60 int bsd_to_ibcs2_sig[IBCS2_SIGTBLSZ] = {
61 IBCS2_SIGHUP, /* 1 */
62 IBCS2_SIGINT, /* 2 */
63 IBCS2_SIGQUIT, /* 3 */
64 IBCS2_SIGILL, /* 4 */
65 IBCS2_SIGTRAP, /* 5 */
66 IBCS2_SIGABRT, /* 6 */
67 IBCS2_SIGEMT, /* 7 */
68 IBCS2_SIGFPE, /* 8 */
69 IBCS2_SIGKILL, /* 9 */
70 IBCS2_SIGBUS, /* 10 */
71 IBCS2_SIGSEGV, /* 11 */
72 IBCS2_SIGSYS, /* 12 */
73 IBCS2_SIGPIPE, /* 13 */
74 IBCS2_SIGALRM, /* 14 */
75 IBCS2_SIGTERM, /* 15 */
76 0, /* 16 - SIGURG */
77 IBCS2_SIGSTOP, /* 17 */
78 IBCS2_SIGTSTP, /* 18 */
79 IBCS2_SIGCONT, /* 19 */
80 IBCS2_SIGCLD, /* 20 */
81 IBCS2_SIGTTIN, /* 21 */
82 IBCS2_SIGTTOU, /* 22 */
83 IBCS2_SIGPOLL, /* 23 */
84 0, /* 24 - SIGXCPU */
85 0, /* 25 - SIGXFSZ */
86 IBCS2_SIGVTALRM, /* 26 */
87 IBCS2_SIGPROF, /* 27 */
88 IBCS2_SIGWINCH, /* 28 */
89 0, /* 29 */
90 IBCS2_SIGUSR1, /* 30 */
91 IBCS2_SIGUSR2, /* 31 */
92 0 /* 32 */
93 };
94
95 static int ibcs2_to_bsd_sig[IBCS2_SIGTBLSZ] = {
96 SIGHUP, /* 1 */
97 SIGINT, /* 2 */
98 SIGQUIT, /* 3 */
99 SIGILL, /* 4 */
100 SIGTRAP, /* 5 */
101 SIGABRT, /* 6 */
102 SIGEMT, /* 7 */
103 SIGFPE, /* 8 */
104 SIGKILL, /* 9 */
105 SIGBUS, /* 10 */
106 SIGSEGV, /* 11 */
107 SIGSYS, /* 12 */
108 SIGPIPE, /* 13 */
109 SIGALRM, /* 14 */
110 SIGTERM, /* 15 */
111 SIGUSR1, /* 16 */
112 SIGUSR2, /* 17 */
113 SIGCHLD, /* 18 */
114 0, /* 19 - SIGPWR */
115 SIGWINCH, /* 20 */
116 0, /* 21 */
117 SIGIO, /* 22 */
118 SIGSTOP, /* 23 */
119 SIGTSTP, /* 24 */
120 SIGCONT, /* 25 */
121 SIGTTIN, /* 26 */
122 SIGTTOU, /* 27 */
123 SIGVTALRM, /* 28 */
124 SIGPROF, /* 29 */
125 0, /* 30 */
126 0, /* 31 */
127 0 /* 32 */
128 };
129
130 void
131 ibcs2_to_bsd_sigset(iss, bss)
132 const ibcs2_sigset_t *iss;
133 sigset_t *bss;
134 {
135 int i, newsig;
136
137 sigemptyset(bss);
138 for (i = 1; i <= IBCS2_SIGTBLSZ; i++) {
139 if (ibcs2_sigismember(iss, i)) {
140 newsig = ibcs2_to_bsd_sig[_SIG_IDX(i)];
141 if (newsig)
142 sigaddset(bss, newsig);
143 }
144 }
145 }
146
147 static void
148 bsd_to_ibcs2_sigset(bss, iss)
149 const sigset_t *bss;
150 ibcs2_sigset_t *iss;
151 {
152 int i, newsig;
153
154 ibcs2_sigemptyset(iss);
155 for (i = 1; i <= IBCS2_SIGTBLSZ; i++) {
156 if (sigismember(bss, i)) {
157 newsig = bsd_to_ibcs2_sig[_SIG_IDX(i)];
158 if (newsig)
159 ibcs2_sigaddset(iss, newsig);
160 }
161 }
162 }
163
164 static void
165 ibcs2_to_bsd_sigaction(isa, bsa)
166 struct ibcs2_sigaction *isa;
167 struct sigaction *bsa;
168 {
169
170 bsa->sa_handler = isa->isa_handler;
171 ibcs2_to_bsd_sigset(&isa->isa_mask, &bsa->sa_mask);
172 bsa->sa_flags = 0; /* ??? SA_NODEFER */
173 if ((isa->isa_flags & IBCS2_SA_NOCLDSTOP) != 0)
174 bsa->sa_flags |= SA_NOCLDSTOP;
175 }
176
177 static void
178 bsd_to_ibcs2_sigaction(bsa, isa)
179 struct sigaction *bsa;
180 struct ibcs2_sigaction *isa;
181 {
182
183 isa->isa_handler = bsa->sa_handler;
184 bsd_to_ibcs2_sigset(&bsa->sa_mask, &isa->isa_mask);
185 isa->isa_flags = 0;
186 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
187 isa->isa_flags |= IBCS2_SA_NOCLDSTOP;
188 }
189
190 int
191 ibcs2_sigaction(td, uap)
192 register struct thread *td;
193 struct ibcs2_sigaction_args *uap;
194 {
195 struct ibcs2_sigaction *nisa, *oisa, tmpisa;
196 struct sigaction *nbsa, *obsa, tmpbsa;
197 struct sigaction_args sa;
198 caddr_t sg;
199 int error;
200
201 sg = stackgap_init();
202 nisa = uap->act;
203 oisa = uap->oact;
204
205 if (oisa != NULL)
206 obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
207 else
208 obsa = NULL;
209
210 if (nisa != NULL) {
211 nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
212 if ((error = copyin(nisa, &tmpisa, sizeof(tmpisa))) != 0)
213 return error;
214 ibcs2_to_bsd_sigaction(&tmpisa, &tmpbsa);
215 if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
216 return error;
217 } else
218 nbsa = NULL;
219
220 sa.sig = ibcs2_to_bsd_sig[_SIG_IDX(uap->sig)];
221 sa.act = nbsa;
222 sa.oact = obsa;
223
224 if ((error = sigaction(td, &sa)) != 0)
225 return error;
226
227 if (oisa != NULL) {
228 if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
229 return error;
230 bsd_to_ibcs2_sigaction(&tmpbsa, &tmpisa);
231 if ((error = copyout(&tmpisa, oisa, sizeof(tmpisa))) != 0)
232 return error;
233 }
234
235 return 0;
236 }
237
238 int
239 ibcs2_sigsys(td, uap)
240 register struct thread *td;
241 struct ibcs2_sigsys_args *uap;
242 {
243 struct proc *p = td->td_proc;
244 struct sigaction sa;
245 int signum = ibcs2_to_bsd_sig[_SIG_IDX(IBCS2_SIGNO(uap->sig))];
246 int error;
247 caddr_t sg = stackgap_init();
248
249 if (signum <= 0 || signum >= IBCS2_NSIG) {
250 if (IBCS2_SIGCALL(uap->sig) == IBCS2_SIGNAL_MASK ||
251 IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK)
252 td->td_retval[0] = (int)IBCS2_SIG_ERR;
253 return EINVAL;
254 }
255
256 switch (IBCS2_SIGCALL(uap->sig)) {
257 case IBCS2_SIGSET_MASK:
258 /*
259 * Check for SIG_HOLD action.
260 * Otherwise, perform signal() except with different sa_flags.
261 */
262 if (uap->fp != IBCS2_SIG_HOLD) {
263 /* add sig to mask before exececuting signal handler */
264 sa.sa_flags = 0;
265 goto ibcs2_sigset;
266 }
267 /* else FALLTHROUGH to sighold */
268
269 case IBCS2_SIGHOLD_MASK:
270 {
271 sigset_t mask;
272 struct sigprocmask_args sa;
273
274 SIGEMPTYSET(mask);
275 SIGADDSET(mask, signum);
276 sa.how = SIG_BLOCK;
277 sa.set = &mask;
278 sa.oset = NULL;
279 return sigprocmask(td, &sa);
280 }
281
282 case IBCS2_SIGNAL_MASK:
283 {
284 struct sigaction_args sa_args;
285 struct sigaction *nbsa, *obsa;
286
287 /* do not automatically block signal */
288 sa.sa_flags = SA_NODEFER;
289 #ifdef SA_RESETHAND
290 if((signum != IBCS2_SIGILL) &&
291 (signum != IBCS2_SIGTRAP) &&
292 (signum != IBCS2_SIGPWR))
293 /* set to SIG_DFL before executing handler */
294 sa.sa_flags |= SA_RESETHAND;
295 #endif
296 ibcs2_sigset:
297 nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
298 obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
299 sa_args.sig = signum;
300 sa_args.act = nbsa;
301 sa_args.oact = obsa;
302
303 sa.sa_handler = uap->fp;
304 sigemptyset(&sa.sa_mask);
305 #if 0
306 if (signum != SIGALRM)
307 sa.sa_flags |= SA_RESTART;
308 #endif
309 td->td_retval[0] = (int)IBCS2_SIG_ERR; /* init error return */
310
311 /* perform native sigaction() */
312 if ((error = copyout(&sa, nbsa, sizeof(sa))) != 0)
313 return error;
314 if ((error = sigaction(td, &sa_args)) != 0) {
315 DPRINTF(("signal: sigaction failed: %d\n",
316 error));
317 return error;
318 }
319 if ((error = copyin(obsa, &sa, sizeof(sa))) != 0)
320 return error;
321 td->td_retval[0] = (int)sa.sa_handler;
322
323 /* special sigset() check */
324 if(IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) {
325 PROC_LOCK(p);
326 /* check to make sure signal is not blocked */
327 if(sigismember(&p->p_sigmask, signum)) {
328 /* return SIG_HOLD and unblock signal*/
329 td->td_retval[0] = (int)IBCS2_SIG_HOLD;
330 SIGDELSET(p->p_sigmask, signum);
331 signotify(p);
332 }
333 PROC_UNLOCK(p);
334 }
335
336 return 0;
337 }
338
339 case IBCS2_SIGRELSE_MASK:
340 {
341 sigset_t mask;
342 struct sigprocmask_args sa;
343
344 SIGEMPTYSET(mask);
345 SIGADDSET(mask, signum);
346 sa.how = SIG_UNBLOCK;
347 sa.set = &mask;
348 sa.oset = NULL;
349 return sigprocmask(td, &sa);
350 }
351
352 case IBCS2_SIGIGNORE_MASK:
353 {
354 struct sigaction_args sa_args;
355 struct sigaction *bsa;
356
357 bsa = stackgap_alloc(&sg, sizeof(struct sigaction));
358 sa_args.sig = signum;
359 sa_args.act = bsa;
360 sa_args.oact = NULL;
361
362 sa.sa_handler = SIG_IGN;
363 sigemptyset(&sa.sa_mask);
364 sa.sa_flags = 0;
365 if ((error = copyout(&sa, bsa, sizeof(sa))) != 0)
366 return error;
367 if ((error = sigaction(td, &sa_args)) != 0) {
368 DPRINTF(("sigignore: sigaction failed\n"));
369 return error;
370 }
371 return 0;
372 }
373
374 case IBCS2_SIGPAUSE_MASK:
375 {
376 sigset_t mask;
377 struct sigsuspend_args sa;
378
379 PROC_LOCK(p);
380 mask = p->p_sigmask;
381 PROC_UNLOCK(p);
382 SIGDELSET(mask, signum);
383 sa.sigmask = &mask;
384 return sigsuspend(td, &sa);
385 }
386
387 default:
388 return ENOSYS;
389 }
390 }
391
392 int
393 ibcs2_sigprocmask(td, uap)
394 register struct thread *td;
395 struct ibcs2_sigprocmask_args *uap;
396 {
397 struct proc *p = td->td_proc;
398 ibcs2_sigset_t iss;
399 sigset_t bss;
400 int error = 0;
401
402 if (uap->oset != NULL) {
403 /* Fix the return value first if needed */
404 PROC_LOCK(p);
405 bsd_to_ibcs2_sigset(&p->p_sigmask, &iss);
406 PROC_UNLOCK(p);
407 if ((error = copyout(&iss, uap->oset, sizeof(iss))) != 0)
408 return error;
409 }
410
411 if (uap->set == NULL)
412 /* Just examine */
413 return 0;
414
415 if ((error = copyin(uap->set, &iss, sizeof(iss))) != 0)
416 return error;
417
418 ibcs2_to_bsd_sigset(&iss, &bss);
419
420 PROC_LOCK(p);
421
422 switch (uap->how) {
423 case IBCS2_SIG_BLOCK:
424 SIGSETOR(p->p_sigmask, bss);
425 SIG_CANTMASK(p->p_sigmask);
426 break;
427
428 case IBCS2_SIG_UNBLOCK:
429 SIGSETNAND(p->p_sigmask, bss);
430 signotify(p);
431 break;
432
433 case IBCS2_SIG_SETMASK:
434 p->p_sigmask = bss;
435 SIG_CANTMASK(p->p_sigmask);
436 signotify(p);
437 break;
438
439 default:
440 error = EINVAL;
441 break;
442 }
443
444 PROC_UNLOCK(p);
445
446 return error;
447 }
448
449 int
450 ibcs2_sigpending(td, uap)
451 register struct thread *td;
452 struct ibcs2_sigpending_args *uap;
453 {
454 struct proc *p = td->td_proc;
455 sigset_t bss;
456 ibcs2_sigset_t iss;
457
458 PROC_LOCK(p);
459 bss = p->p_siglist;
460 SIGSETAND(bss, p->p_sigmask);
461 PROC_UNLOCK(p);
462 bsd_to_ibcs2_sigset(&bss, &iss);
463
464 return copyout(&iss, uap->mask, sizeof(iss));
465 }
466
467 int
468 ibcs2_sigsuspend(td, uap)
469 register struct thread *td;
470 struct ibcs2_sigsuspend_args *uap;
471 {
472 ibcs2_sigset_t sss;
473 sigset_t bss;
474 struct sigsuspend_args sa;
475 int error;
476
477 if ((error = copyin(uap->mask, &sss, sizeof(sss))) != 0)
478 return error;
479
480 ibcs2_to_bsd_sigset(&sss, &bss);
481 sa.sigmask = &bss;
482 return sigsuspend(td, &sa);
483 }
484
485 int
486 ibcs2_pause(td, uap)
487 register struct thread *td;
488 struct ibcs2_pause_args *uap;
489 {
490 struct proc *p = td->td_proc;
491 sigset_t mask;
492 struct sigsuspend_args sa;
493
494 PROC_LOCK(p);
495 mask = td->td_proc->p_sigmask;
496 PROC_UNLOCK(p);
497 sa.sigmask = &mask;
498 return sigsuspend(td, &sa);
499 }
500
501 int
502 ibcs2_kill(td, uap)
503 register struct thread *td;
504 struct ibcs2_kill_args *uap;
505 {
506 struct kill_args ka;
507
508 ka.pid = uap->pid;
509 ka.signum = ibcs2_to_bsd_sig[_SIG_IDX(uap->signo)];
510 return kill(td, &ka);
511 }
Cache object: 48b8abd4d8ff49f8c8c99934fcbc9faa
|