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