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