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