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