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