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