linux_signal.c revision 12458
155714Skris/*-
255714Skris * Copyright (c) 1994-1995 S�ren Schmidt
355714Skris * All rights reserved.
455714Skris *
555714Skris * Redistribution and use in source and binary forms, with or without
655714Skris * modification, are permitted provided that the following conditions
755714Skris * are met:
855714Skris * 1. Redistributions of source code must retain the above copyright
955714Skris *    notice, this list of conditions and the following disclaimer
1055714Skris *    in this position and unchanged.
1155714Skris * 2. Redistributions in binary form must reproduce the above copyright
1255714Skris *    notice, this list of conditions and the following disclaimer in the
1355714Skris *    documentation and/or other materials provided with the distribution.
14109998Smarkm * 3. The name of the author may not be used to endorse or promote products
1555714Skris *    derived from this software withough specific prior written permission
1655714Skris *
1755714Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1855714Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1955714Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2055714Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2155714Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2255714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2355714Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24109998Smarkm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2555714Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2655714Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2755714Skris *
28109998Smarkm *  $Id: linux_signal.c,v 1.1 1995/06/25 17:32:40 sos Exp $
2955714Skris */
3055714Skris
3155714Skris#include <sys/param.h>
3255714Skris#include <sys/systm.h>
3355714Skris#include <sys/sysproto.h>
3455714Skris#include <sys/proc.h>
3555714Skris#include <sys/exec.h>
3655714Skris#include <sys/signal.h>
3755714Skris#include <sys/signalvar.h>
3855714Skris
3955714Skris#include <i386/linux/linux.h>
4055714Skris#include <i386/linux/sysproto.h>
4155714Skris
4255714Skris#define DONTMASK    (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD))
4355714Skris
4455714Skrisstatic sigset_t
4555714Skrislinux_to_bsd_sigmask(linux_sigset_t mask) {
4655714Skris    int i;
4755714Skris    sigset_t new = 0;
4855714Skris
4955714Skris    for (i = 1; i <= LINUX_NSIG; i++)
5055714Skris	if (mask & (1 << i-1))
5155714Skris	    new |= (1 << (linux_to_bsd_signal[i]-1));
5255714Skris    return new;
5355714Skris}
5455714Skris
5555714Skrisstatic linux_sigset_t
5655714Skrisbsd_to_linux_sigmask(sigset_t mask) {
5755714Skris    int i;
5855714Skris    sigset_t new = 0;
5955714Skris
6055714Skris    for (i = 1; i <= NSIG; i++)
6155714Skris	if (mask & (1 << i-1))
6255714Skris	    new |= (1 << (bsd_to_linux_signal[i]-1));
6355714Skris    return new;
6455714Skris}
6555714Skris
6655714Skrisstruct linux_sigaction_args {
6755714Skris    int sig;
6855714Skris    linux_sigaction_t *nsa;
69100936Snectar    linux_sigaction_t *osa;
70100936Snectar};
71100936Snectar
72100936Snectarint
73100936Snectarlinux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval)
74100936Snectar{
75100936Snectar    linux_sigaction_t linux_sa;
76100936Snectar    struct sigaction *nsa = NULL, *osa = NULL, bsd_sa;
77100936Snectar    struct sigaction_args {
78100936Snectar	int sig;
79100936Snectar	struct sigaction *nsa;
80100936Snectar	struct sigaction *osa;
81100936Snectar    } sa;
82100936Snectar    int error;
83100936Snectar
84100936Snectar#ifdef DEBUG
85100936Snectar    printf("Linux-emul(%d): sigaction(%d, *, *)\n", p->p_pid, args->sig);
86100936Snectar#endif
8755714Skris    if (args->osa)
8855714Skris	osa = (struct sigaction *)ua_alloc_init(sizeof(struct sigaction));
8955714Skris
9055714Skris    if (args->nsa) {
9155714Skris	nsa = (struct sigaction *)ua_alloc(sizeof(struct sigaction));
9255714Skris	if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t)))
9355714Skris	    return error;
94109998Smarkm	bsd_sa.sa_mask = linux_to_bsd_sigmask(linux_sa.sa_mask);
9555714Skris	bsd_sa.sa_handler = linux_sa.sa_handler;
9655714Skris	bsd_sa.sa_flags = 0;
9755714Skris	if (linux_sa.sa_flags & LINUX_SA_NOCLDSTOP)
9855714Skris	    bsd_sa.sa_flags |= SA_NOCLDSTOP;
9955714Skris	if (linux_sa.sa_flags & LINUX_SA_ONSTACK)
10055714Skris	    bsd_sa.sa_flags |= SA_ONSTACK;
10155714Skris	if (linux_sa.sa_flags & LINUX_SA_RESTART)
10255714Skris	    bsd_sa.sa_flags |= SA_RESTART;
10355714Skris	if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction)))
10455714Skris	    return error;
10555714Skris    }
10655714Skris    sa.sig = linux_to_bsd_signal[args->sig];
10755714Skris    sa.nsa = nsa;
10855714Skris    sa.osa = osa;
10955714Skris    if ((error = sigaction(p, &sa, retval)))
11055714Skris	return error;
11155714Skris
11255714Skris    if (args->osa) {
11355714Skris	if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction)))
11468651Skris	    return error;
11568651Skris	linux_sa.sa_handler = bsd_sa.sa_handler;
11655714Skris	linux_sa.sa_restorer = NULL;
11755714Skris	linux_sa.sa_mask = bsd_to_linux_sigmask(bsd_sa.sa_mask);
11855714Skris	linux_sa.sa_flags = 0;
11955714Skris	if (bsd_sa.sa_flags & SA_NOCLDSTOP)
12055714Skris	    linux_sa.sa_flags |= LINUX_SA_NOCLDSTOP;
12155714Skris	if (bsd_sa.sa_flags & SA_ONSTACK)
12255714Skris	    linux_sa.sa_flags |= LINUX_SA_ONSTACK;
12355714Skris	if (bsd_sa.sa_flags & SA_RESTART)
12455714Skris	    linux_sa.sa_flags |= LINUX_SA_RESTART;
12555714Skris	if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t)))
12655714Skris	    return error;
12755714Skris    }
12855714Skris    return 0;
12955714Skris}
13055714Skris
13155714Skrisstruct linux_sigprocmask_args {
13255714Skris    int how;
13355714Skris    linux_sigset_t *mask;
13455714Skris    linux_sigset_t *omask;
13555714Skris};
13655714Skris
13755714Skrisint
13855714Skrislinux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
13955714Skris		  int *retval)
14055714Skris{
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