int sigvec(int sig, struct sigvec *nvec, struct sigvec *ovec) { struct sigaction nact; struct sigaction oact; struct sigaction *nactp; void (*ohandler)(), (*nhandler)(); if (sig <= 0 || sig >= NSIG) { errno = EINVAL; return -1; } ohandler = _siguhandler[sig]; if (nvec) { _sigaction(sig, (struct sigaction *)0, &nact); nhandler = nvec->sv_handler; _siguhandler[sig] = nhandler; if (nhandler != SIG_DFL && nhandler != SIG_IGN) nact.sa_handler = (void (*)())sigvechandler; else nact.sa_handler = nhandler; mask2set(nvec->sv_mask, &nact.sa_mask); /* if ( sig == SIGTSTP || sig == SIGSTOP ) nact.sa_handler = SIG_DFL; */ nact.sa_flags = SA_SIGINFO; if (!(nvec->sv_flags & SV_INTERRUPT)) nact.sa_flags |= SA_RESTART; if (nvec->sv_flags & SV_RESETHAND) nact.sa_flags |= SA_RESETHAND; if (nvec->sv_flags & SV_ONSTACK) nact.sa_flags |= SA_ONSTACK; nactp = &nact; } else nactp = (struct sigaction *)0; if (_sigaction(sig, nactp, &oact) < 0) { _siguhandler[sig] = ohandler; return -1; } if (ovec) { if (oact.sa_handler == SIG_DFL || oact.sa_handler == SIG_IGN) ovec->sv_handler = oact.sa_handler; else ovec->sv_handler = ohandler; ovec->sv_mask = set2mask(&oact.sa_mask); ovec->sv_flags = 0; if (oact.sa_flags & SA_ONSTACK) ovec->sv_flags |= SV_ONSTACK; if (oact.sa_flags & SA_RESETHAND) ovec->sv_flags |= SV_RESETHAND; if (!(oact.sa_flags & SA_RESTART)) ovec->sv_flags |= SV_INTERRUPT; } return 0; }
static void sigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp) { struct sigcontext sc; int code; char *addr; int i, j; int gwinswitch = 0; sc.sc_onstack = ((ucp->uc_stack.ss_flags & SS_ONSTACK) != 0); sc.sc_mask = set2mask(&ucp->uc_sigmask); /* * Machine dependent code begins */ sc.sc_sp = (int) ucp->uc_mcontext.gregs[UESP]; sc.sc_pc = (int) ucp->uc_mcontext.gregs[EIP]; sc.sc_ps = (int) ucp->uc_mcontext.gregs[EFL]; sc.sc_eax = (int) ucp->uc_mcontext.gregs[EAX]; sc.sc_edx = (int) ucp->uc_mcontext.gregs[EDX]; /* * Machine dependent code ends */ if (sip != NULL) if ((code = sip->si_code) == BUS_OBJERR) code = SEGV_MAKE_ERR(sip->si_errno); if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) if (sip != NULL) addr = (char *)sip->si_addr; else addr = SIG_NOADDR; (*_siguhandler[sig])(sig, code, &sc, addr); if (sc.sc_onstack) ucp->uc_stack.ss_flags |= SS_ONSTACK; else ucp->uc_stack.ss_flags &= ~SS_ONSTACK; mask2set(sc.sc_mask, &ucp->uc_sigmask); /* * Machine dependent code begins */ ucp->uc_mcontext.gregs[UESP] = (int) sc.sc_sp; ucp->uc_mcontext.gregs[EIP] = (int) sc.sc_pc; ucp->uc_mcontext.gregs[EFL] = (int) sc.sc_ps; ucp->uc_mcontext.gregs[EAX] = (int) sc.sc_eax; ucp->uc_mcontext.gregs[EDX] = (int) sc.sc_edx; /* * Machine dependent code ends */ setcontext (ucp); }
static int sigblock(int mask) { sigset_t oset; sigset_t nset; (void) sigprocmask(0, NULL, &nset); mask2set(mask, &nset); (void) sigprocmask(SIG_BLOCK, &nset, &oset); return (set2mask(&oset)); }
int sigblock(int mask) { sigset_t oset; sigset_t nset; (void) sigprocmask(0, (sigset_t *)0, &nset); mask2set(mask, &nset); (void) sigprocmask(SIG_BLOCK, &nset, &oset); return set2mask(&oset); }
int ucbsigsetmask(int mask) { sigset_t oset; sigset_t nset; (void) sigprocmask(0, (sigset_t *)0, &nset); mask2set(mask, &nset); (void) sigprocmask(SIG_SETMASK, &nset, &oset); return (set2mask(&oset)); }
static void ucbsigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp) { struct sigcontext sc; int code; char *addr; int i, j; int gwinswitch = 0; sc.sc_onstack = ((ucp->uc_stack.ss_flags & SS_ONSTACK) != 0); sc.sc_mask = set2mask(&ucp->uc_sigmask); #if defined(__amd64) sc.sc_sp = (long)ucp->uc_mcontext.gregs[REG_RSP]; sc.sc_pc = (long)ucp->uc_mcontext.gregs[REG_RIP]; sc.sc_ps = (long)ucp->uc_mcontext.gregs[REG_RFL]; sc.sc_r0 = (long)ucp->uc_mcontext.gregs[REG_RAX]; sc.sc_r1 = (long)ucp->uc_mcontext.gregs[REG_RDX]; #else sc.sc_sp = (int)ucp->uc_mcontext.gregs[UESP]; sc.sc_pc = (int)ucp->uc_mcontext.gregs[EIP]; sc.sc_ps = (int)ucp->uc_mcontext.gregs[EFL]; sc.sc_r0 = (int)ucp->uc_mcontext.gregs[EAX]; sc.sc_r1 = (int)ucp->uc_mcontext.gregs[EDX]; #endif /* * Translate signal codes from new to old. * /usr/include/sys/siginfo.h contains new codes. * /usr/ucbinclude/sys/signal.h contains old codes. */ code = 0; addr = SIG_NOADDR; if (sip != NULL && SI_FROMKERNEL(sip)) { addr = sip->si_addr; switch (sig) { case SIGILL: case SIGFPE: code = ILL_ILLINSTR_FAULT; break; case SIGBUS: switch (sip->si_code) { case BUS_ADRALN: code = BUS_ALIGN; break; case BUS_ADRERR: code = BUS_HWERR; break; default: /* BUS_OBJERR */ code = FC_MAKE_ERR(sip->si_errno); break; } break; case SIGSEGV: switch (sip->si_code) { case SEGV_MAPERR: code = SEGV_NOMAP; break; case SEGV_ACCERR: code = SEGV_PROT; break; default: code = FC_MAKE_ERR(sip->si_errno); break; } break; default: addr = SIG_NOADDR; break; } } (*_siguhandler[sig])(sig, code, &sc, addr); if (sc.sc_onstack) ucp->uc_stack.ss_flags |= SS_ONSTACK; else ucp->uc_stack.ss_flags &= ~SS_ONSTACK; mask2set(sc.sc_mask, &ucp->uc_sigmask); #if defined(__amd64) ucp->uc_mcontext.gregs[REG_RSP] = (long)sc.sc_sp; ucp->uc_mcontext.gregs[REG_RIP] = (long)sc.sc_pc; ucp->uc_mcontext.gregs[REG_RFL] = (long)sc.sc_ps; ucp->uc_mcontext.gregs[REG_RAX] = (long)sc.sc_r0; ucp->uc_mcontext.gregs[REG_RDX] = (long)sc.sc_r1; #else ucp->uc_mcontext.gregs[UESP] = (int)sc.sc_sp; ucp->uc_mcontext.gregs[EIP] = (int)sc.sc_pc; ucp->uc_mcontext.gregs[EFL] = (int)sc.sc_ps; ucp->uc_mcontext.gregs[EAX] = (int)sc.sc_r0; ucp->uc_mcontext.gregs[EDX] = (int)sc.sc_r1; #endif setcontext(ucp); }
int ucbsigvec(int sig, struct sigvec *nvec, struct sigvec *ovec) { struct sigaction nact; struct sigaction oact; struct sigaction *nactp; void (*ohandler)(), (*nhandler)(); if (sig <= 0 || sig >= NSIG) { errno = EINVAL; return (-1); } if ((intptr_t)ovec == -1 || (intptr_t)nvec == -1) { errno = EFAULT; return (-1); } ohandler = _siguhandler[sig]; if (nvec) { _sigaction(sig, (struct sigaction *)0, &nact); nhandler = nvec->sv_handler; /* * To be compatible with the behavior of SunOS 4.x: * If the new signal handler is SIG_IGN or SIG_DFL, * do not change the signal's entry in the handler array. * This allows a child of vfork(2) to set signal handlers * to SIG_IGN or SIG_DFL without affecting the parent. */ if (nhandler != SIG_DFL && nhandler != SIG_IGN) { _siguhandler[sig] = nhandler; nact.sa_handler = (void (*)())ucbsigvechandler; } else { nact.sa_handler = nhandler; } mask2set(nvec->sv_mask, &nact.sa_mask); if (sig == SIGKILL || sig == SIGSTOP) nact.sa_handler = SIG_DFL; nact.sa_flags = SA_SIGINFO; if (!(nvec->sv_flags & SV_INTERRUPT)) nact.sa_flags |= SA_RESTART; if (nvec->sv_flags & SV_RESETHAND) nact.sa_flags |= SA_RESETHAND; if (nvec->sv_flags & SV_ONSTACK) nact.sa_flags |= SA_ONSTACK; nactp = &nact; } else nactp = (struct sigaction *)0; if (_sigaction(sig, nactp, &oact) < 0) { _siguhandler[sig] = ohandler; return (-1); } if (ovec) { if (oact.sa_handler == SIG_DFL || oact.sa_handler == SIG_IGN) ovec->sv_handler = oact.sa_handler; else ovec->sv_handler = ohandler; ovec->sv_mask = set2mask(&oact.sa_mask); ovec->sv_flags = 0; if (oact.sa_flags & SA_ONSTACK) ovec->sv_flags |= SV_ONSTACK; if (oact.sa_flags & SA_RESETHAND) ovec->sv_flags |= SV_RESETHAND; if (!(oact.sa_flags & SA_RESTART)) ovec->sv_flags |= SV_INTERRUPT; } return (0); }
static void ucbsigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp) { struct sigcontext sc; int code; char *addr; #ifdef NEVER int gwinswitch = 0; #endif sc.sc_onstack = ((ucp->uc_stack.ss_flags & SS_ONSTACK) != 0); sc.sc_mask = set2mask(&ucp->uc_sigmask); #if defined(__sparc) if (sig == SIGFPE && sip != NULL && SI_FROMKERNEL(sip) && (sip->si_code == FPE_INTDIV || sip->si_code == FPE_INTOVF)) { /* * Hack to emulate the 4.x kernel behavior of incrementing * the PC on integer divide by zero and integer overflow * on sparc machines. (5.x does not increment the PC.) */ ucp->uc_mcontext.gregs[REG_PC] = ucp->uc_mcontext.gregs[REG_nPC]; ucp->uc_mcontext.gregs[REG_nPC] += 4; } sc.sc_sp = ucp->uc_mcontext.gregs[REG_SP]; sc.sc_pc = ucp->uc_mcontext.gregs[REG_PC]; sc.sc_npc = ucp->uc_mcontext.gregs[REG_nPC]; /* XX64 There is no REG_PSR for sparcv9, we map in REG_CCR for now */ #if defined(__sparcv9) sc.sc_psr = ucp->uc_mcontext.gregs[REG_CCR]; #else sc.sc_psr = ucp->uc_mcontext.gregs[REG_PSR]; #endif sc.sc_g1 = ucp->uc_mcontext.gregs[REG_G1]; sc.sc_o0 = ucp->uc_mcontext.gregs[REG_O0]; /* * XXX - What a kludge! * Store a pointer to the original ucontext_t in the sigcontext * so that it's available to the sigcleanup call that needs to * return from the signal handler. Otherwise, vital information * (e.g., the "out" registers) that's only saved in the * ucontext_t isn't available to sigcleanup. */ sc.sc_wbcnt = (int)(sizeof (*ucp)); sc.sc_spbuf[0] = (char *)(uintptr_t)sig; sc.sc_spbuf[1] = (char *)ucp; #ifdef NEVER /* * XXX - Sorry, we can never pass the saved register windows * on in the sigcontext because we use that space to save the * ucontext_t. */ if (ucp->uc_mcontext.gwins != (gwindows_t *)0) { int i, j; gwinswitch = 1; sc.sc_wbcnt = ucp->uc_mcontext.gwins->wbcnt; /* XXX - should use bcopy to move this in bulk */ for (i = 0; i < ucp->uc_mcontext.gwins; i++) { sc.sc_spbuf[i] = ucp->uc_mcontext.gwins->spbuf[i]; for (j = 0; j < 8; j++) sc.sc_wbuf[i][j] = ucp->uc_mcontext.gwins->wbuf[i].rw_local[j]; for (j = 0; j < 8; j++) sc.sc_wbuf[i][j+8] = ucp->uc_mcontext.gwins->wbuf[i].rw_in[j]; } } #endif #endif /* * Translate signal codes from new to old. * /usr/include/sys/siginfo.h contains new codes. * /usr/ucbinclude/sys/signal.h contains old codes. */ code = 0; addr = SIG_NOADDR; if (sip != NULL && SI_FROMKERNEL(sip)) { addr = sip->si_addr; switch (sig) { case SIGILL: switch (sip->si_code) { case ILL_PRVOPC: code = ILL_PRIVINSTR_FAULT; break; case ILL_BADSTK: code = ILL_STACK; break; case ILL_ILLTRP: code = ILL_TRAP_FAULT(sip->si_trapno); break; default: code = ILL_ILLINSTR_FAULT; break; } break; case SIGEMT: code = EMT_TAG; break; case SIGFPE: switch (sip->si_code) { case FPE_INTDIV: code = FPE_INTDIV_TRAP; break; case FPE_INTOVF: code = FPE_INTOVF_TRAP; break; case FPE_FLTDIV: code = FPE_FLTDIV_TRAP; break; case FPE_FLTOVF: code = FPE_FLTOVF_TRAP; break; case FPE_FLTUND: code = FPE_FLTUND_TRAP; break; case FPE_FLTRES: code = FPE_FLTINEX_TRAP; break; default: code = FPE_FLTOPERR_TRAP; break; } break; case SIGBUS: switch (sip->si_code) { case BUS_ADRALN: code = BUS_ALIGN; break; case BUS_ADRERR: code = BUS_HWERR; break; default: /* BUS_OBJERR */ code = FC_MAKE_ERR(sip->si_errno); break; } break; case SIGSEGV: switch (sip->si_code) { case SEGV_MAPERR: code = SEGV_NOMAP; break; case SEGV_ACCERR: code = SEGV_PROT; break; default: code = FC_MAKE_ERR(sip->si_errno); break; } break; default: addr = SIG_NOADDR; break; } } (*_siguhandler[sig])(sig, code, &sc, addr); if (sc.sc_onstack) ucp->uc_stack.ss_flags |= SS_ONSTACK; else ucp->uc_stack.ss_flags &= ~SS_ONSTACK; mask2set(sc.sc_mask, &ucp->uc_sigmask); #if defined(__sparc) ucp->uc_mcontext.gregs[REG_SP] = sc.sc_sp; ucp->uc_mcontext.gregs[REG_PC] = sc.sc_pc; ucp->uc_mcontext.gregs[REG_nPC] = sc.sc_npc; #if defined(__sparcv9) ucp->uc_mcontext.gregs[REG_CCR] = sc.sc_psr; #else ucp->uc_mcontext.gregs[REG_PSR] = sc.sc_psr; #endif ucp->uc_mcontext.gregs[REG_G1] = sc.sc_g1; ucp->uc_mcontext.gregs[REG_O0] = sc.sc_o0; #ifdef NEVER if (gwinswitch == 1) { int i, j; ucp->uc_mcontext.gwins->wbcnt = sc.sc_wbcnt; /* XXX - should use bcopy to move this in bulk */ for (i = 0; i < sc.sc_wbcnt; i++) { ucp->uc_mcontext.gwins->spbuf[i] = sc.sc_spbuf[i]; for (j = 0; j < 8; j++) ucp->uc_mcontext.gwins->wbuf[i].rw_local[j] = sc.sc_wbuf[i][j]; for (j = 0; j < 8; j++) ucp->uc_mcontext.gwins->wbuf[i].rw_in[j] = sc.sc_wbuf[i][j+8]; } } #endif if (sig == SIGFPE) { if (ucp->uc_mcontext.fpregs.fpu_qcnt > 0) { ucp->uc_mcontext.fpregs.fpu_qcnt--; ucp->uc_mcontext.fpregs.fpu_q++; } } #endif (void) setcontext(ucp); }