linux_signal.c revision 12858
1130812Smarcel/*-
2130812Smarcel * Copyright (c) 1994-1995 S�ren Schmidt
3130812Smarcel * All rights reserved.
4130812Smarcel *
5130812Smarcel * Redistribution and use in source and binary forms, with or without
6130812Smarcel * modification, are permitted provided that the following conditions
7130812Smarcel * are met:
8130812Smarcel * 1. Redistributions of source code must retain the above copyright
9130812Smarcel *    notice, this list of conditions and the following disclaimer
10130812Smarcel *    in this position and unchanged.
11130812Smarcel * 2. Redistributions in binary form must reproduce the above copyright
12130812Smarcel *    notice, this list of conditions and the following disclaimer in the
13130812Smarcel *    documentation and/or other materials provided with the distribution.
14130812Smarcel * 3. The name of the author may not be used to endorse or promote products
15130812Smarcel *    derived from this software withough specific prior written permission
16130812Smarcel *
17130812Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18130812Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19130812Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20130812Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21130812Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22130812Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23130812Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24130812Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25130812Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26130812Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27130812Smarcel *
28130812Smarcel *  $Id: linux_signal.c,v 1.2 1995/11/22 07:43:50 bde Exp $
29130812Smarcel */
30130812Smarcel
31130812Smarcel#include <sys/param.h>
32130812Smarcel#include <sys/systm.h>
33130812Smarcel#include <sys/sysproto.h>
34130812Smarcel#include <sys/proc.h>
35130812Smarcel#include <sys/exec.h>
36130812Smarcel#include <sys/signal.h>
37130812Smarcel#include <sys/signalvar.h>
38130812Smarcel
39130812Smarcel#include <i386/linux/linux.h>
40130812Smarcel#include <i386/linux/sysproto.h>
41130812Smarcel
42130812Smarcel#define DONTMASK    (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD))
43130812Smarcel
44130812Smarcelstatic sigset_t
45130812Smarcellinux_to_bsd_sigmask(linux_sigset_t mask) {
46130812Smarcel    int i;
47130812Smarcel    sigset_t new = 0;
48130812Smarcel
49130812Smarcel    for (i = 1; i <= LINUX_NSIG; i++)
50130812Smarcel	if (mask & (1 << i-1))
51130812Smarcel	    new |= (1 << (linux_to_bsd_signal[i]-1));
52130812Smarcel    return new;
53130812Smarcel}
54130812Smarcel
55130812Smarcelstatic linux_sigset_t
56130812Smarcelbsd_to_linux_sigmask(sigset_t mask) {
57130812Smarcel    int i;
58130812Smarcel    sigset_t new = 0;
59130812Smarcel
60130812Smarcel    for (i = 1; i <= NSIG; i++)
61130812Smarcel	if (mask & (1 << i-1))
62130812Smarcel	    new |= (1 << (bsd_to_linux_signal[i]-1));
63130812Smarcel    return new;
64130812Smarcel}
65130812Smarcel
66130812Smarcelstruct linux_sigaction_args {
67130812Smarcel    int sig;
68130812Smarcel    linux_sigaction_t *nsa;
69130812Smarcel    linux_sigaction_t *osa;
70130812Smarcel};
71130812Smarcel
72130812Smarcelint
73130812Smarcellinux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval)
74130812Smarcel{
75130812Smarcel    linux_sigaction_t linux_sa;
76130812Smarcel    struct sigaction *nsa = NULL, *osa = NULL, bsd_sa;
77130812Smarcel    struct sigaction_args /* {
78130812Smarcel	int signum;
79130812Smarcel	struct sigaction *nsa;
80130812Smarcel	struct sigaction *osa;
81130812Smarcel    } */ sa;
82130812Smarcel    int error;
83130812Smarcel
84130812Smarcel#ifdef DEBUG
85130812Smarcel    printf("Linux-emul(%d): sigaction(%d, *, *)\n", p->p_pid, args->sig);
86130812Smarcel#endif
87130812Smarcel    if (args->osa)
88130812Smarcel	osa = (struct sigaction *)ua_alloc_init(sizeof(struct sigaction));
89130812Smarcel
90130812Smarcel    if (args->nsa) {
91130812Smarcel	nsa = (struct sigaction *)ua_alloc(sizeof(struct sigaction));
92130812Smarcel	if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t)))
93130812Smarcel	    return error;
94130812Smarcel	bsd_sa.sa_mask = linux_to_bsd_sigmask(linux_sa.sa_mask);
95130812Smarcel	bsd_sa.sa_handler = linux_sa.sa_handler;
96130812Smarcel	bsd_sa.sa_flags = 0;
97130812Smarcel	if (linux_sa.sa_flags & LINUX_SA_NOCLDSTOP)
98130812Smarcel	    bsd_sa.sa_flags |= SA_NOCLDSTOP;
99130812Smarcel	if (linux_sa.sa_flags & LINUX_SA_ONSTACK)
100130812Smarcel	    bsd_sa.sa_flags |= SA_ONSTACK;
101130812Smarcel	if (linux_sa.sa_flags & LINUX_SA_RESTART)
102130812Smarcel	    bsd_sa.sa_flags |= SA_RESTART;
103130812Smarcel	if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction)))
104130812Smarcel	    return error;
105130812Smarcel    }
106130812Smarcel    sa.signum = linux_to_bsd_signal[args->sig];
107130812Smarcel    sa.nsa = nsa;
108130812Smarcel    sa.osa = osa;
109130812Smarcel    if ((error = sigaction(p, &sa, retval)))
110130812Smarcel	return error;
111130812Smarcel
112130812Smarcel    if (args->osa) {
113130812Smarcel	if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction)))
114130812Smarcel	    return error;
115130812Smarcel	linux_sa.sa_handler = bsd_sa.sa_handler;
116130812Smarcel	linux_sa.sa_restorer = NULL;
117130812Smarcel	linux_sa.sa_mask = bsd_to_linux_sigmask(bsd_sa.sa_mask);
118130812Smarcel	linux_sa.sa_flags = 0;
119130812Smarcel	if (bsd_sa.sa_flags & SA_NOCLDSTOP)
120130812Smarcel	    linux_sa.sa_flags |= LINUX_SA_NOCLDSTOP;
121130812Smarcel	if (bsd_sa.sa_flags & SA_ONSTACK)
122130812Smarcel	    linux_sa.sa_flags |= LINUX_SA_ONSTACK;
123130812Smarcel	if (bsd_sa.sa_flags & SA_RESTART)
124130812Smarcel	    linux_sa.sa_flags |= LINUX_SA_RESTART;
125130812Smarcel	if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t)))
126130812Smarcel	    return error;
127130812Smarcel    }
128130812Smarcel    return 0;
129130812Smarcel}
130130812Smarcel
131130812Smarcelstruct linux_sigprocmask_args {
132130812Smarcel    int how;
133130812Smarcel    linux_sigset_t *mask;
134130812Smarcel    linux_sigset_t *omask;
135130812Smarcel};
136130812Smarcel
137130812Smarcelint
138130812Smarcellinux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
139130812Smarcel		  int *retval)
140130812Smarcel{
141130812Smarcel    int error, s;
142130812Smarcel    sigset_t mask;
143130812Smarcel    sigset_t omask;
144130812Smarcel
145130812Smarcel#ifdef DEBUG
146130812Smarcel    printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how);
147130812Smarcel#endif
148130812Smarcel    if (args->omask != NULL) {
149130812Smarcel	omask = bsd_to_linux_sigmask(p->p_sigmask);
150130812Smarcel	if (error = copyout(&omask, args->omask, sizeof(sigset_t)))
151130812Smarcel	    return error;
152130812Smarcel    }
153130812Smarcel    if (!(args->mask))
154130812Smarcel	return 0;
155130812Smarcel    if (error = copyin(args->mask, &mask, sizeof(linux_sigset_t)))
156130812Smarcel	return error;
157130812Smarcel
158130812Smarcel    mask = linux_to_bsd_sigmask(mask);
159130812Smarcel    s = splhigh();
160130812Smarcel    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    struct sigsuspend_args /* {
231	int mask;
232    } */ tmp;
233
234#ifdef DEBUG
235    printf("Linux-emul(%d): sigsuspend(%08x)\n", p->p_pid, args->mask);
236#endif
237    tmp.mask = linux_to_bsd_sigmask(args->mask);
238    return sigsuspend(p, &tmp , retval);
239}
240
241struct linux_kill_args {
242    int pid;
243    int signum;
244};
245
246int
247linux_kill(struct proc *p, struct linux_kill_args *args, int *retval)
248{
249    struct kill_args /* {
250	int pid;
251	int signum;
252    } */ tmp;
253
254#ifdef DEBUG
255    printf("Linux-emul(%d): kill(%d, %d)\n",
256	   p->p_pid, args->pid, args->signum);
257#endif
258    tmp.pid = args->pid;
259    tmp.signum = linux_to_bsd_signal[args->signum];
260    return kill(p, &tmp, retval);
261}
262