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$"); 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 if (uap->sig <= 0 || uap->sig > IBCS2_NSIG) 210 return (EINVAL); 211 error = kern_sigaction(td, ibcs2_to_bsd_sig[_SIG_IDX(uap->sig)], &nbsa, 212 &obsa, 0); 213 if (error == 0 && uap->oact != NULL) { 214 bsd_to_ibcs2_sigaction(&obsa, &isa); 215 error = copyout(&isa, uap->oact, sizeof(isa)); 216 } 217 return (error); 218} 219 220int 221ibcs2_sigsys(td, uap) 222 register struct thread *td; 223 struct ibcs2_sigsys_args *uap; 224{ 225 struct proc *p = td->td_proc; 226 struct sigaction sa; 227 int signum = IBCS2_SIGNO(uap->sig); 228 int error; 229 230 if (signum <= 0 || signum > IBCS2_NSIG) { 231 if (IBCS2_SIGCALL(uap->sig) == IBCS2_SIGNAL_MASK || 232 IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) 233 td->td_retval[0] = (int)IBCS2_SIG_ERR; 234 return EINVAL; 235 } 236 signum = ibcs2_to_bsd_sig[_SIG_IDX(signum)]; 237 238 switch (IBCS2_SIGCALL(uap->sig)) { 239 case IBCS2_SIGSET_MASK: 240 /* 241 * Check for SIG_HOLD action. 242 * Otherwise, perform signal() except with different sa_flags. 243 */ 244 if (uap->fp != IBCS2_SIG_HOLD) { 245 /* add sig to mask before exececuting signal handler */ 246 sa.sa_flags = 0; 247 goto ibcs2_sigset; 248 } 249 /* else FALLTHROUGH to sighold */ 250 251 case IBCS2_SIGHOLD_MASK: 252 { 253 sigset_t mask; 254 255 SIGEMPTYSET(mask); 256 SIGADDSET(mask, signum); 257 return (kern_sigprocmask(td, SIG_BLOCK, &mask, NULL, 258 0)); 259 } 260 261 case IBCS2_SIGNAL_MASK: 262 { 263 struct sigaction osa; 264 265 /* do not automatically block signal */ 266 sa.sa_flags = SA_NODEFER; 267#ifdef SA_RESETHAND 268 if((signum != IBCS2_SIGILL) && 269 (signum != IBCS2_SIGTRAP) && 270 (signum != IBCS2_SIGPWR)) 271 /* set to SIG_DFL before executing handler */ 272 sa.sa_flags |= SA_RESETHAND; 273#endif 274 ibcs2_sigset: 275 sa.sa_handler = uap->fp; 276 sigemptyset(&sa.sa_mask); 277#if 0 278 if (signum != SIGALRM) 279 sa.sa_flags |= SA_RESTART; 280#endif 281 error = kern_sigaction(td, signum, &sa, &osa, 0); 282 if (error != 0) { 283 DPRINTF(("signal: sigaction failed: %d\n", 284 error)); 285 td->td_retval[0] = (int)IBCS2_SIG_ERR; 286 return (error); 287 } 288 td->td_retval[0] = (int)osa.sa_handler; 289 290 /* special sigset() check */ 291 if(IBCS2_SIGCALL(uap->sig) == IBCS2_SIGSET_MASK) { 292 PROC_LOCK(p); 293 /* check to make sure signal is not blocked */ 294 if(sigismember(&td->td_sigmask, signum)) { 295 /* return SIG_HOLD and unblock signal*/ 296 td->td_retval[0] = (int)IBCS2_SIG_HOLD; 297 SIGDELSET(td->td_sigmask, signum); 298 signotify(td); 299 } 300 PROC_UNLOCK(p); 301 } 302 303 return 0; 304 } 305 306 case IBCS2_SIGRELSE_MASK: 307 { 308 sigset_t mask; 309 310 SIGEMPTYSET(mask); 311 SIGADDSET(mask, signum); 312 return (kern_sigprocmask(td, SIG_UNBLOCK, &mask, NULL, 313 0)); 314 } 315 316 case IBCS2_SIGIGNORE_MASK: 317 { 318 sa.sa_handler = SIG_IGN; 319 sigemptyset(&sa.sa_mask); 320 sa.sa_flags = 0; 321 error = kern_sigaction(td, signum, &sa, NULL, 0); 322 if (error != 0) 323 DPRINTF(("sigignore: sigaction failed\n")); 324 return (error); 325 } 326 327 case IBCS2_SIGPAUSE_MASK: 328 { 329 sigset_t mask; 330 331 PROC_LOCK(p); 332 mask = td->td_sigmask; 333 PROC_UNLOCK(p); 334 SIGDELSET(mask, signum); 335 return kern_sigsuspend(td, mask); 336 } 337 338 default: 339 return ENOSYS; 340 } 341} 342 343int 344ibcs2_sigprocmask(td, uap) 345 register struct thread *td; 346 struct ibcs2_sigprocmask_args *uap; 347{ 348 ibcs2_sigset_t iss; 349 sigset_t oss, nss; 350 sigset_t *nssp; 351 int error, how; 352 353 switch (uap->how) { 354 case IBCS2_SIG_BLOCK: 355 how = SIG_BLOCK; 356 break; 357 case IBCS2_SIG_UNBLOCK: 358 how = SIG_UNBLOCK; 359 break; 360 case IBCS2_SIG_SETMASK: 361 how = SIG_SETMASK; 362 break; 363 default: 364 return (EINVAL); 365 } 366 if (uap->set != NULL) { 367 if ((error = copyin(uap->set, &iss, sizeof(iss))) != 0) 368 return error; 369 ibcs2_to_bsd_sigset(&iss, &nss); 370 nssp = &nss; 371 } else 372 nssp = NULL; 373 error = kern_sigprocmask(td, how, nssp, &oss, 0); 374 if (error == 0 && uap->oset != NULL) { 375 bsd_to_ibcs2_sigset(&oss, &iss); 376 error = copyout(&iss, uap->oset, sizeof(iss)); 377 } 378 return (error); 379} 380 381int 382ibcs2_sigpending(td, uap) 383 register struct thread *td; 384 struct ibcs2_sigpending_args *uap; 385{ 386 struct proc *p = td->td_proc; 387 sigset_t bss; 388 ibcs2_sigset_t iss; 389 390 PROC_LOCK(p); 391 bss = td->td_siglist; 392 SIGSETOR(bss, p->p_siglist); 393 SIGSETAND(bss, td->td_sigmask); 394 PROC_UNLOCK(p); 395 bsd_to_ibcs2_sigset(&bss, &iss); 396 397 return copyout(&iss, uap->mask, sizeof(iss)); 398} 399 400int 401ibcs2_sigsuspend(td, uap) 402 register struct thread *td; 403 struct ibcs2_sigsuspend_args *uap; 404{ 405 ibcs2_sigset_t sss; 406 sigset_t bss; 407 int error; 408 409 if ((error = copyin(uap->mask, &sss, sizeof(sss))) != 0) 410 return error; 411 412 ibcs2_to_bsd_sigset(&sss, &bss); 413 return kern_sigsuspend(td, bss); 414} 415 416int 417ibcs2_pause(td, uap) 418 register struct thread *td; 419 struct ibcs2_pause_args *uap; 420{ 421 sigset_t mask; 422 423 PROC_LOCK(td->td_proc); 424 mask = td->td_sigmask; 425 PROC_UNLOCK(td->td_proc); 426 return kern_sigsuspend(td, mask); 427} 428 429int 430ibcs2_kill(td, uap) 431 register struct thread *td; 432 struct ibcs2_kill_args *uap; 433{ 434 struct kill_args ka; 435 436 if (uap->signo <= 0 || uap->signo > IBCS2_NSIG) 437 return (EINVAL); 438 ka.pid = uap->pid; 439 ka.signum = ibcs2_to_bsd_sig[_SIG_IDX(uap->signo)]; 440 return sys_kill(td, &ka); 441} 442