ibcs2_signal.c revision 115684
1/* 2 * Copyright (c) 1995 Scott Bartram 3 * Copyright (c) 1995 Steven Wallace 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 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 without 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 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD: head/sys/i386/ibcs2/ibcs2_signal.c 115684 2003-06-02 06:48:51Z obrien $"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/lock.h> 35#include <sys/mutex.h> 36#include <sys/signalvar.h> 37#include <sys/syscallsubr.h> 38#include <sys/sysproto.h> 39 40#include <i386/ibcs2/ibcs2_types.h> 41#include <i386/ibcs2/ibcs2_signal.h> 42#include <i386/ibcs2/ibcs2_proto.h> 43#include <i386/ibcs2/ibcs2_xenix.h> 44#include <i386/ibcs2/ibcs2_util.h> 45 46#define sigemptyset(s) SIGEMPTYSET(*(s)) 47#define sigismember(s, n) SIGISMEMBER(*(s), n) 48#define sigaddset(s, n) SIGADDSET(*(s), n) 49 50#define ibcs2_sigmask(n) (1 << ((n) - 1)) 51#define ibcs2_sigemptyset(s) bzero((s), sizeof(*(s))) 52#define ibcs2_sigismember(s, n) (*(s) & ibcs2_sigmask(n)) 53#define ibcs2_sigaddset(s, n) (*(s) |= ibcs2_sigmask(n)) 54 55static void ibcs2_to_bsd_sigset(const ibcs2_sigset_t *, sigset_t *); 56static void bsd_to_ibcs2_sigset(const sigset_t *, ibcs2_sigset_t *); 57static void ibcs2_to_bsd_sigaction(struct ibcs2_sigaction *, 58 struct sigaction *); 59static void bsd_to_ibcs2_sigaction(struct sigaction *, 60 struct ibcs2_sigaction *); 61 62int bsd_to_ibcs2_sig[IBCS2_SIGTBLSZ] = { 63 IBCS2_SIGHUP, /* 1 */ 64 IBCS2_SIGINT, /* 2 */ 65 IBCS2_SIGQUIT, /* 3 */ 66 IBCS2_SIGILL, /* 4 */ 67 IBCS2_SIGTRAP, /* 5 */ 68 IBCS2_SIGABRT, /* 6 */ 69 IBCS2_SIGEMT, /* 7 */ 70 IBCS2_SIGFPE, /* 8 */ 71 IBCS2_SIGKILL, /* 9 */ 72 IBCS2_SIGBUS, /* 10 */ 73 IBCS2_SIGSEGV, /* 11 */ 74 IBCS2_SIGSYS, /* 12 */ 75 IBCS2_SIGPIPE, /* 13 */ 76 IBCS2_SIGALRM, /* 14 */ 77 IBCS2_SIGTERM, /* 15 */ 78 0, /* 16 - SIGURG */ 79 IBCS2_SIGSTOP, /* 17 */ 80 IBCS2_SIGTSTP, /* 18 */ 81 IBCS2_SIGCONT, /* 19 */ 82 IBCS2_SIGCLD, /* 20 */ 83 IBCS2_SIGTTIN, /* 21 */ 84 IBCS2_SIGTTOU, /* 22 */ 85 IBCS2_SIGPOLL, /* 23 */ 86 0, /* 24 - SIGXCPU */ 87 0, /* 25 - SIGXFSZ */ 88 IBCS2_SIGVTALRM, /* 26 */ 89 IBCS2_SIGPROF, /* 27 */ 90 IBCS2_SIGWINCH, /* 28 */ 91 0, /* 29 */ 92 IBCS2_SIGUSR1, /* 30 */ 93 IBCS2_SIGUSR2, /* 31 */ 94 0 /* 32 */ 95}; 96 97static int ibcs2_to_bsd_sig[IBCS2_SIGTBLSZ] = { 98 SIGHUP, /* 1 */ 99 SIGINT, /* 2 */ 100 SIGQUIT, /* 3 */ 101 SIGILL, /* 4 */ 102 SIGTRAP, /* 5 */ 103 SIGABRT, /* 6 */ 104 SIGEMT, /* 7 */ 105 SIGFPE, /* 8 */ 106 SIGKILL, /* 9 */ 107 SIGBUS, /* 10 */ 108 SIGSEGV, /* 11 */ 109 SIGSYS, /* 12 */ 110 SIGPIPE, /* 13 */ 111 SIGALRM, /* 14 */ 112 SIGTERM, /* 15 */ 113 SIGUSR1, /* 16 */ 114 SIGUSR2, /* 17 */ 115 SIGCHLD, /* 18 */ 116 0, /* 19 - SIGPWR */ 117 SIGWINCH, /* 20 */ 118 0, /* 21 */ 119 SIGIO, /* 22 */ 120 SIGSTOP, /* 23 */ 121 SIGTSTP, /* 24 */ 122 SIGCONT, /* 25 */ 123 SIGTTIN, /* 26 */ 124 SIGTTOU, /* 27 */ 125 SIGVTALRM, /* 28 */ 126 SIGPROF, /* 29 */ 127 0, /* 30 */ 128 0, /* 31 */ 129 0 /* 32 */ 130}; 131 132void 133ibcs2_to_bsd_sigset(iss, bss) 134 const ibcs2_sigset_t *iss; 135 sigset_t *bss; 136{ 137 int i, newsig; 138 139 sigemptyset(bss); 140 for (i = 1; i <= IBCS2_SIGTBLSZ; i++) { 141 if (ibcs2_sigismember(iss, i)) { 142 newsig = ibcs2_to_bsd_sig[_SIG_IDX(i)]; 143 if (newsig) 144 sigaddset(bss, newsig); 145 } 146 } 147} 148 149static void 150bsd_to_ibcs2_sigset(bss, iss) 151 const sigset_t *bss; 152 ibcs2_sigset_t *iss; 153{ 154 int i, newsig; 155 156 ibcs2_sigemptyset(iss); 157 for (i = 1; i <= IBCS2_SIGTBLSZ; i++) { 158 if (sigismember(bss, i)) { 159 newsig = bsd_to_ibcs2_sig[_SIG_IDX(i)]; 160 if (newsig) 161 ibcs2_sigaddset(iss, newsig); 162 } 163 } 164} 165 166static void 167ibcs2_to_bsd_sigaction(isa, bsa) 168 struct ibcs2_sigaction *isa; 169 struct sigaction *bsa; 170{ 171 172 bsa->sa_handler = isa->isa_handler; 173 ibcs2_to_bsd_sigset(&isa->isa_mask, &bsa->sa_mask); 174 bsa->sa_flags = 0; /* ??? SA_NODEFER */ 175 if ((isa->isa_flags & IBCS2_SA_NOCLDSTOP) != 0) 176 bsa->sa_flags |= SA_NOCLDSTOP; 177} 178 179static void 180bsd_to_ibcs2_sigaction(bsa, isa) 181 struct sigaction *bsa; 182 struct ibcs2_sigaction *isa; 183{ 184 185 isa->isa_handler = bsa->sa_handler; 186 bsd_to_ibcs2_sigset(&bsa->sa_mask, &isa->isa_mask); 187 isa->isa_flags = 0; 188 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) 189 isa->isa_flags |= IBCS2_SA_NOCLDSTOP; 190} 191 192int 193ibcs2_sigaction(td, uap) 194 register struct thread *td; 195 struct ibcs2_sigaction_args *uap; 196{ 197 struct ibcs2_sigaction isa; 198 struct sigaction nbsa, obsa; 199 struct sigaction *nbsap; 200 int error; 201 202 if (uap->act != NULL) { 203 if ((error = copyin(uap->act, &isa, sizeof(isa))) != 0) 204 return (error); 205 ibcs2_to_bsd_sigaction(&isa, &nbsa); 206 nbsap = &nbsa; 207 } else 208 nbsap = NULL; 209 error = kern_sigaction(td, ibcs2_to_bsd_sig[_SIG_IDX(uap->sig)], &nbsa, 210 &obsa, 0); 211 if (error == 0 && uap->oact != NULL) { 212 bsd_to_ibcs2_sigaction(&obsa, &isa); 213 error = copyout(&isa, uap->oact, sizeof(isa)); 214 } 215 return (error); 216} 217 218int 219ibcs2_sigsys(td, uap) 220 register struct thread *td; 221 struct ibcs2_sigsys_args *uap; 222{ 223 struct proc *p = td->td_proc; 224 struct sigaction sa; 225 int signum = ibcs2_to_bsd_sig[_SIG_IDX(IBCS2_SIGNO(uap->sig))]; 226 int error; 227 228 if (signum <= 0 || signum >= IBCS2_NSIG) { 229 if (IBCS2_SIGCALL(uap->sig) == IBCS2_SIGNAL_MASK || 230 IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) 231 td->td_retval[0] = (int)IBCS2_SIG_ERR; 232 return EINVAL; 233 } 234 235 switch (IBCS2_SIGCALL(uap->sig)) { 236 case IBCS2_SIGSET_MASK: 237 /* 238 * Check for SIG_HOLD action. 239 * Otherwise, perform signal() except with different sa_flags. 240 */ 241 if (uap->fp != IBCS2_SIG_HOLD) { 242 /* add sig to mask before exececuting signal handler */ 243 sa.sa_flags = 0; 244 goto ibcs2_sigset; 245 } 246 /* else FALLTHROUGH to sighold */ 247 248 case IBCS2_SIGHOLD_MASK: 249 { 250 sigset_t mask; 251 252 SIGEMPTYSET(mask); 253 SIGADDSET(mask, signum); 254 return (kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, 255 0)); 256 } 257 258 case IBCS2_SIGNAL_MASK: 259 { 260 struct sigaction osa; 261 262 /* do not automatically block signal */ 263 sa.sa_flags = SA_NODEFER; 264#ifdef SA_RESETHAND 265 if((signum != IBCS2_SIGILL) && 266 (signum != IBCS2_SIGTRAP) && 267 (signum != IBCS2_SIGPWR)) 268 /* set to SIG_DFL before executing handler */ 269 sa.sa_flags |= SA_RESETHAND; 270#endif 271 ibcs2_sigset: 272 sa.sa_handler = uap->fp; 273 sigemptyset(&sa.sa_mask); 274#if 0 275 if (signum != SIGALRM) 276 sa.sa_flags |= SA_RESTART; 277#endif 278 error = kern_sigaction(td, signum, &sa, &osa, 0); 279 if (error != 0) { 280 DPRINTF(("signal: sigaction failed: %d\n", 281 error)); 282 td->td_retval[0] = (int)IBCS2_SIG_ERR; 283 return (error); 284 } 285 td->td_retval[0] = (int)osa.sa_handler; 286 287 /* special sigset() check */ 288 if(IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) { 289 PROC_LOCK(p); 290 /* check to make sure signal is not blocked */ 291 if(sigismember(&td->td_sigmask, signum)) { 292 /* return SIG_HOLD and unblock signal*/ 293 td->td_retval[0] = (int)IBCS2_SIG_HOLD; 294 SIGDELSET(td->td_sigmask, signum); 295 signotify(td); 296 } 297 PROC_UNLOCK(p); 298 } 299 300 return 0; 301 } 302 303 case IBCS2_SIGRELSE_MASK: 304 { 305 sigset_t mask; 306 307 SIGEMPTYSET(mask); 308 SIGADDSET(mask, signum); 309 return (kern_sigprocmask(td, SIG_UNBLOCK, &mask, NULL, 310 0)); 311 } 312 313 case IBCS2_SIGIGNORE_MASK: 314 { 315 sa.sa_handler = SIG_IGN; 316 sigemptyset(&sa.sa_mask); 317 sa.sa_flags = 0; 318 error = kern_sigaction(td, signum, &sa, NULL, 0); 319 if (error != 0) 320 DPRINTF(("sigignore: sigaction failed\n")); 321 return (error); 322 } 323 324 case IBCS2_SIGPAUSE_MASK: 325 { 326 sigset_t mask; 327 328 PROC_LOCK(p); 329 mask = td->td_sigmask; 330 PROC_UNLOCK(p); 331 SIGDELSET(mask, signum); 332 return kern_sigsuspend(td, mask); 333 } 334 335 default: 336 return ENOSYS; 337 } 338} 339 340int 341ibcs2_sigprocmask(td, uap) 342 register struct thread *td; 343 struct ibcs2_sigprocmask_args *uap; 344{ 345 ibcs2_sigset_t iss; 346 sigset_t oss, nss; 347 sigset_t *nssp; 348 int error, how; 349 350 switch (uap->how) { 351 case IBCS2_SIG_BLOCK: 352 how = SIG_BLOCK; 353 break; 354 case IBCS2_SIG_UNBLOCK: 355 how = SIG_UNBLOCK; 356 break; 357 case IBCS2_SIG_SETMASK: 358 how = SIG_SETMASK; 359 break; 360 default: 361 return (EINVAL); 362 } 363 if (uap->set != NULL) { 364 if ((error = copyin(uap->set, &iss, sizeof(iss))) != 0) 365 return error; 366 ibcs2_to_bsd_sigset(&iss, &nss); 367 nssp = &nss; 368 } else 369 nssp = NULL; 370 error = kern_sigprocmask(td, how, nssp, &oss, 0); 371 if (error == 0 && uap->oset != NULL) { 372 bsd_to_ibcs2_sigset(&oss, &iss); 373 error = copyout(&iss, uap->oset, sizeof(iss)); 374 } 375 return (error); 376} 377 378int 379ibcs2_sigpending(td, uap) 380 register struct thread *td; 381 struct ibcs2_sigpending_args *uap; 382{ 383 struct proc *p = td->td_proc; 384 sigset_t bss; 385 ibcs2_sigset_t iss; 386 387 PROC_LOCK(p); 388 bss = td->td_siglist; 389 SIGSETOR(bss, p->p_siglist); 390 SIGSETAND(bss, td->td_sigmask); 391 PROC_UNLOCK(p); 392 bsd_to_ibcs2_sigset(&bss, &iss); 393 394 return copyout(&iss, uap->mask, sizeof(iss)); 395} 396 397int 398ibcs2_sigsuspend(td, uap) 399 register struct thread *td; 400 struct ibcs2_sigsuspend_args *uap; 401{ 402 ibcs2_sigset_t sss; 403 sigset_t bss; 404 int error; 405 406 if ((error = copyin(uap->mask, &sss, sizeof(sss))) != 0) 407 return error; 408 409 ibcs2_to_bsd_sigset(&sss, &bss); 410 return kern_sigsuspend(td, bss); 411} 412 413int 414ibcs2_pause(td, uap) 415 register struct thread *td; 416 struct ibcs2_pause_args *uap; 417{ 418 sigset_t mask; 419 420 PROC_LOCK(td->td_proc); 421 mask = td->td_sigmask; 422 PROC_UNLOCK(td->td_proc); 423 return kern_sigsuspend(td, mask); 424} 425 426int 427ibcs2_kill(td, uap) 428 register struct thread *td; 429 struct ibcs2_kill_args *uap; 430{ 431 struct kill_args ka; 432 433 ka.pid = uap->pid; 434 ka.signum = ibcs2_to_bsd_sig[_SIG_IDX(uap->signo)]; 435 return kill(td, &ka); 436} 437