ibcs2_signal.c revision 52084
119370Spst/*
219370Spst * Copyright (c) 1995 Scott Bartram
319370Spst * Copyright (c) 1995 Steven Wallace
419370Spst * All rights reserved.
519370Spst *
619370Spst * Redistribution and use in source and binary forms, with or without
719370Spst * modification, are permitted provided that the following conditions
819370Spst * are met:
919370Spst * 1. Redistributions of source code must retain the above copyright
1019370Spst *    notice, this list of conditions and the following disclaimer.
1119370Spst * 2. Redistributions in binary form must reproduce the above copyright
1219370Spst *    notice, this list of conditions and the following disclaimer in the
1319370Spst *    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: head/sys/i386/ibcs2/ibcs2_signal.c 52084 1999-10-10 09:14:31Z marcel $
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)		SIGEMPTYSET(*(s))
43#define sigismember(s, n)	SIGISMEMBER(*(s), n)
44#define sigaddset(s, n)		SIGADDSET(*(s), 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[IBCS2_SIGTBLSZ] = {
59	IBCS2_SIGHUP,		/* 1 */
60	IBCS2_SIGINT,		/* 2 */
61	IBCS2_SIGQUIT,		/* 3 */
62	IBCS2_SIGILL,		/* 4 */
63	IBCS2_SIGTRAP,		/* 5 */
64	IBCS2_SIGABRT,		/* 6 */
65	IBCS2_SIGEMT,		/* 7 */
66	IBCS2_SIGFPE,		/* 8 */
67	IBCS2_SIGKILL,		/* 9 */
68	IBCS2_SIGBUS,		/* 10 */
69	IBCS2_SIGSEGV,		/* 11 */
70	IBCS2_SIGSYS,		/* 12 */
71	IBCS2_SIGPIPE,		/* 13 */
72	IBCS2_SIGALRM,		/* 14 */
73	IBCS2_SIGTERM,		/* 15 */
74	0,			/* 16 - SIGURG */
75	IBCS2_SIGSTOP,		/* 17 */
76	IBCS2_SIGTSTP,		/* 18 */
77	IBCS2_SIGCONT,		/* 19 */
78	IBCS2_SIGCLD,		/* 20 */
79	IBCS2_SIGTTIN,		/* 21 */
80	IBCS2_SIGTTOU,		/* 22 */
81	IBCS2_SIGPOLL,		/* 23 */
82	0,			/* 24 - SIGXCPU */
83	0,			/* 25 - SIGXFSZ */
84	IBCS2_SIGVTALRM,	/* 26 */
85	IBCS2_SIGPROF,		/* 27 */
86	IBCS2_SIGWINCH,		/* 28 */
87	0,			/* 29 */
88	IBCS2_SIGUSR1,		/* 30 */
89	IBCS2_SIGUSR2,		/* 31 */
90	0			/* 32 */
91};
92
93static int ibcs2_to_bsd_sig[IBCS2_SIGTBLSZ] = {
94	SIGHUP,			/* 1 */
95	SIGINT,			/* 2 */
96	SIGQUIT,		/* 3 */
97	SIGILL,			/* 4 */
98	SIGTRAP,		/* 5 */
99	SIGABRT,		/* 6 */
100	SIGEMT,			/* 7 */
101	SIGFPE,			/* 8 */
102	SIGKILL,		/* 9 */
103	SIGBUS,			/* 10 */
104	SIGSEGV,		/* 11 */
105	SIGSYS,			/* 12 */
106	SIGPIPE,		/* 13 */
107	SIGALRM,		/* 14 */
108	SIGTERM,		/* 15 */
109	SIGUSR1,		/* 16 */
110	SIGUSR2,		/* 17 */
111	SIGCHLD,		/* 18 */
112	0,			/* 19 - SIGPWR */
113	SIGWINCH,		/* 20 */
114	0,			/* 21 */
115	SIGIO,			/* 22 */
116	SIGSTOP,		/* 23 */
117	SIGTSTP,		/* 24 */
118	SIGCONT,		/* 25 */
119	SIGTTIN,		/* 26 */
120	SIGTTOU,		/* 27 */
121	SIGVTALRM,		/* 28 */
122	SIGPROF,		/* 29 */
123	0,			/* 30 */
124	0,			/* 31 */
125	0			/* 32 */
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_SIGTBLSZ; i++) {
137		if (ibcs2_sigismember(iss, i)) {
138			newsig = ibcs2_to_bsd_sig[_SIG_IDX(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 <= IBCS2_SIGTBLSZ; i++) {
154		if (sigismember(bss, i)) {
155			newsig = bsd_to_ibcs2_sig[_SIG_IDX(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->isa_handler;
169	ibcs2_to_bsd_sigset(&isa->isa_mask, &bsa->sa_mask);
170	bsa->sa_flags = 0;	/* ??? SA_NODEFER */
171	if ((isa->isa_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->isa_handler = bsa->sa_handler;
182	bsd_to_ibcs2_sigset(&bsa->sa_mask, &isa->isa_mask);
183	isa->isa_flags = 0;
184	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
185		isa->isa_flags |= IBCS2_SA_NOCLDSTOP;
186}
187
188int
189ibcs2_sigaction(p, uap)
190	register struct proc *p;
191	struct ibcs2_sigaction_args *uap;
192{
193	struct ibcs2_sigaction *nisa, *oisa, tmpisa;
194	struct sigaction *nbsa, *obsa, tmpbsa;
195	struct sigaction_args sa;
196	caddr_t sg;
197	int error;
198
199	sg = stackgap_init();
200	nisa = SCARG(uap, act);
201	oisa = SCARG(uap, oact);
202
203	if (oisa != NULL)
204		obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
205	else
206		obsa = NULL;
207
208	if (nisa != NULL) {
209		nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
210		if ((error = copyin(nisa, &tmpisa, sizeof(tmpisa))) != 0)
211			return error;
212		ibcs2_to_bsd_sigaction(&tmpisa, &tmpbsa);
213		if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
214			return error;
215	} else
216		nbsa = NULL;
217
218	SCARG(&sa, sig) = ibcs2_to_bsd_sig[_SIG_IDX(SCARG(uap, sig))];
219	SCARG(&sa, act) = nbsa;
220	SCARG(&sa, oact) = obsa;
221
222	if ((error = sigaction(p, &sa)) != 0)
223		return error;
224
225	if (oisa != NULL) {
226		if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
227			return error;
228		bsd_to_ibcs2_sigaction(&tmpbsa, &tmpisa);
229		if ((error = copyout(&tmpisa, oisa, sizeof(tmpisa))) != 0)
230			return error;
231	}
232
233	return 0;
234}
235
236int
237ibcs2_sigsys(p, uap)
238	register struct proc *p;
239	struct ibcs2_sigsys_args *uap;
240{
241	struct sigaction sa;
242	int signum = ibcs2_to_bsd_sig[_SIG_IDX(IBCS2_SIGNO(SCARG(uap, sig)))];
243	int error;
244	caddr_t sg = stackgap_init();
245
246	if (signum <= 0 || signum >= IBCS2_NSIG) {
247		if (IBCS2_SIGCALL(SCARG(uap, sig)) == IBCS2_SIGNAL_MASK ||
248		    IBCS2_SIGCALL(SCARG(uap, sig)) == IBCS2_SIGSET_MASK)
249			p->p_retval[0] = (int)IBCS2_SIG_ERR;
250		return EINVAL;
251	}
252
253	switch (IBCS2_SIGCALL(SCARG(uap, sig))) {
254	case IBCS2_SIGSET_MASK:
255		/*
256		 * Check for SIG_HOLD action.
257		 * Otherwise, perform signal() except with different sa_flags.
258		 */
259		if (SCARG(uap, fp) != IBCS2_SIG_HOLD) {
260			/* add sig to mask before exececuting signal handler */
261			sa.sa_flags = 0;
262			goto ibcs2_sigset;
263		}
264		/* else fallthrough to sighold */
265
266	case IBCS2_SIGHOLD_MASK:
267		{
268			sigset_t mask;
269			struct sigprocmask_args sa;
270
271			SIGEMPTYSET(mask);
272			SIGADDSET(mask, signum);
273			SCARG(&sa, how) = SIG_BLOCK;
274			SCARG(&sa, set) = &mask;
275			SCARG(&sa, oset) = NULL;
276			return sigprocmask(p, &sa);
277		}
278
279	case IBCS2_SIGNAL_MASK:
280		{
281			struct sigaction_args sa_args;
282			struct sigaction *nbsa, *obsa;
283
284			/* do not automatically block signal */
285			sa.sa_flags = SA_NODEFER;
286#ifdef SA_RESETHAND
287			if((signum != IBCS2_SIGILL) &&
288			   (signum != IBCS2_SIGTRAP) &&
289			   (signum != IBCS2_SIGPWR))
290				/* set to SIG_DFL before executing handler */
291				sa.sa_flags |= SA_RESETHAND;
292#endif
293		ibcs2_sigset:
294			nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
295			obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
296			SCARG(&sa_args, sig) = signum;
297			SCARG(&sa_args, act) = nbsa;
298			SCARG(&sa_args, oact) = obsa;
299
300			sa.sa_handler = SCARG(uap, fp);
301			sigemptyset(&sa.sa_mask);
302#if 0
303			if (signum != SIGALRM)
304				sa.sa_flags |= SA_RESTART;
305#endif
306			p->p_retval[0] = (int)IBCS2_SIG_ERR; /* init error return */
307
308			/* perform native sigaction() */
309			if ((error = copyout(&sa, nbsa, sizeof(sa))) != 0)
310				return error;
311			if ((error = sigaction(p, &sa_args)) != 0) {
312				DPRINTF(("signal: sigaction failed: %d\n",
313					 error));
314				return error;
315			}
316			if ((error = copyin(obsa, &sa, sizeof(sa))) != 0)
317				return error;
318			p->p_retval[0] = (int)sa.sa_handler;
319
320			/* special sigset() check */
321                        if(IBCS2_SIGCALL(SCARG(uap, sig)) == IBCS2_SIGSET_MASK)
322			        /* check to make sure signal is not blocked */
323                                if(sigismember(&p->p_sigmask, signum)) {
324				        /* return SIG_HOLD and unblock signal*/
325                                        p->p_retval[0] = (int)IBCS2_SIG_HOLD;
326					SIGDELSET(p->p_sigmask, signum);
327				}
328
329			return 0;
330		}
331
332	case IBCS2_SIGRELSE_MASK:
333		{
334			sigset_t mask;
335			struct sigprocmask_args sa;
336
337			SIGEMPTYSET(mask);
338			SIGADDSET(mask, signum);
339			SCARG(&sa, how) = SIG_UNBLOCK;
340			SCARG(&sa, set) = &mask;
341			SCARG(&sa, oset) = NULL;
342			return sigprocmask(p, &sa);
343		}
344
345	case IBCS2_SIGIGNORE_MASK:
346		{
347			struct sigaction_args sa_args;
348			struct sigaction *bsa;
349
350			bsa = stackgap_alloc(&sg, sizeof(struct sigaction));
351			SCARG(&sa_args, sig) = signum;
352			SCARG(&sa_args, act) = bsa;
353			SCARG(&sa_args, oact) = NULL;
354
355			sa.sa_handler = SIG_IGN;
356			sigemptyset(&sa.sa_mask);
357			sa.sa_flags = 0;
358			if ((error = copyout(&sa, bsa, sizeof(sa))) != 0)
359				return error;
360			if ((error = sigaction(p, &sa_args)) != 0) {
361				DPRINTF(("sigignore: sigaction failed\n"));
362				return error;
363			}
364			return 0;
365		}
366
367	case IBCS2_SIGPAUSE_MASK:
368		{
369			sigset_t mask;
370			struct sigsuspend_args sa;
371
372			mask = p->p_sigmask;
373			SIGDELSET(mask, signum);
374			SCARG(&sa, sigmask) = &mask;
375			return sigsuspend(p, &sa);
376		}
377
378	default:
379		return ENOSYS;
380	}
381}
382
383int
384ibcs2_sigprocmask(p, uap)
385	register struct proc *p;
386	struct ibcs2_sigprocmask_args *uap;
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		SIGSETOR(p->p_sigmask, bss);
413		SIG_CANTMASK(p->p_sigmask);
414		break;
415
416	case IBCS2_SIG_UNBLOCK:
417		SIGSETNAND(p->p_sigmask, bss);
418		break;
419
420	case IBCS2_SIG_SETMASK:
421		p->p_sigmask = bss;
422		SIG_CANTMASK(p->p_sigmask);
423		break;
424
425	default:
426		error = EINVAL;
427		break;
428	}
429
430	(void) spl0();
431
432	return error;
433}
434
435int
436ibcs2_sigpending(p, uap)
437	register struct proc *p;
438	struct ibcs2_sigpending_args *uap;
439{
440	sigset_t bss;
441	ibcs2_sigset_t iss;
442
443	bss = p->p_siglist;
444	SIGSETAND(bss, p->p_sigmask);
445	bsd_to_ibcs2_sigset(&bss, &iss);
446
447	return copyout(&iss, SCARG(uap, mask), sizeof(iss));
448}
449
450int
451ibcs2_sigsuspend(p, uap)
452	register struct proc *p;
453	struct ibcs2_sigsuspend_args *uap;
454{
455	ibcs2_sigset_t sss;
456	sigset_t bss;
457	struct sigsuspend_args sa;
458	int error;
459
460	if ((error = copyin(SCARG(uap, mask), &sss, sizeof(sss))) != 0)
461		return error;
462
463	ibcs2_to_bsd_sigset(&sss, &bss);
464	SCARG(&sa, sigmask) = &bss;
465	return sigsuspend(p, &sa);
466}
467
468int
469ibcs2_pause(p, uap)
470	register struct proc *p;
471	struct ibcs2_pause_args *uap;
472{
473	sigset_t mask;
474	struct sigsuspend_args sa;
475
476	mask = p->p_sigmask;
477	SCARG(&sa, sigmask) = &mask;
478	return sigsuspend(p, &sa);
479}
480
481int
482ibcs2_kill(p, uap)
483	register struct proc *p;
484	struct ibcs2_kill_args *uap;
485{
486	struct kill_args ka;
487
488	SCARG(&ka, pid) = SCARG(uap, pid);
489	SCARG(&ka, signum) = ibcs2_to_bsd_sig[_SIG_IDX(SCARG(uap, signo))];
490	return kill(p, &ka);
491}
492