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