ibcs2_signal.c revision 115684
111397Sswallace/*
211397Sswallace * Copyright (c) 1995 Scott Bartram
311605Sswallace * Copyright (c) 1995 Steven Wallace
43584Ssos * All rights reserved.
53584Ssos *
63584Ssos * Redistribution and use in source and binary forms, with or without
73584Ssos * modification, are permitted provided that the following conditions
83584Ssos * are met:
93584Ssos * 1. Redistributions of source code must retain the above copyright
1011397Sswallace *    notice, this list of conditions and the following disclaimer.
113584Ssos * 2. Redistributions in binary form must reproduce the above copyright
123584Ssos *    notice, this list of conditions and the following disclaimer in the
133584Ssos *    documentation and/or other materials provided with the distribution.
1411397Sswallace * 3. The name of the author may not be used to endorse or promote products
1511397Sswallace *    derived from this software without specific prior written permission
163584Ssos *
1711397Sswallace * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1811397Sswallace * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1911397Sswallace * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2011397Sswallace * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2111397Sswallace * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2211397Sswallace * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311397Sswallace * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411397Sswallace * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511397Sswallace * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2611397Sswallace * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273584Ssos */
283584Ssos
29115684Sobrien#include <sys/cdefs.h>
30115684Sobrien__FBSDID("$FreeBSD: head/sys/i386/ibcs2/ibcs2_signal.c 115684 2003-06-02 06:48:51Z obrien $");
31115684Sobrien
323584Ssos#include <sys/param.h>
333584Ssos#include <sys/systm.h>
3476166Smarkm#include <sys/lock.h>
3576166Smarkm#include <sys/mutex.h>
363584Ssos#include <sys/signalvar.h>
37113859Sjhb#include <sys/syscallsubr.h>
3811397Sswallace#include <sys/sysproto.h>
393584Ssos
4011397Sswallace#include <i386/ibcs2/ibcs2_types.h>
4111397Sswallace#include <i386/ibcs2/ibcs2_signal.h>
4211397Sswallace#include <i386/ibcs2/ibcs2_proto.h>
4311397Sswallace#include <i386/ibcs2/ibcs2_xenix.h>
4411397Sswallace#include <i386/ibcs2/ibcs2_util.h>
453584Ssos
4651793Smarcel#define sigemptyset(s)		SIGEMPTYSET(*(s))
4751793Smarcel#define sigismember(s, n)	SIGISMEMBER(*(s), n)
4851793Smarcel#define sigaddset(s, n)		SIGADDSET(*(s), n)
493584Ssos
5011397Sswallace#define	ibcs2_sigmask(n)	(1 << ((n) - 1))
5111397Sswallace#define ibcs2_sigemptyset(s)	bzero((s), sizeof(*(s)))
5211397Sswallace#define ibcs2_sigismember(s, n)	(*(s) & ibcs2_sigmask(n))
5311397Sswallace#define ibcs2_sigaddset(s, n)	(*(s) |= ibcs2_sigmask(n))
543584Ssos
5592761Salfredstatic void ibcs2_to_bsd_sigset(const ibcs2_sigset_t *, sigset_t *);
5692761Salfredstatic void bsd_to_ibcs2_sigset(const sigset_t *, ibcs2_sigset_t *);
5792761Salfredstatic void ibcs2_to_bsd_sigaction(struct ibcs2_sigaction *,
5892761Salfred					struct sigaction *);
5992761Salfredstatic void bsd_to_ibcs2_sigaction(struct sigaction *,
6092761Salfred					struct ibcs2_sigaction *);
6111397Sswallace
6251793Smarcelint bsd_to_ibcs2_sig[IBCS2_SIGTBLSZ] = {
6311397Sswallace	IBCS2_SIGHUP,		/* 1 */
6411397Sswallace	IBCS2_SIGINT,		/* 2 */
6511397Sswallace	IBCS2_SIGQUIT,		/* 3 */
6611397Sswallace	IBCS2_SIGILL,		/* 4 */
6711397Sswallace	IBCS2_SIGTRAP,		/* 5 */
6811397Sswallace	IBCS2_SIGABRT,		/* 6 */
6911397Sswallace	IBCS2_SIGEMT,		/* 7 */
7011397Sswallace	IBCS2_SIGFPE,		/* 8 */
7111397Sswallace	IBCS2_SIGKILL,		/* 9 */
7211397Sswallace	IBCS2_SIGBUS,		/* 10 */
7311397Sswallace	IBCS2_SIGSEGV,		/* 11 */
7411397Sswallace	IBCS2_SIGSYS,		/* 12 */
7511397Sswallace	IBCS2_SIGPIPE,		/* 13 */
7611397Sswallace	IBCS2_SIGALRM,		/* 14 */
7711397Sswallace	IBCS2_SIGTERM,		/* 15 */
7811397Sswallace	0,			/* 16 - SIGURG */
7911397Sswallace	IBCS2_SIGSTOP,		/* 17 */
8011397Sswallace	IBCS2_SIGTSTP,		/* 18 */
8111397Sswallace	IBCS2_SIGCONT,		/* 19 */
8211397Sswallace	IBCS2_SIGCLD,		/* 20 */
8311397Sswallace	IBCS2_SIGTTIN,		/* 21 */
8411397Sswallace	IBCS2_SIGTTOU,		/* 22 */
8511397Sswallace	IBCS2_SIGPOLL,		/* 23 */
8611397Sswallace	0,			/* 24 - SIGXCPU */
8711397Sswallace	0,			/* 25 - SIGXFSZ */
8811397Sswallace	IBCS2_SIGVTALRM,	/* 26 */
8911397Sswallace	IBCS2_SIGPROF,		/* 27 */
9011397Sswallace	IBCS2_SIGWINCH,		/* 28 */
9111397Sswallace	0,			/* 29 */
9211397Sswallace	IBCS2_SIGUSR1,		/* 30 */
9311397Sswallace	IBCS2_SIGUSR2,		/* 31 */
9451793Smarcel	0			/* 32 */
953584Ssos};
963584Ssos
9751793Smarcelstatic int ibcs2_to_bsd_sig[IBCS2_SIGTBLSZ] = {
9811397Sswallace	SIGHUP,			/* 1 */
9911397Sswallace	SIGINT,			/* 2 */
10011397Sswallace	SIGQUIT,		/* 3 */
10111397Sswallace	SIGILL,			/* 4 */
10211397Sswallace	SIGTRAP,		/* 5 */
10311397Sswallace	SIGABRT,		/* 6 */
10411397Sswallace	SIGEMT,			/* 7 */
10511397Sswallace	SIGFPE,			/* 8 */
10611397Sswallace	SIGKILL,		/* 9 */
10711397Sswallace	SIGBUS,			/* 10 */
10811397Sswallace	SIGSEGV,		/* 11 */
10911397Sswallace	SIGSYS,			/* 12 */
11011397Sswallace	SIGPIPE,		/* 13 */
11111397Sswallace	SIGALRM,		/* 14 */
11211397Sswallace	SIGTERM,		/* 15 */
11311397Sswallace	SIGUSR1,		/* 16 */
11411397Sswallace	SIGUSR2,		/* 17 */
11511397Sswallace	SIGCHLD,		/* 18 */
11611397Sswallace	0,			/* 19 - SIGPWR */
11711397Sswallace	SIGWINCH,		/* 20 */
11811397Sswallace	0,			/* 21 */
11911397Sswallace	SIGIO,			/* 22 */
12011397Sswallace	SIGSTOP,		/* 23 */
12111397Sswallace	SIGTSTP,		/* 24 */
12211397Sswallace	SIGCONT,		/* 25 */
12311397Sswallace	SIGTTIN,		/* 26 */
12411397Sswallace	SIGTTOU,		/* 27 */
12511397Sswallace	SIGVTALRM,		/* 28 */
12611397Sswallace	SIGPROF,		/* 29 */
12711397Sswallace	0,			/* 30 */
12811397Sswallace	0,			/* 31 */
12951793Smarcel	0			/* 32 */
1303584Ssos};
1313584Ssos
13211397Sswallacevoid
13311397Sswallaceibcs2_to_bsd_sigset(iss, bss)
13411397Sswallace	const ibcs2_sigset_t *iss;
13511397Sswallace	sigset_t *bss;
1363584Ssos{
13711397Sswallace	int i, newsig;
13811397Sswallace
13911397Sswallace	sigemptyset(bss);
14051793Smarcel	for (i = 1; i <= IBCS2_SIGTBLSZ; i++) {
14111397Sswallace		if (ibcs2_sigismember(iss, i)) {
14251793Smarcel			newsig = ibcs2_to_bsd_sig[_SIG_IDX(i)];
14311397Sswallace			if (newsig)
14411397Sswallace				sigaddset(bss, newsig);
14511397Sswallace		}
1463584Ssos	}
1473584Ssos}
1483584Ssos
14911397Sswallacestatic void
15011397Sswallacebsd_to_ibcs2_sigset(bss, iss)
15111397Sswallace	const sigset_t *bss;
15211397Sswallace	ibcs2_sigset_t *iss;
1533584Ssos{
15411397Sswallace	int i, newsig;
1553584Ssos
15611397Sswallace	ibcs2_sigemptyset(iss);
15751793Smarcel	for (i = 1; i <= IBCS2_SIGTBLSZ; i++) {
15811397Sswallace		if (sigismember(bss, i)) {
15951793Smarcel			newsig = bsd_to_ibcs2_sig[_SIG_IDX(i)];
16011397Sswallace			if (newsig)
16111397Sswallace				ibcs2_sigaddset(iss, newsig);
16211397Sswallace		}
1633584Ssos	}
1643584Ssos}
1653584Ssos
16611397Sswallacestatic void
16711397Sswallaceibcs2_to_bsd_sigaction(isa, bsa)
16811397Sswallace	struct ibcs2_sigaction *isa;
16911397Sswallace	struct sigaction *bsa;
17011397Sswallace{
17111397Sswallace
17248620Scracauer	bsa->sa_handler = isa->isa_handler;
17348620Scracauer	ibcs2_to_bsd_sigset(&isa->isa_mask, &bsa->sa_mask);
17411574Sswallace	bsa->sa_flags = 0;	/* ??? SA_NODEFER */
17548620Scracauer	if ((isa->isa_flags & IBCS2_SA_NOCLDSTOP) != 0)
17611397Sswallace		bsa->sa_flags |= SA_NOCLDSTOP;
1773584Ssos}
1783584Ssos
17911397Sswallacestatic void
18011397Sswallacebsd_to_ibcs2_sigaction(bsa, isa)
18111397Sswallace	struct sigaction *bsa;
18211397Sswallace	struct ibcs2_sigaction *isa;
18311397Sswallace{
1843584Ssos
18548620Scracauer	isa->isa_handler = bsa->sa_handler;
18648620Scracauer	bsd_to_ibcs2_sigset(&bsa->sa_mask, &isa->isa_mask);
18748620Scracauer	isa->isa_flags = 0;
18811397Sswallace	if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
18948620Scracauer		isa->isa_flags |= IBCS2_SA_NOCLDSTOP;
1903584Ssos}
1913584Ssos
19211397Sswallaceint
19383366Sjulianibcs2_sigaction(td, uap)
19483366Sjulian	register struct thread *td;
19511397Sswallace	struct ibcs2_sigaction_args *uap;
19611397Sswallace{
197113859Sjhb	struct ibcs2_sigaction isa;
198113859Sjhb	struct sigaction nbsa, obsa;
199113859Sjhb	struct sigaction *nbsap;
200113859Sjhb 	int error;
2013584Ssos
202113859Sjhb	if (uap->act != NULL) {
203113859Sjhb		if ((error = copyin(uap->act, &isa, sizeof(isa))) != 0)
204113859Sjhb			return (error);
205113859Sjhb		ibcs2_to_bsd_sigaction(&isa, &nbsa);
206113859Sjhb		nbsap = &nbsa;
20711397Sswallace	} else
208113859Sjhb		nbsap = NULL;
209113859Sjhb	error = kern_sigaction(td, ibcs2_to_bsd_sig[_SIG_IDX(uap->sig)], &nbsa,
210113859Sjhb	    &obsa, 0);
211113859Sjhb	if (error == 0 && uap->oact != NULL) {
212113859Sjhb		bsd_to_ibcs2_sigaction(&obsa, &isa);
213113859Sjhb		error = copyout(&isa, uap->oact, sizeof(isa));
2143584Ssos	}
215113859Sjhb	return (error);
2168876Srgrimes}
2173584Ssos
21811397Sswallaceint
21983366Sjulianibcs2_sigsys(td, uap)
22083366Sjulian	register struct thread *td;
22111397Sswallace	struct ibcs2_sigsys_args *uap;
2223584Ssos{
22383366Sjulian	struct proc *p = td->td_proc;
22411605Sswallace	struct sigaction sa;
225107849Salfred	int signum = ibcs2_to_bsd_sig[_SIG_IDX(IBCS2_SIGNO(uap->sig))];
22611397Sswallace	int error;
2273584Ssos
22811397Sswallace	if (signum <= 0 || signum >= IBCS2_NSIG) {
229107849Salfred		if (IBCS2_SIGCALL(uap->sig) == IBCS2_SIGNAL_MASK ||
230107849Salfred		    IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK)
23183366Sjulian			td->td_retval[0] = (int)IBCS2_SIG_ERR;
23211397Sswallace		return EINVAL;
23311397Sswallace	}
23411397Sswallace
235107849Salfred	switch (IBCS2_SIGCALL(uap->sig)) {
23611397Sswallace	case IBCS2_SIGSET_MASK:
23711397Sswallace		/*
23811605Sswallace		 * Check for SIG_HOLD action.
23911605Sswallace		 * Otherwise, perform signal() except with different sa_flags.
24011397Sswallace		 */
241107849Salfred		if (uap->fp != IBCS2_SIG_HOLD) {
24211605Sswallace			/* add sig to mask before exececuting signal handler */
24311605Sswallace			sa.sa_flags = 0;
24411605Sswallace			goto ibcs2_sigset;
24511605Sswallace		}
246102412Scharnier		/* else FALLTHROUGH to sighold */
24711605Sswallace
24811605Sswallace	case IBCS2_SIGHOLD_MASK:
24911605Sswallace		{
25052084Smarcel			sigset_t mask;
2513584Ssos
25252084Smarcel			SIGEMPTYSET(mask);
25352084Smarcel			SIGADDSET(mask, signum);
254113859Sjhb			return (kern_sigprocmask(td, SIG_BLOCK, &mask, NULL,
255113859Sjhb				    0));
25611397Sswallace		}
25711605Sswallace
25811397Sswallace	case IBCS2_SIGNAL_MASK:
25911397Sswallace		{
260113859Sjhb			struct sigaction osa;
2613584Ssos
26211605Sswallace			/* do not automatically block signal */
26311605Sswallace			sa.sa_flags = SA_NODEFER;
26411605Sswallace#ifdef SA_RESETHAND
26511605Sswallace			if((signum != IBCS2_SIGILL) &&
26611605Sswallace			   (signum != IBCS2_SIGTRAP) &&
26711605Sswallace			   (signum != IBCS2_SIGPWR))
26811605Sswallace				/* set to SIG_DFL before executing handler */
26911605Sswallace				sa.sa_flags |= SA_RESETHAND;
27011605Sswallace#endif
27111605Sswallace		ibcs2_sigset:
272107849Salfred			sa.sa_handler = uap->fp;
27311397Sswallace			sigemptyset(&sa.sa_mask);
27411397Sswallace#if 0
27511397Sswallace			if (signum != SIGALRM)
27611574Sswallace				sa.sa_flags |= SA_RESTART;
27711397Sswallace#endif
278113859Sjhb			error = kern_sigaction(td, signum, &sa, &osa, 0);
279113859Sjhb			if (error != 0) {
28011397Sswallace				DPRINTF(("signal: sigaction failed: %d\n",
28111397Sswallace					 error));
282113859Sjhb				td->td_retval[0] = (int)IBCS2_SIG_ERR;
283113859Sjhb				return (error);
28411397Sswallace			}
285113859Sjhb			td->td_retval[0] = (int)osa.sa_handler;
28620203Sswallace
28720203Sswallace			/* special sigset() check */
288107849Salfred                        if(IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) {
28971489Sjhb				PROC_LOCK(p);
29020203Sswallace			        /* check to make sure signal is not blocked */
291112888Sjeff                                if(sigismember(&td->td_sigmask, signum)) {
29220203Sswallace				        /* return SIG_HOLD and unblock signal*/
29383366Sjulian                                        td->td_retval[0] = (int)IBCS2_SIG_HOLD;
294112888Sjeff					SIGDELSET(td->td_sigmask, signum);
295112888Sjeff					signotify(td);
29620203Sswallace				}
29771489Sjhb				PROC_UNLOCK(p);
29871489Sjhb			}
29920203Sswallace
30011397Sswallace			return 0;
30111397Sswallace		}
30211397Sswallace
30311397Sswallace	case IBCS2_SIGRELSE_MASK:
30411397Sswallace		{
30552084Smarcel			sigset_t mask;
3063584Ssos
30752084Smarcel			SIGEMPTYSET(mask);
30852084Smarcel			SIGADDSET(mask, signum);
309113859Sjhb			return (kern_sigprocmask(td, SIG_UNBLOCK, &mask, NULL,
310113859Sjhb				    0));
31111397Sswallace		}
31211397Sswallace
31311397Sswallace	case IBCS2_SIGIGNORE_MASK:
31411397Sswallace		{
31511397Sswallace			sa.sa_handler = SIG_IGN;
31611397Sswallace			sigemptyset(&sa.sa_mask);
31711397Sswallace			sa.sa_flags = 0;
318113859Sjhb			error = kern_sigaction(td, signum, &sa, NULL, 0);
319113859Sjhb			if (error != 0)
32011397Sswallace				DPRINTF(("sigignore: sigaction failed\n"));
321113859Sjhb			return (error);
32211397Sswallace		}
32311397Sswallace
32411397Sswallace	case IBCS2_SIGPAUSE_MASK:
32511397Sswallace		{
32652084Smarcel			sigset_t mask;
3273584Ssos
32871489Sjhb			PROC_LOCK(p);
329112888Sjeff			mask = td->td_sigmask;
33071489Sjhb			PROC_UNLOCK(p);
33152084Smarcel			SIGDELSET(mask, signum);
332113859Sjhb			return kern_sigsuspend(td, mask);
33311397Sswallace		}
33411397Sswallace
3353584Ssos	default:
33611397Sswallace		return ENOSYS;
3373584Ssos	}
3383584Ssos}
3393584Ssos
3403584Ssosint
34183366Sjulianibcs2_sigprocmask(td, uap)
34283366Sjulian	register struct thread *td;
34311397Sswallace	struct ibcs2_sigprocmask_args *uap;
3443584Ssos{
34511397Sswallace	ibcs2_sigset_t iss;
346113859Sjhb	sigset_t oss, nss;
347113859Sjhb	sigset_t *nssp;
348113859Sjhb	int error, how;
3493584Ssos
350107849Salfred	switch (uap->how) {
35111397Sswallace	case IBCS2_SIG_BLOCK:
352113859Sjhb		how = SIG_BLOCK;
3533584Ssos		break;
35411397Sswallace	case IBCS2_SIG_UNBLOCK:
355113859Sjhb		how = SIG_UNBLOCK;
3563584Ssos		break;
35711397Sswallace	case IBCS2_SIG_SETMASK:
358113859Sjhb		how = SIG_SETMASK;
3593584Ssos		break;
3603584Ssos	default:
361113859Sjhb		return (EINVAL);
3623584Ssos	}
363113859Sjhb	if (uap->set != NULL) {
364113859Sjhb		if ((error = copyin(uap->set, &iss, sizeof(iss))) != 0)
365113859Sjhb			return error;
366113859Sjhb		ibcs2_to_bsd_sigset(&iss, &nss);
367113859Sjhb		nssp = &nss;
368113859Sjhb	} else
369113859Sjhb		nssp = NULL;
370113859Sjhb	error = kern_sigprocmask(td, how, nssp, &oss, 0);
371113859Sjhb	if (error == 0 && uap->oset != NULL) {
372113859Sjhb		bsd_to_ibcs2_sigset(&oss, &iss);
373113859Sjhb		error = copyout(&iss, uap->oset, sizeof(iss));
374113859Sjhb	}
375113859Sjhb	return (error);
3763584Ssos}
3773584Ssos
37811397Sswallaceint
37983366Sjulianibcs2_sigpending(td, uap)
38083366Sjulian	register struct thread *td;
38111397Sswallace	struct ibcs2_sigpending_args *uap;
38211397Sswallace{
38383366Sjulian	struct proc *p = td->td_proc;
38411397Sswallace	sigset_t bss;
38511397Sswallace	ibcs2_sigset_t iss;
3863584Ssos
38771489Sjhb	PROC_LOCK(p);
388112888Sjeff	bss = td->td_siglist;
389112888Sjeff	SIGSETOR(bss, p->p_siglist);
390112888Sjeff	SIGSETAND(bss, td->td_sigmask);
39171489Sjhb	PROC_UNLOCK(p);
39211397Sswallace	bsd_to_ibcs2_sigset(&bss, &iss);
39311397Sswallace
394107849Salfred	return copyout(&iss, uap->mask, sizeof(iss));
39511397Sswallace}
39611397Sswallace
3973584Ssosint
39883366Sjulianibcs2_sigsuspend(td, uap)
39983366Sjulian	register struct thread *td;
40011397Sswallace	struct ibcs2_sigsuspend_args *uap;
4013584Ssos{
40211397Sswallace	ibcs2_sigset_t sss;
40311397Sswallace	sigset_t bss;
40411397Sswallace	int error;
4058876Srgrimes
406107849Salfred	if ((error = copyin(uap->mask, &sss, sizeof(sss))) != 0)
40711397Sswallace		return error;
40811397Sswallace
40911397Sswallace	ibcs2_to_bsd_sigset(&sss, &bss);
410113859Sjhb	return kern_sigsuspend(td, bss);
4113584Ssos}
4123584Ssos
4133584Ssosint
41483366Sjulianibcs2_pause(td, uap)
41583366Sjulian	register struct thread *td;
41611397Sswallace	struct ibcs2_pause_args *uap;
4173584Ssos{
41852084Smarcel	sigset_t mask;
4193584Ssos
420113859Sjhb	PROC_LOCK(td->td_proc);
421112888Sjeff	mask = td->td_sigmask;
422113859Sjhb	PROC_UNLOCK(td->td_proc);
423113859Sjhb	return kern_sigsuspend(td, mask);
4243584Ssos}
4253584Ssos
4263584Ssosint
42783366Sjulianibcs2_kill(td, uap)
42883366Sjulian	register struct thread *td;
42911397Sswallace	struct ibcs2_kill_args *uap;
4303584Ssos{
43111397Sswallace	struct kill_args ka;
4323584Ssos
433107849Salfred	ka.pid = uap->pid;
434107849Salfred	ka.signum = ibcs2_to_bsd_sig[_SIG_IDX(uap->signo)];
43583366Sjulian	return kill(td, &ka);
4363584Ssos}
437