1139799Simp/*-
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$");
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;
209121016Stjr	if (uap->sig <= 0 || uap->sig > IBCS2_NSIG)
210121016Stjr		return (EINVAL);
211113859Sjhb	error = kern_sigaction(td, ibcs2_to_bsd_sig[_SIG_IDX(uap->sig)], &nbsa,
212113859Sjhb	    &obsa, 0);
213113859Sjhb	if (error == 0 && uap->oact != NULL) {
214113859Sjhb		bsd_to_ibcs2_sigaction(&obsa, &isa);
215113859Sjhb		error = copyout(&isa, uap->oact, sizeof(isa));
2163584Ssos	}
217113859Sjhb	return (error);
2188876Srgrimes}
2193584Ssos
22011397Sswallaceint
22183366Sjulianibcs2_sigsys(td, uap)
22283366Sjulian	register struct thread *td;
22311397Sswallace	struct ibcs2_sigsys_args *uap;
2243584Ssos{
22583366Sjulian	struct proc *p = td->td_proc;
22611605Sswallace	struct sigaction sa;
227121016Stjr	int signum = IBCS2_SIGNO(uap->sig);
22811397Sswallace	int error;
2293584Ssos
230121016Stjr	if (signum <= 0 || signum > IBCS2_NSIG) {
231107849Salfred		if (IBCS2_SIGCALL(uap->sig) == IBCS2_SIGNAL_MASK ||
232107849Salfred		    IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK)
23383366Sjulian			td->td_retval[0] = (int)IBCS2_SIG_ERR;
23411397Sswallace		return EINVAL;
23511397Sswallace	}
236121016Stjr	signum = ibcs2_to_bsd_sig[_SIG_IDX(signum)];
23711397Sswallace
238107849Salfred	switch (IBCS2_SIGCALL(uap->sig)) {
23911397Sswallace	case IBCS2_SIGSET_MASK:
24011397Sswallace		/*
24111605Sswallace		 * Check for SIG_HOLD action.
24211605Sswallace		 * Otherwise, perform signal() except with different sa_flags.
24311397Sswallace		 */
244107849Salfred		if (uap->fp != IBCS2_SIG_HOLD) {
24511605Sswallace			/* add sig to mask before exececuting signal handler */
24611605Sswallace			sa.sa_flags = 0;
24711605Sswallace			goto ibcs2_sigset;
24811605Sswallace		}
249102412Scharnier		/* else FALLTHROUGH to sighold */
25011605Sswallace
25111605Sswallace	case IBCS2_SIGHOLD_MASK:
25211605Sswallace		{
25352084Smarcel			sigset_t mask;
2543584Ssos
25552084Smarcel			SIGEMPTYSET(mask);
25652084Smarcel			SIGADDSET(mask, signum);
257113859Sjhb			return (kern_sigprocmask(td, SIG_BLOCK, &mask, NULL,
258113859Sjhb				    0));
25911397Sswallace		}
26011605Sswallace
26111397Sswallace	case IBCS2_SIGNAL_MASK:
26211397Sswallace		{
263113859Sjhb			struct sigaction osa;
2643584Ssos
26511605Sswallace			/* do not automatically block signal */
26611605Sswallace			sa.sa_flags = SA_NODEFER;
26711605Sswallace#ifdef SA_RESETHAND
26811605Sswallace			if((signum != IBCS2_SIGILL) &&
26911605Sswallace			   (signum != IBCS2_SIGTRAP) &&
27011605Sswallace			   (signum != IBCS2_SIGPWR))
27111605Sswallace				/* set to SIG_DFL before executing handler */
27211605Sswallace				sa.sa_flags |= SA_RESETHAND;
27311605Sswallace#endif
27411605Sswallace		ibcs2_sigset:
275107849Salfred			sa.sa_handler = uap->fp;
27611397Sswallace			sigemptyset(&sa.sa_mask);
27711397Sswallace#if 0
27811397Sswallace			if (signum != SIGALRM)
27911574Sswallace				sa.sa_flags |= SA_RESTART;
28011397Sswallace#endif
281113859Sjhb			error = kern_sigaction(td, signum, &sa, &osa, 0);
282113859Sjhb			if (error != 0) {
28311397Sswallace				DPRINTF(("signal: sigaction failed: %d\n",
28411397Sswallace					 error));
285113859Sjhb				td->td_retval[0] = (int)IBCS2_SIG_ERR;
286113859Sjhb				return (error);
28711397Sswallace			}
288113859Sjhb			td->td_retval[0] = (int)osa.sa_handler;
28920203Sswallace
29020203Sswallace			/* special sigset() check */
291107849Salfred                        if(IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) {
29271489Sjhb				PROC_LOCK(p);
29320203Sswallace			        /* check to make sure signal is not blocked */
294112888Sjeff                                if(sigismember(&td->td_sigmask, signum)) {
29520203Sswallace				        /* return SIG_HOLD and unblock signal*/
29683366Sjulian                                        td->td_retval[0] = (int)IBCS2_SIG_HOLD;
297112888Sjeff					SIGDELSET(td->td_sigmask, signum);
298112888Sjeff					signotify(td);
29920203Sswallace				}
30071489Sjhb				PROC_UNLOCK(p);
30171489Sjhb			}
30220203Sswallace
30311397Sswallace			return 0;
30411397Sswallace		}
30511397Sswallace
30611397Sswallace	case IBCS2_SIGRELSE_MASK:
30711397Sswallace		{
30852084Smarcel			sigset_t mask;
3093584Ssos
31052084Smarcel			SIGEMPTYSET(mask);
31152084Smarcel			SIGADDSET(mask, signum);
312113859Sjhb			return (kern_sigprocmask(td, SIG_UNBLOCK, &mask, NULL,
313113859Sjhb				    0));
31411397Sswallace		}
31511397Sswallace
31611397Sswallace	case IBCS2_SIGIGNORE_MASK:
31711397Sswallace		{
31811397Sswallace			sa.sa_handler = SIG_IGN;
31911397Sswallace			sigemptyset(&sa.sa_mask);
32011397Sswallace			sa.sa_flags = 0;
321113859Sjhb			error = kern_sigaction(td, signum, &sa, NULL, 0);
322113859Sjhb			if (error != 0)
32311397Sswallace				DPRINTF(("sigignore: sigaction failed\n"));
324113859Sjhb			return (error);
32511397Sswallace		}
32611397Sswallace
32711397Sswallace	case IBCS2_SIGPAUSE_MASK:
32811397Sswallace		{
32952084Smarcel			sigset_t mask;
3303584Ssos
33171489Sjhb			PROC_LOCK(p);
332112888Sjeff			mask = td->td_sigmask;
33371489Sjhb			PROC_UNLOCK(p);
33452084Smarcel			SIGDELSET(mask, signum);
335113859Sjhb			return kern_sigsuspend(td, mask);
33611397Sswallace		}
33711397Sswallace
3383584Ssos	default:
33911397Sswallace		return ENOSYS;
3403584Ssos	}
3413584Ssos}
3423584Ssos
3433584Ssosint
34483366Sjulianibcs2_sigprocmask(td, uap)
34583366Sjulian	register struct thread *td;
34611397Sswallace	struct ibcs2_sigprocmask_args *uap;
3473584Ssos{
34811397Sswallace	ibcs2_sigset_t iss;
349113859Sjhb	sigset_t oss, nss;
350113859Sjhb	sigset_t *nssp;
351113859Sjhb	int error, how;
3523584Ssos
353107849Salfred	switch (uap->how) {
35411397Sswallace	case IBCS2_SIG_BLOCK:
355113859Sjhb		how = SIG_BLOCK;
3563584Ssos		break;
35711397Sswallace	case IBCS2_SIG_UNBLOCK:
358113859Sjhb		how = SIG_UNBLOCK;
3593584Ssos		break;
36011397Sswallace	case IBCS2_SIG_SETMASK:
361113859Sjhb		how = SIG_SETMASK;
3623584Ssos		break;
3633584Ssos	default:
364113859Sjhb		return (EINVAL);
3653584Ssos	}
366113859Sjhb	if (uap->set != NULL) {
367113859Sjhb		if ((error = copyin(uap->set, &iss, sizeof(iss))) != 0)
368113859Sjhb			return error;
369113859Sjhb		ibcs2_to_bsd_sigset(&iss, &nss);
370113859Sjhb		nssp = &nss;
371113859Sjhb	} else
372113859Sjhb		nssp = NULL;
373113859Sjhb	error = kern_sigprocmask(td, how, nssp, &oss, 0);
374113859Sjhb	if (error == 0 && uap->oset != NULL) {
375113859Sjhb		bsd_to_ibcs2_sigset(&oss, &iss);
376113859Sjhb		error = copyout(&iss, uap->oset, sizeof(iss));
377113859Sjhb	}
378113859Sjhb	return (error);
3793584Ssos}
3803584Ssos
38111397Sswallaceint
38283366Sjulianibcs2_sigpending(td, uap)
38383366Sjulian	register struct thread *td;
38411397Sswallace	struct ibcs2_sigpending_args *uap;
38511397Sswallace{
38683366Sjulian	struct proc *p = td->td_proc;
38711397Sswallace	sigset_t bss;
38811397Sswallace	ibcs2_sigset_t iss;
3893584Ssos
39071489Sjhb	PROC_LOCK(p);
391112888Sjeff	bss = td->td_siglist;
392112888Sjeff	SIGSETOR(bss, p->p_siglist);
393112888Sjeff	SIGSETAND(bss, td->td_sigmask);
39471489Sjhb	PROC_UNLOCK(p);
39511397Sswallace	bsd_to_ibcs2_sigset(&bss, &iss);
39611397Sswallace
397107849Salfred	return copyout(&iss, uap->mask, sizeof(iss));
39811397Sswallace}
39911397Sswallace
4003584Ssosint
40183366Sjulianibcs2_sigsuspend(td, uap)
40283366Sjulian	register struct thread *td;
40311397Sswallace	struct ibcs2_sigsuspend_args *uap;
4043584Ssos{
40511397Sswallace	ibcs2_sigset_t sss;
40611397Sswallace	sigset_t bss;
40711397Sswallace	int error;
4088876Srgrimes
409107849Salfred	if ((error = copyin(uap->mask, &sss, sizeof(sss))) != 0)
41011397Sswallace		return error;
41111397Sswallace
41211397Sswallace	ibcs2_to_bsd_sigset(&sss, &bss);
413113859Sjhb	return kern_sigsuspend(td, bss);
4143584Ssos}
4153584Ssos
4163584Ssosint
41783366Sjulianibcs2_pause(td, uap)
41883366Sjulian	register struct thread *td;
41911397Sswallace	struct ibcs2_pause_args *uap;
4203584Ssos{
42152084Smarcel	sigset_t mask;
4223584Ssos
423113859Sjhb	PROC_LOCK(td->td_proc);
424112888Sjeff	mask = td->td_sigmask;
425113859Sjhb	PROC_UNLOCK(td->td_proc);
426113859Sjhb	return kern_sigsuspend(td, mask);
4273584Ssos}
4283584Ssos
4293584Ssosint
43083366Sjulianibcs2_kill(td, uap)
43183366Sjulian	register struct thread *td;
43211397Sswallace	struct ibcs2_kill_args *uap;
4333584Ssos{
43411397Sswallace	struct kill_args ka;
4353584Ssos
436121016Stjr	if (uap->signo <= 0 || uap->signo > IBCS2_NSIG)
437121016Stjr		return (EINVAL);
438107849Salfred	ka.pid = uap->pid;
439107849Salfred	ka.signum = ibcs2_to_bsd_sig[_SIG_IDX(uap->signo)];
440225617Skmacy	return sys_kill(td, &ka);
4413584Ssos}
442