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