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