ibcs2_signal.c revision 11605
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.4 1995/10/19 19:20:17 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 |= 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			if ((error = copyout(&sa, nbsa, sizeof(sa))) != 0)
313				return error;
314			if ((error = sigaction(p, &sa_args, retval)) != 0) {
315				DPRINTF(("signal: sigaction failed: %d\n",
316					 error));
317				*retval = (int)IBCS2_SIG_ERR;
318				return error;
319			}
320			if ((error = copyin(obsa, &sa, sizeof(sa))) != 0)
321				return error;
322			*retval = (int)sa.sa_handler;
323			return 0;
324		}
325
326	case IBCS2_SIGRELSE_MASK:
327		{
328			struct sigprocmask_args sa;
329
330			SCARG(&sa, how) = SIG_UNBLOCK;
331			SCARG(&sa, mask) = sigmask(signum);
332			return sigprocmask(p, &sa, retval);
333		}
334
335	case IBCS2_SIGIGNORE_MASK:
336		{
337			struct sigaction_args sa_args;
338			struct sigaction *bsa;
339
340			bsa = stackgap_alloc(&sg, sizeof(struct sigaction));
341			SCARG(&sa_args, signum) = signum;
342			SCARG(&sa_args, nsa) = bsa;
343			SCARG(&sa_args, osa) = NULL;
344
345			sa.sa_handler = SIG_IGN;
346			sigemptyset(&sa.sa_mask);
347			sa.sa_flags = 0;
348			if ((error = copyout(&sa, bsa, sizeof(sa))) != 0)
349				return error;
350			if ((error = sigaction(p, &sa_args, retval)) != 0) {
351				DPRINTF(("sigignore: sigaction failed\n"));
352				return error;
353			}
354			return 0;
355		}
356
357	case IBCS2_SIGPAUSE_MASK:
358		{
359			struct sigsuspend_args sa;
360
361			SCARG(&sa, mask) = p->p_sigmask &~ sigmask(signum);
362			return sigsuspend(p, &sa, retval);
363		}
364
365	default:
366		return ENOSYS;
367	}
368}
369
370int
371ibcs2_sigprocmask(p, uap, retval)
372	register struct proc *p;
373	struct ibcs2_sigprocmask_args *uap;
374	int *retval;
375{
376	ibcs2_sigset_t iss;
377	sigset_t bss;
378	int error = 0;
379
380	if (SCARG(uap, oset) != NULL) {
381		/* Fix the return value first if needed */
382		bsd_to_ibcs2_sigset(&p->p_sigmask, &iss);
383		if ((error = copyout(&iss, SCARG(uap, oset), sizeof(iss))) != 0)
384			return error;
385	}
386
387	if (SCARG(uap, set) == NULL)
388		/* Just examine */
389		return 0;
390
391	if ((error = copyin(SCARG(uap, set), &iss, sizeof(iss))) != 0)
392		return error;
393
394	ibcs2_to_bsd_sigset(&iss, &bss);
395
396	(void) splhigh();
397
398	switch (SCARG(uap, how)) {
399	case IBCS2_SIG_BLOCK:
400		p->p_sigmask |= bss & ~sigcantmask;
401		break;
402
403	case IBCS2_SIG_UNBLOCK:
404		p->p_sigmask &= ~bss;
405		break;
406
407	case IBCS2_SIG_SETMASK:
408		p->p_sigmask = bss & ~sigcantmask;
409		break;
410
411	default:
412		error = EINVAL;
413		break;
414	}
415
416	(void) spl0();
417
418	return error;
419}
420
421int
422ibcs2_sigpending(p, uap, retval)
423	register struct proc *p;
424	struct ibcs2_sigpending_args *uap;
425	int *retval;
426{
427	sigset_t bss;
428	ibcs2_sigset_t iss;
429
430	bss = p->p_siglist & p->p_sigmask;
431	bsd_to_ibcs2_sigset(&bss, &iss);
432
433	return copyout(&iss, SCARG(uap, mask), sizeof(iss));
434}
435
436int
437ibcs2_sigsuspend(p, uap, retval)
438	register struct proc *p;
439	struct ibcs2_sigsuspend_args *uap;
440	int *retval;
441{
442	ibcs2_sigset_t sss;
443	sigset_t bss;
444	struct sigsuspend_args sa;
445	int error;
446
447	if ((error = copyin(SCARG(uap, mask), &sss, sizeof(sss))) != 0)
448		return error;
449
450	ibcs2_to_bsd_sigset(&sss, &bss);
451
452	SCARG(&sa, mask) = bss;
453	return sigsuspend(p, &sa, retval);
454}
455
456int
457ibcs2_pause(p, uap, retval)
458	register struct proc *p;
459	struct ibcs2_pause_args *uap;
460	int *retval;
461{
462	struct sigsuspend_args bsa;
463
464	SCARG(&bsa, mask) = p->p_sigmask;
465	return sigsuspend(p, &bsa, retval);
466}
467
468int
469ibcs2_kill(p, uap, retval)
470	register struct proc *p;
471	struct ibcs2_kill_args *uap;
472	int *retval;
473{
474	struct kill_args ka;
475
476	SCARG(&ka, pid) = SCARG(uap, pid);
477	SCARG(&ka, signum) = ibcs2_to_bsd_sig[SCARG(uap, signo)];
478	return kill(p, &ka, retval);
479}
480