Annotation of sys/compat/linux/linux_signal.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: linux_signal.c,v 1.12 2003/02/25 09:10:27 tedu Exp $ */
! 2: /* $NetBSD: linux_signal.c,v 1.10 1996/04/04 23:51:36 christos Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1995 Frank van der Linden
! 6: * All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. All advertising materials mentioning features or use of this software
! 17: * must display the following acknowledgement:
! 18: * This product includes software developed for the NetBSD Project
! 19: * by Frank van der Linden
! 20: * 4. The name of the author may not be used to endorse or promote products
! 21: * derived from this software without specific prior written permission
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 33: *
! 34: * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
! 35: */
! 36:
! 37: #include <sys/param.h>
! 38: #include <sys/systm.h>
! 39: #include <sys/namei.h>
! 40: #include <sys/proc.h>
! 41: #include <sys/filedesc.h>
! 42: #include <sys/ioctl.h>
! 43: #include <sys/mount.h>
! 44: #include <sys/kernel.h>
! 45: #include <sys/signal.h>
! 46: #include <sys/signalvar.h>
! 47: #include <sys/malloc.h>
! 48:
! 49: #include <sys/syscallargs.h>
! 50:
! 51: #include <compat/linux/linux_types.h>
! 52: #include <compat/linux/linux_signal.h>
! 53: #include <compat/linux/linux_syscallargs.h>
! 54: #include <compat/linux/linux_util.h>
! 55:
! 56: #define sigemptyset(s) bzero((s), sizeof(*(s)))
! 57: #define sigismember(s, n) (*(s) & sigmask(n))
! 58: #define sigaddset(s, n) (*(s) |= sigmask(n))
! 59:
! 60: /* Locally used defines (in bsd<->linux conversion functions): */
! 61: #define linux_sigmask(n) (1 << ((n) - 1))
! 62: #define linux_sigemptyset(s) bzero((s), sizeof(*(s)))
! 63: #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
! 64: & (1 << ((n) - 1) % LINUX__NSIG_BPW))
! 65: #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
! 66: |= (1 << ((n) - 1) % LINUX__NSIG_BPW))
! 67:
! 68: int bsd_to_linux_sig[NSIG] = {
! 69: 0,
! 70: LINUX_SIGHUP,
! 71: LINUX_SIGINT,
! 72: LINUX_SIGQUIT,
! 73: LINUX_SIGILL,
! 74: LINUX_SIGTRAP,
! 75: LINUX_SIGABRT,
! 76: LINUX_NSIG, /* XXX Kludge to get RT signal #32 to work */
! 77: LINUX_SIGFPE,
! 78: LINUX_SIGKILL,
! 79: LINUX_SIGBUS,
! 80: LINUX_SIGSEGV,
! 81: LINUX_NSIG + 1, /* XXX Kludge to get RT signal #32 to work */
! 82: LINUX_SIGPIPE,
! 83: LINUX_SIGALRM,
! 84: LINUX_SIGTERM,
! 85: LINUX_SIGURG,
! 86: LINUX_SIGSTOP,
! 87: LINUX_SIGTSTP,
! 88: LINUX_SIGCONT,
! 89: LINUX_SIGCHLD,
! 90: LINUX_SIGTTIN,
! 91: LINUX_SIGTTOU,
! 92: LINUX_SIGIO,
! 93: LINUX_SIGXCPU,
! 94: LINUX_SIGXFSZ,
! 95: LINUX_SIGVTALRM,
! 96: LINUX_SIGPROF,
! 97: LINUX_SIGWINCH,
! 98: 0, /* SIGINFO */
! 99: LINUX_SIGUSR1,
! 100: LINUX_SIGUSR2,
! 101: };
! 102:
! 103: int linux_to_bsd_sig[LINUX__NSIG] = {
! 104: 0,
! 105: SIGHUP,
! 106: SIGINT,
! 107: SIGQUIT,
! 108: SIGILL,
! 109: SIGTRAP,
! 110: SIGABRT,
! 111: SIGBUS,
! 112: SIGFPE,
! 113: SIGKILL,
! 114: SIGUSR1,
! 115: SIGSEGV,
! 116: SIGUSR2,
! 117: SIGPIPE,
! 118: SIGALRM,
! 119: SIGTERM,
! 120: 0, /* SIGSTKFLT */
! 121: SIGCHLD,
! 122: SIGCONT,
! 123: SIGSTOP,
! 124: SIGTSTP,
! 125: SIGTTIN,
! 126: SIGTTOU,
! 127: SIGURG,
! 128: SIGXCPU,
! 129: SIGXFSZ,
! 130: SIGVTALRM,
! 131: SIGPROF,
! 132: SIGWINCH,
! 133: SIGIO,
! 134: 0, /* SIGUNUSED */
! 135: 0,
! 136: SIGEMT, /* XXX Gruesome hack for linuxthreads: */
! 137: SIGSYS, /* Map 1st 2 RT signals onto ones we handle. */
! 138: 0,
! 139: 0,
! 140: 0,
! 141: 0,
! 142: 0,
! 143: 0,
! 144: 0,
! 145: 0,
! 146: 0,
! 147: 0,
! 148: 0,
! 149: 0,
! 150: 0,
! 151: 0,
! 152: 0,
! 153: 0,
! 154: 0,
! 155: 0,
! 156: 0,
! 157: 0,
! 158: 0,
! 159: 0,
! 160: 0,
! 161: 0,
! 162: 0,
! 163: 0,
! 164: 0,
! 165: 0,
! 166: 0,
! 167: 0,
! 168: };
! 169:
! 170: /*
! 171: * Convert between Linux and BSD signal sets.
! 172: */
! 173: void
! 174: linux_old_to_bsd_sigset(lss, bss)
! 175: const linux_old_sigset_t *lss;
! 176: sigset_t *bss;
! 177: {
! 178: linux_old_extra_to_bsd_sigset(lss, (const unsigned long *) 0, bss);
! 179: }
! 180:
! 181: void
! 182: bsd_to_linux_old_sigset(bss, lss)
! 183: const sigset_t *bss;
! 184: linux_old_sigset_t *lss;
! 185: {
! 186: bsd_to_linux_old_extra_sigset(bss, lss, (unsigned long *) 0);
! 187: }
! 188:
! 189: void
! 190: linux_old_extra_to_bsd_sigset(lss, extra, bss)
! 191: const linux_old_sigset_t *lss;
! 192: const unsigned long *extra;
! 193: sigset_t *bss;
! 194: {
! 195: linux_sigset_t lsnew;
! 196:
! 197: /* convert old sigset to new sigset */
! 198: linux_sigemptyset(&lsnew);
! 199: lsnew.sig[0] = *lss;
! 200: if (extra)
! 201: bcopy(extra, &lsnew.sig[1],
! 202: sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
! 203:
! 204: linux_to_bsd_sigset(&lsnew, bss);
! 205: }
! 206:
! 207: void
! 208: bsd_to_linux_old_extra_sigset(bss, lss, extra)
! 209: const sigset_t *bss;
! 210: linux_old_sigset_t *lss;
! 211: unsigned long *extra;
! 212: {
! 213: linux_sigset_t lsnew;
! 214:
! 215: bsd_to_linux_sigset(bss, &lsnew);
! 216:
! 217: /* convert new sigset to old sigset */
! 218: *lss = lsnew.sig[0];
! 219: if (extra)
! 220: bcopy(&lsnew.sig[1], extra,
! 221: sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t));
! 222: }
! 223:
! 224: void
! 225: linux_to_bsd_sigset(lss, bss)
! 226: const linux_sigset_t *lss;
! 227: sigset_t *bss;
! 228: {
! 229: int i, newsig;
! 230:
! 231: sigemptyset(bss);
! 232: for (i = 1; i < LINUX__NSIG; i++) {
! 233: if (linux_sigismember(lss, i)) {
! 234: newsig = linux_to_bsd_sig[i];
! 235: if (newsig)
! 236: sigaddset(bss, newsig);
! 237: }
! 238: }
! 239: }
! 240:
! 241: void
! 242: bsd_to_linux_sigset(bss, lss)
! 243: const sigset_t *bss;
! 244: linux_sigset_t *lss;
! 245: {
! 246: int i, newsig;
! 247:
! 248: linux_sigemptyset(lss);
! 249: for (i = 1; i < NSIG; i++) {
! 250: if (sigismember(bss, i)) {
! 251: newsig = bsd_to_linux_sig[i];
! 252: if (newsig)
! 253: linux_sigaddset(lss, newsig);
! 254: }
! 255: }
! 256: }
! 257:
! 258: /*
! 259: * Convert between Linux and BSD sigaction structures. Linux has
! 260: * one extra field (sa_restorer) which we don't support.
! 261: */
! 262: void
! 263: linux_old_to_bsd_sigaction(lsa, bsa)
! 264: struct linux_old_sigaction *lsa;
! 265: struct sigaction *bsa;
! 266: {
! 267:
! 268: bsa->sa_handler = lsa->sa__handler;
! 269: linux_old_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
! 270: bsa->sa_flags = 0;
! 271: if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
! 272: bsa->sa_flags |= SA_ONSTACK;
! 273: if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
! 274: bsa->sa_flags |= SA_RESTART;
! 275: if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
! 276: bsa->sa_flags |= SA_RESETHAND;
! 277: if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
! 278: bsa->sa_flags |= SA_NOCLDSTOP;
! 279: if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
! 280: bsa->sa_flags |= SA_NODEFER;
! 281: }
! 282:
! 283: void
! 284: bsd_to_linux_old_sigaction(bsa, lsa)
! 285: struct sigaction *bsa;
! 286: struct linux_old_sigaction *lsa;
! 287: {
! 288:
! 289: lsa->sa__handler = bsa->sa_handler;
! 290: bsd_to_linux_old_sigset(&bsa->sa_mask, &lsa->sa_mask);
! 291: lsa->sa_flags = 0;
! 292: if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
! 293: lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
! 294: if ((bsa->sa_flags & SA_ONSTACK) != 0)
! 295: lsa->sa_flags |= LINUX_SA_ONSTACK;
! 296: if ((bsa->sa_flags & SA_RESTART) != 0)
! 297: lsa->sa_flags |= LINUX_SA_RESTART;
! 298: if ((bsa->sa_flags & SA_NODEFER) != 0)
! 299: lsa->sa_flags |= LINUX_SA_NOMASK;
! 300: if ((bsa->sa_flags & SA_RESETHAND) != 0)
! 301: lsa->sa_flags |= LINUX_SA_ONESHOT;
! 302: lsa->sa_restorer = NULL;
! 303: }
! 304:
! 305: void
! 306: linux_to_bsd_sigaction(lsa, bsa)
! 307: struct linux_sigaction *lsa;
! 308: struct sigaction *bsa;
! 309: {
! 310:
! 311: bsa->sa_handler = lsa->sa__handler;
! 312: linux_to_bsd_sigset(&lsa->sa_mask, &bsa->sa_mask);
! 313: bsa->sa_flags = 0;
! 314: if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0)
! 315: bsa->sa_flags |= SA_NOCLDSTOP;
! 316: if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0)
! 317: bsa->sa_flags |= SA_ONSTACK;
! 318: if ((lsa->sa_flags & LINUX_SA_RESTART) != 0)
! 319: bsa->sa_flags |= SA_RESTART;
! 320: if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0)
! 321: bsa->sa_flags |= SA_RESETHAND;
! 322: if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0)
! 323: bsa->sa_flags |= SA_NODEFER;
! 324: if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0)
! 325: bsa->sa_flags |= SA_SIGINFO;
! 326: }
! 327:
! 328: void
! 329: bsd_to_linux_sigaction(bsa, lsa)
! 330: struct sigaction *bsa;
! 331: struct linux_sigaction *lsa;
! 332: {
! 333:
! 334: /* Clear sa_flags and sa_restorer (if it exists) */
! 335: bzero(lsa, sizeof(struct linux_sigaction));
! 336:
! 337: /* ...and fill in the mask and flags */
! 338: bsd_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask);
! 339: if ((bsa->sa_flags & SA_NOCLDSTOP) != 0)
! 340: lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
! 341: if ((bsa->sa_flags & SA_ONSTACK) != 0)
! 342: lsa->sa_flags |= LINUX_SA_ONSTACK;
! 343: if ((bsa->sa_flags & SA_RESTART) != 0)
! 344: lsa->sa_flags |= LINUX_SA_RESTART;
! 345: if ((bsa->sa_flags & SA_NODEFER) != 0)
! 346: lsa->sa_flags |= LINUX_SA_NOMASK;
! 347: if ((bsa->sa_flags & SA_RESETHAND) != 0)
! 348: lsa->sa_flags |= LINUX_SA_ONESHOT;
! 349: if ((bsa->sa_flags & SA_SIGINFO) != 0)
! 350: lsa->sa_flags |= LINUX_SA_SIGINFO;
! 351: lsa->sa__handler = bsa->sa_handler;
! 352: }
! 353:
! 354: int
! 355: linux_to_bsd_signal(int linuxsig, int *bsdsig)
! 356: {
! 357: if (linuxsig < 0 || linuxsig >= LINUX__NSIG)
! 358: return (EINVAL);
! 359:
! 360: *bsdsig = linux_to_bsd_sig[linuxsig];
! 361: return (0);
! 362: }
! 363:
! 364: int
! 365: bsd_to_linux_signal(int bsdsig, int *linuxsig)
! 366: {
! 367: if (bsdsig < 0 || bsdsig >= NSIG)
! 368: return (EINVAL);
! 369:
! 370: *linuxsig = bsd_to_linux_sig[bsdsig];
! 371: return (0);
! 372: }
! 373:
! 374: /*
! 375: * The Linux sigaction() system call. Do the usual conversions,
! 376: * and just call sigaction(). Some flags and values are silently
! 377: * ignored (see above).
! 378: */
! 379: int
! 380: linux_sys_sigaction(p, v, retval)
! 381: register struct proc *p;
! 382: void *v;
! 383: register_t *retval;
! 384: {
! 385: struct linux_sys_sigaction_args /* {
! 386: syscallarg(int) signum;
! 387: syscallarg(struct linux_old_sigaction *) nsa;
! 388: syscallarg(struct linux_old_sigaction *) osa;
! 389: } */ *uap = v;
! 390: struct linux_old_sigaction *nlsa, *olsa, tmplsa;
! 391: struct sigaction *nbsa, *obsa, tmpbsa;
! 392: struct sys_sigaction_args sa;
! 393: caddr_t sg;
! 394: int error;
! 395:
! 396: if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
! 397: return (EINVAL);
! 398:
! 399: sg = stackgap_init(p->p_emul);
! 400: nlsa = SCARG(uap, nsa);
! 401: olsa = SCARG(uap, osa);
! 402:
! 403: if (olsa != NULL)
! 404: obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
! 405: else
! 406: obsa = NULL;
! 407:
! 408: if (nlsa != NULL) {
! 409: nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
! 410: if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
! 411: return (error);
! 412: linux_old_to_bsd_sigaction(&tmplsa, &tmpbsa);
! 413: if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
! 414: return (error);
! 415: } else
! 416: nbsa = NULL;
! 417:
! 418: SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
! 419: SCARG(&sa, nsa) = nbsa;
! 420: SCARG(&sa, osa) = obsa;
! 421:
! 422: /* Silently ignore unknown signals */
! 423: if (SCARG(&sa, signum) == 0) {
! 424: if (obsa != NULL) {
! 425: obsa->sa_handler = SIG_IGN;
! 426: sigemptyset(&obsa->sa_mask);
! 427: obsa->sa_flags = 0;
! 428: }
! 429: }
! 430: else {
! 431: if ((error = sys_sigaction(p, &sa, retval)) != 0)
! 432: return (error);
! 433: }
! 434:
! 435: if (olsa != NULL) {
! 436: if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
! 437: return (error);
! 438: bsd_to_linux_old_sigaction(&tmpbsa, &tmplsa);
! 439: if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
! 440: return (error);
! 441: }
! 442:
! 443: return (0);
! 444: }
! 445:
! 446: int
! 447: linux_sys_rt_sigaction(p, v, retval)
! 448: register struct proc *p;
! 449: void *v;
! 450: register_t *retval;
! 451: {
! 452: struct linux_sys_rt_sigaction_args /* {
! 453: syscallarg(int) signum;
! 454: syscallarg(struct linux_sigaction *) nsa;
! 455: syscallarg(struct linux_sigaction *) osa;
! 456: syscallarg(size_t) sigsetsize;
! 457: } */ *uap = v;
! 458: struct linux_sigaction *nlsa, *olsa, tmplsa;
! 459: struct sigaction *nbsa, *obsa, tmpbsa;
! 460: struct sys_sigaction_args sa;
! 461: caddr_t sg;
! 462: int error;
! 463:
! 464: if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
! 465: return (EINVAL);
! 466:
! 467: if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
! 468: return (EINVAL);
! 469:
! 470: sg = stackgap_init(p->p_emul);
! 471: nlsa = SCARG(uap, nsa);
! 472: olsa = SCARG(uap, osa);
! 473:
! 474: if (olsa != NULL)
! 475: obsa = stackgap_alloc(&sg, sizeof(struct sigaction));
! 476: else
! 477: obsa = NULL;
! 478:
! 479: if (nlsa != NULL) {
! 480: nbsa = stackgap_alloc(&sg, sizeof(struct sigaction));
! 481: if ((error = copyin(nlsa, &tmplsa, sizeof(tmplsa))) != 0)
! 482: return (error);
! 483: linux_to_bsd_sigaction(&tmplsa, &tmpbsa);
! 484: if ((error = copyout(&tmpbsa, nbsa, sizeof(tmpbsa))) != 0)
! 485: return (error);
! 486: }
! 487: else
! 488: nbsa = NULL;
! 489:
! 490: SCARG(&sa, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
! 491: SCARG(&sa, nsa) = nbsa;
! 492: SCARG(&sa, osa) = obsa;
! 493:
! 494: /* Silently ignore unknown signals */
! 495: if (SCARG(&sa, signum) == 0) {
! 496: if (obsa != NULL) {
! 497: obsa->sa_handler = SIG_IGN;
! 498: sigemptyset(&obsa->sa_mask);
! 499: obsa->sa_flags = 0;
! 500: }
! 501: }
! 502: else {
! 503: if ((error = sys_sigaction(p, &sa, retval)) != 0)
! 504: return (error);
! 505: }
! 506:
! 507: if (olsa != NULL) {
! 508: if ((error = copyin(obsa, &tmpbsa, sizeof(tmpbsa))) != 0)
! 509: return (error);
! 510: bsd_to_linux_sigaction(&tmpbsa, &tmplsa);
! 511: if ((error = copyout(&tmplsa, olsa, sizeof(tmplsa))) != 0)
! 512: return (error);
! 513: }
! 514:
! 515: return (0);
! 516: }
! 517:
! 518: /*
! 519: * The Linux signal() system call. I think that the signal() in the C
! 520: * library actually calls sigaction, so I doubt this one is ever used.
! 521: * But hey, it can't hurt having it here. The same restrictions as for
! 522: * sigaction() apply.
! 523: */
! 524: int
! 525: linux_sys_signal(p, v, retval)
! 526: register struct proc *p;
! 527: void *v;
! 528: register_t *retval;
! 529: {
! 530: struct linux_sys_signal_args /* {
! 531: syscallarg(int) sig;
! 532: syscallarg(linux_handler_t) handler;
! 533: } */ *uap = v;
! 534: caddr_t sg;
! 535: struct sys_sigaction_args sa_args;
! 536: struct sigaction *osa, *nsa, tmpsa;
! 537: int error;
! 538:
! 539: if (SCARG(uap, sig) < 0 || SCARG(uap, sig) >= LINUX__NSIG)
! 540: return (EINVAL);
! 541:
! 542: sg = stackgap_init(p->p_emul);
! 543: nsa = stackgap_alloc(&sg, sizeof *nsa);
! 544: osa = stackgap_alloc(&sg, sizeof *osa);
! 545:
! 546: tmpsa.sa_handler = SCARG(uap, handler);
! 547: tmpsa.sa_mask = (sigset_t) 0;
! 548: tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
! 549: if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
! 550: return (error);
! 551:
! 552: SCARG(&sa_args, signum) = linux_to_bsd_sig[SCARG(uap, sig)];
! 553: SCARG(&sa_args, osa) = osa;
! 554: SCARG(&sa_args, nsa) = nsa;
! 555:
! 556: /* Silently ignore unknown signals */
! 557: if (SCARG(&sa_args, signum) != 0) {
! 558: if ((error = sys_sigaction(p, &sa_args, retval)))
! 559: return (error);
! 560: }
! 561:
! 562: if ((error = copyin(osa, &tmpsa, sizeof *osa)))
! 563: return (error);
! 564: retval[0] = (register_t) tmpsa.sa_handler;
! 565:
! 566: return (0);
! 567: }
! 568:
! 569: /*
! 570: * This is just a copy of the svr4 compat one. I feel so creative now.
! 571: */
! 572: int
! 573: linux_sys_sigprocmask(p, v, retval)
! 574: register struct proc *p;
! 575: void *v;
! 576: register_t *retval;
! 577: {
! 578: struct linux_sys_sigprocmask_args /* {
! 579: syscallarg(int) how;
! 580: syscallarg(linux_old_sigset_t *) set;
! 581: syscallarg(linux_old_sigset_t *) oset;
! 582: } */ *uap = v;
! 583: linux_old_sigset_t ss;
! 584: sigset_t bs;
! 585: int error = 0;
! 586:
! 587: *retval = 0;
! 588:
! 589: if (SCARG(uap, oset) != NULL) {
! 590: /* Fix the return value first if needed */
! 591: bsd_to_linux_old_sigset(&p->p_sigmask, &ss);
! 592: if ((error = copyout(&ss, SCARG(uap, oset), sizeof(ss))) != 0)
! 593: return (error);
! 594: }
! 595:
! 596: if (SCARG(uap, set) == NULL)
! 597: /* Just examine */
! 598: return (0);
! 599:
! 600: if ((error = copyin(SCARG(uap, set), &ss, sizeof(ss))) != 0)
! 601: return (error);
! 602:
! 603: linux_old_to_bsd_sigset(&ss, &bs);
! 604:
! 605: (void) splhigh();
! 606:
! 607: switch (SCARG(uap, how)) {
! 608: case LINUX_SIG_BLOCK:
! 609: p->p_sigmask |= bs & ~sigcantmask;
! 610: break;
! 611:
! 612: case LINUX_SIG_UNBLOCK:
! 613: p->p_sigmask &= ~bs;
! 614: break;
! 615:
! 616: case LINUX_SIG_SETMASK:
! 617: p->p_sigmask = bs & ~sigcantmask;
! 618: break;
! 619:
! 620: default:
! 621: error = EINVAL;
! 622: break;
! 623: }
! 624:
! 625: (void) spl0();
! 626:
! 627: return (error);
! 628: }
! 629:
! 630: int
! 631: linux_sys_rt_sigprocmask(p, v, retval)
! 632: register struct proc *p;
! 633: void *v;
! 634: register_t *retval;
! 635: {
! 636: struct linux_sys_rt_sigprocmask_args /* {
! 637: syscallarg(int) how;
! 638: syscallarg(const linux_sigset_t *) set;
! 639: syscallarg(linux_sigset_t *) oset;
! 640: syscallarg(size_t) sigsetsize;
! 641: } */ *uap = v;
! 642: linux_sigset_t ls;
! 643: sigset_t bs;
! 644: int error = 0;
! 645:
! 646: if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
! 647: return (EINVAL);
! 648:
! 649: *retval = 0;
! 650:
! 651: if (SCARG(uap, oset) != NULL) {
! 652: /* Fix the return value first if needed */
! 653: bsd_to_linux_sigset(&p->p_sigmask, &ls);
! 654: if ((error = copyout(&ls, SCARG(uap, oset), sizeof(ls))) != 0)
! 655: return (error);
! 656: }
! 657:
! 658: if (SCARG(uap, set) == NULL)
! 659: /* Just examine */
! 660: return (0);
! 661:
! 662: if ((error = copyin(SCARG(uap, set), &ls, sizeof(ls))) != 0)
! 663: return (error);
! 664:
! 665: linux_to_bsd_sigset(&ls, &bs);
! 666:
! 667: (void) splhigh();
! 668:
! 669: switch (SCARG(uap, how)) {
! 670: case LINUX_SIG_BLOCK:
! 671: p->p_sigmask |= bs & ~sigcantmask;
! 672: break;
! 673:
! 674: case LINUX_SIG_UNBLOCK:
! 675: p->p_sigmask &= ~bs;
! 676: break;
! 677:
! 678: case LINUX_SIG_SETMASK:
! 679: p->p_sigmask = bs & ~sigcantmask;
! 680: break;
! 681:
! 682: default:
! 683: error = EINVAL;
! 684: break;
! 685: }
! 686:
! 687: (void) spl0();
! 688:
! 689: return (error);
! 690: }
! 691:
! 692: /*
! 693: * The functions below really make no distinction between an int
! 694: * and [linux_]sigset_t. This is ok for now, but it might break
! 695: * sometime. Then again, sigset_t is trusted to be an int everywhere
! 696: * else in the kernel too.
! 697: */
! 698: /* ARGSUSED */
! 699: int
! 700: linux_sys_siggetmask(p, v, retval)
! 701: register struct proc *p;
! 702: void *v;
! 703: register_t *retval;
! 704: {
! 705:
! 706: bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
! 707: return (0);
! 708: }
! 709:
! 710: /*
! 711: * The following three functions fiddle with a process' signal mask.
! 712: * Convert the signal masks because of the different signal
! 713: * values for Linux. The need for this is the reason why
! 714: * they are here, and have not been mapped directly.
! 715: */
! 716: int
! 717: linux_sys_sigsetmask(p, v, retval)
! 718: register struct proc *p;
! 719: void *v;
! 720: register_t *retval;
! 721: {
! 722: struct linux_sys_sigsetmask_args /* {
! 723: syscallarg(linux_old_sigset_t) mask;
! 724: } */ *uap = v;
! 725: linux_old_sigset_t mask;
! 726: sigset_t bsdsig;
! 727:
! 728: bsd_to_linux_old_sigset(&p->p_sigmask, (linux_old_sigset_t *)retval);
! 729:
! 730: mask = SCARG(uap, mask);
! 731: bsd_to_linux_old_sigset(&bsdsig, &mask);
! 732:
! 733: splhigh();
! 734: p->p_sigmask = bsdsig & ~sigcantmask;
! 735: spl0();
! 736:
! 737: return (0);
! 738: }
! 739:
! 740: int
! 741: linux_sys_sigpending(p, v, retval)
! 742: register struct proc *p;
! 743: void *v;
! 744: register_t *retval;
! 745: {
! 746: struct linux_sys_sigpending_args /* {
! 747: syscallarg(linux_old_sigset_t *) mask;
! 748: } */ *uap = v;
! 749: sigset_t bs;
! 750: linux_old_sigset_t ls;
! 751:
! 752: bs = p->p_siglist & p->p_sigmask;
! 753: bsd_to_linux_old_sigset(&bs, &ls);
! 754:
! 755: return (copyout(&ls, SCARG(uap, mask), sizeof ls));
! 756: }
! 757:
! 758: int
! 759: linux_sys_rt_sigpending(p, v, retval)
! 760: register struct proc *p;
! 761: void *v;
! 762: register_t *retval;
! 763: {
! 764: struct linux_sys_rt_sigpending_args /* {
! 765: syscallarg(linux_sigset_t *) set;
! 766: syscallarg(size_t) sigsetsize;
! 767: } */ *uap = v;
! 768: sigset_t bs;
! 769: linux_sigset_t ls;
! 770:
! 771: if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
! 772: return (EINVAL);
! 773:
! 774: bs = p->p_siglist & p->p_sigmask;
! 775: bsd_to_linux_sigset(&bs, &ls);
! 776:
! 777: return (copyout(&ls, SCARG(uap, set), sizeof ls));
! 778: }
! 779:
! 780: int
! 781: linux_sys_sigsuspend(p, v, retval)
! 782: register struct proc *p;
! 783: void *v;
! 784: register_t *retval;
! 785: {
! 786: struct linux_sys_sigsuspend_args /* {
! 787: syscallarg(caddr_t) restart;
! 788: syscallarg(int) oldmask;
! 789: syscallarg(int) mask;
! 790: } */ *uap = v;
! 791: struct sys_sigsuspend_args sa;
! 792: linux_old_sigset_t mask = SCARG(uap, mask);
! 793:
! 794: linux_old_to_bsd_sigset(&mask, &SCARG(&sa, mask));
! 795: return (sys_sigsuspend(p, &sa, retval));
! 796: }
! 797:
! 798: int
! 799: linux_sys_rt_sigsuspend(p, v, retval)
! 800: register struct proc *p;
! 801: void *v;
! 802: register_t *retval;
! 803: {
! 804: struct linux_sys_rt_sigsuspend_args /* {
! 805: syscallarg(sigset_t *) unewset;
! 806: syscallarg(size_t) sigsetsize;
! 807: } */ *uap = v;
! 808: struct sys_sigsuspend_args sa;
! 809: linux_sigset_t mask;
! 810: int error;
! 811:
! 812: if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t))
! 813: return (EINVAL);
! 814:
! 815: error = copyin(SCARG(uap, unewset), &mask, sizeof mask);
! 816: if (error)
! 817: return (error);
! 818:
! 819: linux_to_bsd_sigset(&mask, &SCARG(&sa, mask));
! 820: return (sys_sigsuspend(p, &sa, retval));
! 821: }
! 822:
! 823: /*
! 824: * Linux' sigaltstack structure is just of a different order than BSD's
! 825: * so just shuffle the fields around and call our version.
! 826: */
! 827: int
! 828: linux_sys_sigaltstack(p, v, retval)
! 829: register struct proc *p;
! 830: void *v;
! 831: register_t *retval;
! 832: {
! 833: struct linux_sys_sigaltstack_args /* {
! 834: syscallarg(const struct linux_sigaltstack *) nss;
! 835: syscallarg(struct linux_sigaltstack *) oss;
! 836: } */ *uap = v;
! 837: struct linux_sigaltstack linux_ss;
! 838: struct sigaltstack *bsd_nss, *bsd_oss;
! 839: struct sys_sigaltstack_args sa;
! 840: int error;
! 841: caddr_t sg;
! 842:
! 843: sg = stackgap_init(p->p_emul);
! 844:
! 845: if (SCARG(uap, nss) != NULL) {
! 846: bsd_nss = stackgap_alloc(&sg, sizeof *bsd_nss);
! 847:
! 848: error = copyin(SCARG(uap, nss), &linux_ss, sizeof linux_ss);
! 849: if (error)
! 850: return (error);
! 851:
! 852: bsd_nss->ss_sp = linux_ss.ss_sp;
! 853: bsd_nss->ss_size = linux_ss.ss_size;
! 854: bsd_nss->ss_flags = (linux_ss.ss_flags & LINUX_SS_DISABLE) ?
! 855: SS_DISABLE : 0;
! 856:
! 857: SCARG(&sa, nss) = bsd_nss;
! 858: } else
! 859: SCARG(&sa, nss) = NULL;
! 860:
! 861: if (SCARG(uap, oss) == NULL) {
! 862: SCARG(&sa, oss) = NULL;
! 863: return (sys_sigaltstack(p, &sa, retval));
! 864: }
! 865: SCARG(&sa, oss) = bsd_oss = stackgap_alloc(&sg, sizeof *bsd_oss);
! 866:
! 867: error = sys_sigaltstack(p, &sa, retval);
! 868: if (error)
! 869: return (error);
! 870:
! 871: linux_ss.ss_sp = bsd_oss->ss_sp;
! 872: linux_ss.ss_size = bsd_oss->ss_size;
! 873: linux_ss.ss_flags = 0;
! 874: if (bsd_oss->ss_flags & SS_ONSTACK)
! 875: linux_ss.ss_flags |= LINUX_SS_ONSTACK;
! 876: if (bsd_oss->ss_flags & SS_DISABLE)
! 877: linux_ss.ss_flags |= LINUX_SS_DISABLE;
! 878: return (copyout(&linux_ss, SCARG(uap, oss), sizeof linux_ss));
! 879: }
! 880:
! 881: /*
! 882: * The deprecated pause(2), which is really just an instance
! 883: * of sigsuspend(2).
! 884: */
! 885: int
! 886: linux_sys_pause(p, v, retval)
! 887: register struct proc *p;
! 888: void *v;
! 889: register_t *retval;
! 890: {
! 891: struct sys_sigsuspend_args bsa;
! 892:
! 893: SCARG(&bsa, mask) = p->p_sigmask;
! 894: return (sys_sigsuspend(p, &bsa, retval));
! 895: }
! 896:
! 897: /*
! 898: * Once more: only a signal conversion is needed.
! 899: */
! 900: int
! 901: linux_sys_kill(p, v, retval)
! 902: register struct proc *p;
! 903: void *v;
! 904: register_t *retval;
! 905: {
! 906: struct linux_sys_kill_args /* {
! 907: syscallarg(int) pid;
! 908: syscallarg(int) signum;
! 909: } */ *uap = v;
! 910: struct sys_kill_args ka;
! 911:
! 912: SCARG(&ka, pid) = SCARG(uap, pid);
! 913: if (SCARG(uap, signum) < 0 || SCARG(uap, signum) >= LINUX__NSIG)
! 914: return (EINVAL);
! 915: SCARG(&ka, signum) = linux_to_bsd_sig[SCARG(uap, signum)];
! 916: return (sys_kill(p, &ka, retval));
! 917: }
CVSweb