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
38void (*_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
64static void
65sigvechandler(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
146int
147sigsetmask(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
158int
159sigblock(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
170int
171sigpause(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
180int
181sigvec(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
242void (*
243signal(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