1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate /* 18*7c478bd9Sstevel@tonic-gate * 4.3BSD signal compatibility functions 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * the implementation interprets signal masks equal to -1 as "all of the 21*7c478bd9Sstevel@tonic-gate * signals in the signal set", thereby allowing signals with numbers 22*7c478bd9Sstevel@tonic-gate * above 32 to be blocked when referenced in code such as: 23*7c478bd9Sstevel@tonic-gate * 24*7c478bd9Sstevel@tonic-gate * for (i = 0; i < NSIG; i++) 25*7c478bd9Sstevel@tonic-gate * mask |= sigmask(i) 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 29*7c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/ucontext.h> 31*7c478bd9Sstevel@tonic-gate #include <signal.h> 32*7c478bd9Sstevel@tonic-gate #include "signal.h" 33*7c478bd9Sstevel@tonic-gate #include <errno.h> 34*7c478bd9Sstevel@tonic-gate #include <stdio.h> 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #define set2mask(setp) ((setp)->__sigbits[0]) 37*7c478bd9Sstevel@tonic-gate #define mask2set(mask, setp) \ 38*7c478bd9Sstevel@tonic-gate ((mask) == -1 ? sigfillset(setp) : sigemptyset(setp), (((setp)->__sigbits[0]) = (mask))) 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate void (*_siguhandler[NSIG])() = { 0 }; 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * sigstack is emulated with sigaltstack by guessing an appropriate 44*7c478bd9Sstevel@tonic-gate * value for the stack size - on machines that have stacks that grow 45*7c478bd9Sstevel@tonic-gate * upwards, the ss_sp arguments for both functions mean the same thing, 46*7c478bd9Sstevel@tonic-gate * (the initial stack pointer sigstack() is also the stack base 47*7c478bd9Sstevel@tonic-gate * sigaltstack()), so a "very large" value should be chosen for the 48*7c478bd9Sstevel@tonic-gate * stack size - on machines that have stacks that grow downwards, the 49*7c478bd9Sstevel@tonic-gate * ss_sp arguments mean opposite things, so 0 should be used (hopefully 50*7c478bd9Sstevel@tonic-gate * these machines don't have hardware stack bounds registers that pay 51*7c478bd9Sstevel@tonic-gate * attention to sigaltstack()'s size argument. 52*7c478bd9Sstevel@tonic-gate */ 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #ifdef sun 55*7c478bd9Sstevel@tonic-gate #define SIGSTACKSIZE 0 56*7c478bd9Sstevel@tonic-gate #endif 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * sigvechandler is the real signal handler installed for all 61*7c478bd9Sstevel@tonic-gate * signals handled in the 4.3BSD compatibility interface - it translates 62*7c478bd9Sstevel@tonic-gate * SVR4 signal hander arguments into 4.3BSD signal handler arguments 63*7c478bd9Sstevel@tonic-gate * and then calls the real handler 64*7c478bd9Sstevel@tonic-gate */ 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate static void 67*7c478bd9Sstevel@tonic-gate sigvechandler(sig, sip, ucp) 68*7c478bd9Sstevel@tonic-gate int sig; 69*7c478bd9Sstevel@tonic-gate siginfo_t *sip; 70*7c478bd9Sstevel@tonic-gate ucontext_t *ucp; 71*7c478bd9Sstevel@tonic-gate { 72*7c478bd9Sstevel@tonic-gate struct sigcontext sc; 73*7c478bd9Sstevel@tonic-gate int code; 74*7c478bd9Sstevel@tonic-gate char *addr; 75*7c478bd9Sstevel@tonic-gate register int i, j; 76*7c478bd9Sstevel@tonic-gate int gwinswitch = 0; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate sc.sc_onstack = ((ucp->uc_stack.ss_flags & SS_ONSTACK) != 0); 79*7c478bd9Sstevel@tonic-gate sc.sc_mask = set2mask(&ucp->uc_sigmask); 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * Machine dependent code begins 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate sc.sc_sp = ucp->uc_mcontext.gregs[REG_O6]; 85*7c478bd9Sstevel@tonic-gate sc.sc_pc = ucp->uc_mcontext.gregs[REG_PC]; 86*7c478bd9Sstevel@tonic-gate sc.sc_npc = ucp->uc_mcontext.gregs[REG_nPC]; 87*7c478bd9Sstevel@tonic-gate sc.sc_psr = ucp->uc_mcontext.gregs[REG_PSR]; 88*7c478bd9Sstevel@tonic-gate sc.sc_g1 = ucp->uc_mcontext.gregs[REG_G1]; 89*7c478bd9Sstevel@tonic-gate sc.sc_o0 = ucp->uc_mcontext.gregs[REG_O0]; 90*7c478bd9Sstevel@tonic-gate if (ucp->uc_mcontext.gwins != (gwindows_t *)0) { 91*7c478bd9Sstevel@tonic-gate gwinswitch = 1; 92*7c478bd9Sstevel@tonic-gate sc.sc_wbcnt = ucp->uc_mcontext.gwins->wbcnt; 93*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAXWINDOW; i++) { 94*7c478bd9Sstevel@tonic-gate for (j = 0; j < 16; j++) 95*7c478bd9Sstevel@tonic-gate sc.sc_spbuf[i][j] = (int)ucp->uc_mcontext.gwins->spbuf[j]; 96*7c478bd9Sstevel@tonic-gate for (j = 0; j < 8; j++) 97*7c478bd9Sstevel@tonic-gate sc.sc_wbuf[i][j] = ucp->uc_mcontext.gwins->wbuf[i].rw_local[j]; 98*7c478bd9Sstevel@tonic-gate for (j = 0; j < 8; j++) 99*7c478bd9Sstevel@tonic-gate sc.sc_wbuf[i][j+8] = ucp->uc_mcontext.gwins->wbuf[i].rw_in[j]; 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate /* 103*7c478bd9Sstevel@tonic-gate * Machine dependent code ends 104*7c478bd9Sstevel@tonic-gate */ 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate if (sip != NULL) 107*7c478bd9Sstevel@tonic-gate if ((code = sip->si_code) == BUS_OBJERR) 108*7c478bd9Sstevel@tonic-gate code = SEGV_MAKE_ERR(sip->si_errno); 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS) 111*7c478bd9Sstevel@tonic-gate if (sip != NULL) 112*7c478bd9Sstevel@tonic-gate addr = (char *)sip->si_addr; 113*7c478bd9Sstevel@tonic-gate else 114*7c478bd9Sstevel@tonic-gate addr = SIG_NOADDR; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate (*_siguhandler[sig])(sig, code, &sc, addr); 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate if (sc.sc_onstack) 119*7c478bd9Sstevel@tonic-gate ucp->uc_stack.ss_flags |= SS_ONSTACK; 120*7c478bd9Sstevel@tonic-gate else 121*7c478bd9Sstevel@tonic-gate ucp->uc_stack.ss_flags &= ~SS_ONSTACK; 122*7c478bd9Sstevel@tonic-gate mask2set(sc.sc_mask, &ucp->uc_sigmask); 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate /* 125*7c478bd9Sstevel@tonic-gate * Machine dependent code begins 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_O6] = sc.sc_sp; 128*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_PC] = sc.sc_pc; 129*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_nPC] = sc.sc_npc; 130*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_PSR] = sc.sc_psr; 131*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_G1] = sc.sc_g1; 132*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_O0] = sc.sc_o0; 133*7c478bd9Sstevel@tonic-gate if (gwinswitch == 1) { 134*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gwins->wbcnt = sc.sc_wbcnt; 135*7c478bd9Sstevel@tonic-gate for (i = 0; i < MAXWINDOW; i++) { 136*7c478bd9Sstevel@tonic-gate for (j = 0; j < 16; j++) 137*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gwins->spbuf[j] = (greg_t *)sc.sc_spbuf[i][j]; 138*7c478bd9Sstevel@tonic-gate for (j = 0; j < 8; j++) 139*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gwins->wbuf[i].rw_local[j] = sc.sc_wbuf[i][j]; 140*7c478bd9Sstevel@tonic-gate for (j = 0; j < 8; j++) 141*7c478bd9Sstevel@tonic-gate ucp->uc_mcontext.gwins->wbuf[i].rw_in[j] = sc.sc_wbuf[i][j+8]; 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * Machine dependent code ends 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate setcontext (ucp); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate sigsetmask(mask) 152*7c478bd9Sstevel@tonic-gate int mask; 153*7c478bd9Sstevel@tonic-gate { 154*7c478bd9Sstevel@tonic-gate sigset_t oset; 155*7c478bd9Sstevel@tonic-gate sigset_t nset; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate (void) sigprocmask(0, (sigset_t *)0, &nset); 158*7c478bd9Sstevel@tonic-gate mask2set(mask, &nset); 159*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &nset, &oset); 160*7c478bd9Sstevel@tonic-gate return set2mask(&oset); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate sigblock(mask) 164*7c478bd9Sstevel@tonic-gate int mask; 165*7c478bd9Sstevel@tonic-gate { 166*7c478bd9Sstevel@tonic-gate sigset_t oset; 167*7c478bd9Sstevel@tonic-gate sigset_t nset; 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate (void) sigprocmask(0, (sigset_t *)0, &nset); 170*7c478bd9Sstevel@tonic-gate mask2set(mask, &nset); 171*7c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &nset, &oset); 172*7c478bd9Sstevel@tonic-gate return set2mask(&oset); 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate sigpause(mask) 176*7c478bd9Sstevel@tonic-gate int mask; 177*7c478bd9Sstevel@tonic-gate { 178*7c478bd9Sstevel@tonic-gate sigset_t set; 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate (void) sigprocmask(0, (sigset_t *)0, &set); 181*7c478bd9Sstevel@tonic-gate mask2set(mask, &set); 182*7c478bd9Sstevel@tonic-gate return (sigsuspend(&set)); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate sigvec(sig, nvec, ovec) 186*7c478bd9Sstevel@tonic-gate int sig; 187*7c478bd9Sstevel@tonic-gate struct sigvec *nvec; 188*7c478bd9Sstevel@tonic-gate struct sigvec *ovec; 189*7c478bd9Sstevel@tonic-gate { 190*7c478bd9Sstevel@tonic-gate struct sigaction nact; 191*7c478bd9Sstevel@tonic-gate struct sigaction oact; 192*7c478bd9Sstevel@tonic-gate struct sigaction *nactp; 193*7c478bd9Sstevel@tonic-gate void (*ohandler)(), (*nhandler)(); 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate if (sig <= 0 || sig >= NSIG) { 196*7c478bd9Sstevel@tonic-gate errno = EINVAL; 197*7c478bd9Sstevel@tonic-gate return -1; 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate ohandler = _siguhandler[sig]; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate if (nvec) { 203*7c478bd9Sstevel@tonic-gate _sigaction(sig, (struct sigaction *)0, &nact); 204*7c478bd9Sstevel@tonic-gate nhandler = nvec->sv_handler; 205*7c478bd9Sstevel@tonic-gate _siguhandler[sig] = nhandler; 206*7c478bd9Sstevel@tonic-gate if (nhandler != SIG_DFL && nhandler != SIG_IGN) 207*7c478bd9Sstevel@tonic-gate nact.sa_handler = (void (*)())sigvechandler; 208*7c478bd9Sstevel@tonic-gate else 209*7c478bd9Sstevel@tonic-gate nact.sa_handler = nhandler; 210*7c478bd9Sstevel@tonic-gate mask2set(nvec->sv_mask, &nact.sa_mask); 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate if ( sig == SIGTSTP || sig == SIGSTOP ) 213*7c478bd9Sstevel@tonic-gate nact.sa_handler = SIG_DFL; */ 214*7c478bd9Sstevel@tonic-gate nact.sa_flags = SA_SIGINFO; 215*7c478bd9Sstevel@tonic-gate if (!(nvec->sv_flags & SV_INTERRUPT)) 216*7c478bd9Sstevel@tonic-gate nact.sa_flags |= SA_RESTART; 217*7c478bd9Sstevel@tonic-gate if (nvec->sv_flags & SV_RESETHAND) 218*7c478bd9Sstevel@tonic-gate nact.sa_flags |= SA_RESETHAND; 219*7c478bd9Sstevel@tonic-gate if (nvec->sv_flags & SV_ONSTACK) 220*7c478bd9Sstevel@tonic-gate nact.sa_flags |= SA_ONSTACK; 221*7c478bd9Sstevel@tonic-gate nactp = &nact; 222*7c478bd9Sstevel@tonic-gate } else 223*7c478bd9Sstevel@tonic-gate nactp = (struct sigaction *)0; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate if (_sigaction(sig, nactp, &oact) < 0) { 226*7c478bd9Sstevel@tonic-gate _siguhandler[sig] = ohandler; 227*7c478bd9Sstevel@tonic-gate return -1; 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate if (ovec) { 231*7c478bd9Sstevel@tonic-gate if (oact.sa_handler == SIG_DFL || oact.sa_handler == SIG_IGN) 232*7c478bd9Sstevel@tonic-gate ovec->sv_handler = oact.sa_handler; 233*7c478bd9Sstevel@tonic-gate else 234*7c478bd9Sstevel@tonic-gate ovec->sv_handler = ohandler; 235*7c478bd9Sstevel@tonic-gate ovec->sv_mask = set2mask(&oact.sa_mask); 236*7c478bd9Sstevel@tonic-gate ovec->sv_flags = 0; 237*7c478bd9Sstevel@tonic-gate if (oact.sa_flags & SA_ONSTACK) 238*7c478bd9Sstevel@tonic-gate ovec->sv_flags |= SV_ONSTACK; 239*7c478bd9Sstevel@tonic-gate if (oact.sa_flags & SA_RESETHAND) 240*7c478bd9Sstevel@tonic-gate ovec->sv_flags |= SV_RESETHAND; 241*7c478bd9Sstevel@tonic-gate if (!(oact.sa_flags & SA_RESTART)) 242*7c478bd9Sstevel@tonic-gate ovec->sv_flags |= SV_INTERRUPT; 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate return 0; 246*7c478bd9Sstevel@tonic-gate } 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate void (* 250*7c478bd9Sstevel@tonic-gate signal(s, a))() 251*7c478bd9Sstevel@tonic-gate int s; 252*7c478bd9Sstevel@tonic-gate void (*a)(); 253*7c478bd9Sstevel@tonic-gate { 254*7c478bd9Sstevel@tonic-gate struct sigvec osv; 255*7c478bd9Sstevel@tonic-gate struct sigvec nsv; 256*7c478bd9Sstevel@tonic-gate static int mask[NSIG]; 257*7c478bd9Sstevel@tonic-gate static int flags[NSIG]; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate nsv.sv_handler = a; 260*7c478bd9Sstevel@tonic-gate nsv.sv_mask = mask[s]; 261*7c478bd9Sstevel@tonic-gate nsv.sv_flags = flags[s]; 262*7c478bd9Sstevel@tonic-gate if (sigvec(s, &nsv, &osv) < 0) 263*7c478bd9Sstevel@tonic-gate return (SIG_ERR); 264*7c478bd9Sstevel@tonic-gate if (nsv.sv_mask != osv.sv_mask || nsv.sv_flags != osv.sv_flags) { 265*7c478bd9Sstevel@tonic-gate mask[s] = nsv.sv_mask = osv.sv_mask; 266*7c478bd9Sstevel@tonic-gate flags[s] = nsv.sv_flags = osv.sv_flags & ~SV_RESETHAND; 267*7c478bd9Sstevel@tonic-gate if (sigvec(s, &nsv, (struct sigvec *)0) < 0) 268*7c478bd9Sstevel@tonic-gate return (SIG_ERR); 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate return (osv.sv_handler); 271*7c478bd9Sstevel@tonic-gate } 272