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