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