linux_signal.c revision 12458
1/*-
2 * Copyright (c) 1994-1995 S�ren Schmidt
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer
10 *    in this position and unchanged.
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 withough 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 *  $Id: linux_signal.c,v 1.1 1995/06/25 17:32:40 sos Exp $
29 */
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/sysproto.h>
34#include <sys/proc.h>
35#include <sys/exec.h>
36#include <sys/signal.h>
37#include <sys/signalvar.h>
38
39#include <i386/linux/linux.h>
40#include <i386/linux/sysproto.h>
41
42#define DONTMASK    (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD))
43
44static sigset_t
45linux_to_bsd_sigmask(linux_sigset_t mask) {
46    int i;
47    sigset_t new = 0;
48
49    for (i = 1; i <= LINUX_NSIG; i++)
50	if (mask & (1 << i-1))
51	    new |= (1 << (linux_to_bsd_signal[i]-1));
52    return new;
53}
54
55static linux_sigset_t
56bsd_to_linux_sigmask(sigset_t mask) {
57    int i;
58    sigset_t new = 0;
59
60    for (i = 1; i <= NSIG; i++)
61	if (mask & (1 << i-1))
62	    new |= (1 << (bsd_to_linux_signal[i]-1));
63    return new;
64}
65
66struct linux_sigaction_args {
67    int sig;
68    linux_sigaction_t *nsa;
69    linux_sigaction_t *osa;
70};
71
72int
73linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval)
74{
75    linux_sigaction_t linux_sa;
76    struct sigaction *nsa = NULL, *osa = NULL, bsd_sa;
77    struct sigaction_args {
78	int sig;
79	struct sigaction *nsa;
80	struct sigaction *osa;
81    } sa;
82    int error;
83
84#ifdef DEBUG
85    printf("Linux-emul(%d): sigaction(%d, *, *)\n", p->p_pid, args->sig);
86#endif
87    if (args->osa)
88	osa = (struct sigaction *)ua_alloc_init(sizeof(struct sigaction));
89
90    if (args->nsa) {
91	nsa = (struct sigaction *)ua_alloc(sizeof(struct sigaction));
92	if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t)))
93	    return error;
94	bsd_sa.sa_mask = linux_to_bsd_sigmask(linux_sa.sa_mask);
95	bsd_sa.sa_handler = linux_sa.sa_handler;
96	bsd_sa.sa_flags = 0;
97	if (linux_sa.sa_flags & LINUX_SA_NOCLDSTOP)
98	    bsd_sa.sa_flags |= SA_NOCLDSTOP;
99	if (linux_sa.sa_flags & LINUX_SA_ONSTACK)
100	    bsd_sa.sa_flags |= SA_ONSTACK;
101	if (linux_sa.sa_flags & LINUX_SA_RESTART)
102	    bsd_sa.sa_flags |= SA_RESTART;
103	if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction)))
104	    return error;
105    }
106    sa.sig = linux_to_bsd_signal[args->sig];
107    sa.nsa = nsa;
108    sa.osa = osa;
109    if ((error = sigaction(p, &sa, retval)))
110	return error;
111
112    if (args->osa) {
113	if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction)))
114	    return error;
115	linux_sa.sa_handler = bsd_sa.sa_handler;
116	linux_sa.sa_restorer = NULL;
117	linux_sa.sa_mask = bsd_to_linux_sigmask(bsd_sa.sa_mask);
118	linux_sa.sa_flags = 0;
119	if (bsd_sa.sa_flags & SA_NOCLDSTOP)
120	    linux_sa.sa_flags |= LINUX_SA_NOCLDSTOP;
121	if (bsd_sa.sa_flags & SA_ONSTACK)
122	    linux_sa.sa_flags |= LINUX_SA_ONSTACK;
123	if (bsd_sa.sa_flags & SA_RESTART)
124	    linux_sa.sa_flags |= LINUX_SA_RESTART;
125	if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t)))
126	    return error;
127    }
128    return 0;
129}
130
131struct linux_sigprocmask_args {
132    int how;
133    linux_sigset_t *mask;
134    linux_sigset_t *omask;
135};
136
137int
138linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
139		  int *retval)
140{
141    int error, s;
142    sigset_t mask;
143    sigset_t omask;
144
145#ifdef DEBUG
146    printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how);
147#endif
148    if (args->omask != NULL) {
149	omask = bsd_to_linux_sigmask(p->p_sigmask);
150	if (error = copyout(&omask, args->omask, sizeof(sigset_t)))
151	    return error;
152    }
153    if (!(args->mask))
154	return 0;
155    if (error = copyin(args->mask, &mask, sizeof(linux_sigset_t)))
156	return error;
157
158    mask = linux_to_bsd_sigmask(mask);
159    s = splhigh();
160    switch (args->how) {
161    case LINUX_SIG_BLOCK:
162	p->p_sigmask |= (mask & ~DONTMASK);
163	break;
164    case LINUX_SIG_UNBLOCK:
165	p->p_sigmask &= ~mask;
166	break;
167    case LINUX_SIG_SETMASK:
168	p->p_sigmask = (mask & ~DONTMASK);
169	break;
170    default:
171	error = EINVAL;
172	break;
173    }
174    splx(s);
175    return error;
176}
177
178int
179linux_siggetmask(struct proc *p, void *args, int *retval)
180{
181#ifdef DEBUG
182    printf("Linux-emul(%d): siggetmask()\n", p->p_pid);
183#endif
184    *retval = bsd_to_linux_sigmask(p->p_sigmask);
185    return 0;
186}
187
188struct linux_sigsetmask_args {
189    linux_sigset_t mask;
190};
191
192int
193linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args,int *retval)
194{
195    int s;
196
197#ifdef DEBUG
198    printf("Linux-emul(%d): sigsetmask(%08x)\n", p->p_pid, args->mask);
199#endif
200    s = splhigh();
201    p->p_sigmask = (linux_to_bsd_sigmask(args->mask) & ~DONTMASK);
202    splx(s);
203    *retval = bsd_to_linux_sigmask(p->p_sigmask);
204    return 0;
205}
206
207struct linux_sigpending_args {
208    linux_sigset_t *mask;
209};
210
211int
212linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval)
213{
214    linux_sigset_t linux_sig;
215
216#ifdef DEBUG
217    printf("Linux-emul(%d): sigpending(*)\n", p->p_pid);
218#endif
219    linux_sig = bsd_to_linux_sigmask(p->p_siglist & p->p_sigmask);
220    return copyout(&linux_sig, args->mask, sizeof(linux_sig));
221}
222
223struct linux_sigsuspend_args {
224    linux_sigset_t mask;
225};
226
227int
228linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args,int *retval)
229{
230    sigset_t tmp;
231
232#ifdef DEBUG
233    printf("Linux-emul(%d): sigsuspend(%08x)\n", p->p_pid, args->mask);
234#endif
235    tmp = linux_to_bsd_sigmask(args->mask);
236    return sigsuspend(p, &tmp , retval);
237}
238
239struct linux_kill_args {
240    int pid;
241    int signum;
242};
243
244int
245linux_kill(struct proc *p, struct linux_kill_args *args, int *retval)
246{
247    struct {
248	int pid;
249	int signum;
250    } tmp;
251
252#ifdef DEBUG
253    printf("Linux-emul(%d): kill(%d, %d)\n",
254	   p->p_pid, args->pid, args->signum);
255#endif
256    tmp.pid = args->pid;
257    tmp.signum = linux_to_bsd_signal[args->signum];
258    return kill(p, &tmp, retval);
259}
260