ibcs2_signal.c revision 20203
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 * $Id: ibcs2_signal.c,v 1.6 1995/10/21 20:33:43 swallace Exp $
29 */
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/namei.h>
34#include <sys/proc.h>
35#include <sys/filedesc.h>
36#include <sys/ioctl.h>
37#include <sys/mount.h>
38#include <sys/kernel.h>
39#include <sys/signal.h>
40#include <sys/signalvar.h>
41#include <sys/malloc.h>
42#include <sys/sysproto.h>
43
44#include <i386/ibcs2/ibcs2_types.h>
45#include <i386/ibcs2/ibcs2_signal.h>
46#include <i386/ibcs2/ibcs2_proto.h>
47#include <i386/ibcs2/ibcs2_xenix.h>
48#include <i386/ibcs2/ibcs2_util.h>
49
50#define sigemptyset(s)		bzero((s), sizeof(*(s)))
51#define sigismember(s, n)	(*(s) & sigmask(n))
52#define sigaddset(s, n)		(*(s) |= sigmask(n))
53
54#define	ibcs2_sigmask(n)	(1 << ((n) - 1))
55#define ibcs2_sigemptyset(s)	bzero((s), sizeof(*(s)))
56#define ibcs2_sigismember(s, n)	(*(s) & ibcs2_sigmask(n))
57#define ibcs2_sigaddset(s, n)	(*(s) |= ibcs2_sigmask(n))
58
59static void ibcs2_to_bsd_sigset    __P((const ibcs2_sigset_t *, sigset_t *));
60static void bsd_to_ibcs2_sigset    __P((const sigset_t *, ibcs2_sigset_t *));
61static void ibcs2_to_bsd_sigaction __P((struct ibcs2_sigaction *,
62					struct sigaction *));
63static void bsd_to_ibcs2_sigaction __P((struct sigaction *,
64					struct ibcs2_sigaction *));
65
66int bsd_to_ibcs2_sig[] = {
67	0,			/* 0 */
68	IBCS2_SIGHUP,		/* 1 */
69	IBCS2_SIGINT,		/* 2 */
70	IBCS2_SIGQUIT,		/* 3 */
71	IBCS2_SIGILL,		/* 4 */
72	IBCS2_SIGTRAP,		/* 5 */
73	IBCS2_SIGABRT,		/* 6 */
74	IBCS2_SIGEMT,		/* 7 */
75	IBCS2_SIGFPE,		/* 8 */
76	IBCS2_SIGKILL,		/* 9 */
77	IBCS2_SIGBUS,		/* 10 */
78	IBCS2_SIGSEGV,		/* 11 */
79	IBCS2_SIGSYS,		/* 12 */
80	IBCS2_SIGPIPE,		/* 13 */
81	IBCS2_SIGALRM,		/* 14 */
82	IBCS2_SIGTERM,		/* 15 */
83	0,			/* 16 - SIGURG */
84	IBCS2_SIGSTOP,		/* 17 */
85	IBCS2_SIGTSTP,		/* 18 */
86	IBCS2_SIGCONT,		/* 19 */
87	IBCS2_SIGCLD,		/* 20 */
88	IBCS2_SIGTTIN,		/* 21 */
89	IBCS2_SIGTTOU,		/* 22 */
90	IBCS2_SIGPOLL,		/* 23 */
91	0,			/* 24 - SIGXCPU */
92	0,			/* 25 - SIGXFSZ */
93	IBCS2_SIGVTALRM,	/* 26 */
94	IBCS2_SIGPROF,		/* 27 */
95	IBCS2_SIGWINCH,		/* 28 */
96	0,			/* 29 */
97	IBCS2_SIGUSR1,		/* 30 */
98	IBCS2_SIGUSR2,		/* 31 */
99};
100
101static int ibcs2_to_bsd_sig[] = {
102	0,			/* 0 */
103	SIGHUP,			/* 1 */
104	SIGINT,			/* 2 */
105	SIGQUIT,		/* 3 */
106	SIGILL,			/* 4 */
107	SIGTRAP,		/* 5 */
108	SIGABRT,		/* 6 */
109	SIGEMT,			/* 7 */
110	SIGFPE,			/* 8 */
111	SIGKILL,		/* 9 */
112	SIGBUS,			/* 10 */
113	SIGSEGV,		/* 11 */
114	SIGSYS,			/* 12 */
115	SIGPIPE,		/* 13 */
116	SIGALRM,		/* 14 */
117	SIGTERM,		/* 15 */
118	SIGUSR1,		/* 16 */
119	SIGUSR2,		/* 17 */
120	SIGCHLD,		/* 18 */
121	0,			/* 19 - SIGPWR */
122	SIGWINCH,		/* 20 */
123	0,			/* 21 */
124	SIGIO,			/* 22 */
125	SIGSTOP,		/* 23 */
126	SIGTSTP,		/* 24 */
127	SIGCONT,		/* 25 */
128	SIGTTIN,		/* 26 */
129	SIGTTOU,		/* 27 */
130	SIGVTALRM,		/* 28 */
131	SIGPROF,		/* 29 */
132	0,			/* 30 */
133	0,			/* 31 */
134};
135
136void
137ibcs2_to_bsd_sigset(iss, bss)
138	const ibcs2_sigset_t *iss;
139	sigset_t *bss;
140{
141	int i, newsig;
142
143	sigemptyset(bss);
144	for (i = 1; i < IBCS2_NSIG; i++) {
145		if (ibcs2_sigismember(iss, i)) {
146			newsig = ibcs2_to_bsd_sig[i];
147			if (newsig)
148				sigaddset(bss, newsig);
149		}
150	}
151}
152
153static void
154bsd_to_ibcs2_sigset(bss, iss)
155	const sigset_t *bss;
156	ibcs2_sigset_t *iss;
157{
158	int i, newsig;
159
160	ibcs2_sigemptyset(iss);
161	for (i = 1; i < NSIG; i++) {
162		if (sigismember(bss, i)) {
163			newsig = bsd_to_ibcs2_sig[i];
164			if (newsig)
165				ibcs2_sigaddset(iss, newsig);
166		}
167	}
168}
169
170static void
171ibcs2_to_bsd_sigaction(isa, bsa)
172	struct ibcs2_sigaction *isa;
173	struct sigaction *bsa;
174{
175
176	bsa->sa_handler = isa->sa_handler;
177	ibcs2_to_bsd_sigset(&isa->sa_mask, &bsa->sa_mask);
178	bsa->sa_flags = 0;	/* ??? SA_NODEFER */
179	if ((isa->sa_flags & IBCS2_SA_NOCLDSTOP) != 0)
180		bsa->sa_flags |= SA_NOCLDSTOP;
181}
182
183static void
184bsd_to_ibcs2_sigaction(bsa, isa)
185	struct sigaction *bsa;
186	struct ibcs2_sigaction *isa;
187{
188
189	isa->sa_handler = bsa->sa_handler;
190	bsd_to_ibcs2_sigset(&bsa->sa_mask, &isa->sa_mask);
191	isa->sa_flags = 0;
192	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
193		isa->sa_flags |= IBCS2_SA_NOCLDSTOP;
194}
195
196int
197ibcs2_sigaction(p, uap, retval)
198	register struct proc *p;
199	struct ibcs2_sigaction_args *uap;
200	int *retval;
201{
202	struct ibcs2_sigaction *nisa, *oisa, tmpisa;
203	struct sigaction *nbsa, *obsa, tmpbsa;
204	struct sigaction_args sa;
205	caddr_t sg;
206	int error;
207
208	sg = stackgap_init();
209	nisa = SCARG(uap, act);
210	oisa = SCARG(uap, oact);
211
212	if (oisa != NULL)
213		obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
214	else
215		obsa = NULL;
216
217	if (nisa != NULL) {
218		nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
219		if ((error = copyin(nisa, &tmpisa, sizeof(tmpisa))) != 0)
220			return error;
221		ibcs2_to_bsd_sigaction(&tmpisa, &tmpbsa);
222		if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
223			return error;
224	} else
225		nbsa = NULL;
226
227	SCARG(&sa, signum) = ibcs2_to_bsd_sig[SCARG(uap, sig)];
228	SCARG(&sa, nsa) = nbsa;
229	SCARG(&sa, osa) = obsa;
230
231	if ((error = sigaction(p, &sa, retval)) != 0)
232		return error;
233
234	if (oisa != NULL) {
235		if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
236			return error;
237		bsd_to_ibcs2_sigaction(&tmpbsa, &tmpisa);
238		if ((error = copyout(&tmpisa, oisa, sizeof(tmpisa))) != 0)
239			return error;
240	}
241
242	return 0;
243}
244
245int
246ibcs2_sigsys(p, uap, retval)
247	register struct proc *p;
248	struct ibcs2_sigsys_args *uap;
249	int *retval;
250{
251	struct sigaction sa;
252	int signum = ibcs2_to_bsd_sig[IBCS2_SIGNO(SCARG(uap, sig))];
253	int error;
254	caddr_t sg = stackgap_init();
255
256	if (signum <= 0 || signum >= IBCS2_NSIG) {
257		if (IBCS2_SIGCALL(SCARG(uap, sig)) == IBCS2_SIGNAL_MASK ||
258		    IBCS2_SIGCALL(SCARG(uap, sig)) == IBCS2_SIGSET_MASK)
259			*retval = (int)IBCS2_SIG_ERR;
260		return EINVAL;
261	}
262
263	switch (IBCS2_SIGCALL(SCARG(uap, sig))) {
264	case IBCS2_SIGSET_MASK:
265		/*
266		 * Check for SIG_HOLD action.
267		 * Otherwise, perform signal() except with different sa_flags.
268		 */
269		if (SCARG(uap, fp) != IBCS2_SIG_HOLD) {
270			/* add sig to mask before exececuting signal handler */
271			sa.sa_flags = 0;
272			goto ibcs2_sigset;
273		}
274		/* else fallthrough to sighold */
275
276	case IBCS2_SIGHOLD_MASK:
277		{
278			struct sigprocmask_args sa;
279
280			SCARG(&sa, how) = SIG_BLOCK;
281			SCARG(&sa, mask) = sigmask(signum);
282			return sigprocmask(p, &sa, retval);
283		}
284
285	case IBCS2_SIGNAL_MASK:
286		{
287			struct sigaction_args sa_args;
288			struct sigaction *nbsa, *obsa;
289
290			/* do not automatically block signal */
291			sa.sa_flags = SA_NODEFER;
292#ifdef SA_RESETHAND
293			if((signum != IBCS2_SIGILL) &&
294			   (signum != IBCS2_SIGTRAP) &&
295			   (signum != IBCS2_SIGPWR))
296				/* set to SIG_DFL before executing handler */
297				sa.sa_flags |= SA_RESETHAND;
298#endif
299		ibcs2_sigset:
300			nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
301			obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
302			SCARG(&sa_args, signum) = signum;
303			SCARG(&sa_args, nsa) = nbsa;
304			SCARG(&sa_args, osa) = obsa;
305
306			sa.sa_handler = SCARG(uap, fp);
307			sigemptyset(&sa.sa_mask);
308#if 0
309			if (signum != SIGALRM)
310				sa.sa_flags |= SA_RESTART;
311#endif
312			*retval = (int)IBCS2_SIG_ERR; /* init error return */
313
314			/* perform native sigaction() */
315			if ((error = copyout(&sa, nbsa, sizeof(sa))) != 0)
316				return error;
317			if ((error = sigaction(p, &sa_args, retval)) != 0) {
318				DPRINTF(("signal: sigaction failed: %d\n",
319					 error));
320				return error;
321			}
322			if ((error = copyin(obsa, &sa, sizeof(sa))) != 0)
323				return error;
324			*retval = (int)sa.sa_handler;
325
326			/* special sigset() check */
327                        if(IBCS2_SIGCALL(SCARG(uap, sig)) == IBCS2_SIGSET_MASK)
328			        /* check to make sure signal is not blocked */
329                                if(sigismember(&p->p_sigmask, signum)) {
330				        /* return SIG_HOLD and unblock signal*/
331                                        *retval = (int)IBCS2_SIG_HOLD;
332					p->p_sigmask &= ~sigmask(signum);
333				}
334
335			return 0;
336		}
337
338	case IBCS2_SIGRELSE_MASK:
339		{
340			struct sigprocmask_args sa;
341
342			SCARG(&sa, how) = SIG_UNBLOCK;
343			SCARG(&sa, mask) = sigmask(signum);
344			return sigprocmask(p, &sa, retval);
345		}
346
347	case IBCS2_SIGIGNORE_MASK:
348		{
349			struct sigaction_args sa_args;
350			struct sigaction *bsa;
351
352			bsa = stackgap_alloc(&sg, sizeof(struct sigaction));
353			SCARG(&sa_args, signum) = signum;
354			SCARG(&sa_args, nsa) = bsa;
355			SCARG(&sa_args, osa) = NULL;
356
357			sa.sa_handler = SIG_IGN;
358			sigemptyset(&sa.sa_mask);
359			sa.sa_flags = 0;
360			if ((error = copyout(&sa, bsa, sizeof(sa))) != 0)
361				return error;
362			if ((error = sigaction(p, &sa_args, retval)) != 0) {
363				DPRINTF(("sigignore: sigaction failed\n"));
364				return error;
365			}
366			return 0;
367		}
368
369	case IBCS2_SIGPAUSE_MASK:
370		{
371			struct sigsuspend_args sa;
372
373			SCARG(&sa, mask) = p->p_sigmask &~ sigmask(signum);
374			return sigsuspend(p, &sa, retval);
375		}
376
377	default:
378		return ENOSYS;
379	}
380}
381
382int
383ibcs2_sigprocmask(p, uap, retval)
384	register struct proc *p;
385	struct ibcs2_sigprocmask_args *uap;
386	int *retval;
387{
388	ibcs2_sigset_t iss;
389	sigset_t bss;
390	int error = 0;
391
392	if (SCARG(uap, oset) != NULL) {
393		/* Fix the return value first if needed */
394		bsd_to_ibcs2_sigset(&p->p_sigmask, &iss);
395		if ((error = copyout(&iss, SCARG(uap, oset), sizeof(iss))) != 0)
396			return error;
397	}
398
399	if (SCARG(uap, set) == NULL)
400		/* Just examine */
401		return 0;
402
403	if ((error = copyin(SCARG(uap, set), &iss, sizeof(iss))) != 0)
404		return error;
405
406	ibcs2_to_bsd_sigset(&iss, &bss);
407
408	(void) splhigh();
409
410	switch (SCARG(uap, how)) {
411	case IBCS2_SIG_BLOCK:
412		p->p_sigmask |= bss & ~sigcantmask;
413		break;
414
415	case IBCS2_SIG_UNBLOCK:
416		p->p_sigmask &= ~bss;
417		break;
418
419	case IBCS2_SIG_SETMASK:
420		p->p_sigmask = bss & ~sigcantmask;
421		break;
422
423	default:
424		error = EINVAL;
425		break;
426	}
427
428	(void) spl0();
429
430	return error;
431}
432
433int
434ibcs2_sigpending(p, uap, retval)
435	register struct proc *p;
436	struct ibcs2_sigpending_args *uap;
437	int *retval;
438{
439	sigset_t bss;
440	ibcs2_sigset_t iss;
441
442	bss = p->p_siglist & p->p_sigmask;
443	bsd_to_ibcs2_sigset(&bss, &iss);
444
445	return copyout(&iss, SCARG(uap, mask), sizeof(iss));
446}
447
448int
449ibcs2_sigsuspend(p, uap, retval)
450	register struct proc *p;
451	struct ibcs2_sigsuspend_args *uap;
452	int *retval;
453{
454	ibcs2_sigset_t sss;
455	sigset_t bss;
456	struct sigsuspend_args sa;
457	int error;
458
459	if ((error = copyin(SCARG(uap, mask), &sss, sizeof(sss))) != 0)
460		return error;
461
462	ibcs2_to_bsd_sigset(&sss, &bss);
463
464	SCARG(&sa, mask) = bss;
465	return sigsuspend(p, &sa, retval);
466}
467
468int
469ibcs2_pause(p, uap, retval)
470	register struct proc *p;
471	struct ibcs2_pause_args *uap;
472	int *retval;
473{
474	struct sigsuspend_args bsa;
475
476	SCARG(&bsa, mask) = p->p_sigmask;
477	return sigsuspend(p, &bsa, retval);
478}
479
480int
481ibcs2_kill(p, uap, retval)
482	register struct proc *p;
483	struct ibcs2_kill_args *uap;
484	int *retval;
485{
486	struct kill_args ka;
487
488	SCARG(&ka, pid) = SCARG(uap, pid);
489	SCARG(&ka, signum) = ibcs2_to_bsd_sig[SCARG(uap, signo)];
490	return kill(p, &ka, retval);
491}
492