1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 1996 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include "signalmap.h"
30#include <sys/signal.h>
31#include <sys/errno.h>
32
33extern int errno;
34void (*handlers[32])();		/* XXX - 32???  NSIG, maybe? */
35
36void
37maphandler(int sig, int code, struct sigcontext *scp, char *addr)
38{
39	switch (sig) {
40		case SIGBUS:
41		case SIGSEGV:
42			switch (FC_CODE(code)) {
43			case 3:		/* 5.x value for FC_OBJERR */
44				code = FC_MAKE_ERR(FC_ERRNO(code));
45				break;
46			case 5:		/* 5.x value for FC_NOMAP */
47				code = FC_NOMAP;
48				break;
49			}
50			break;
51	}
52	__sendsig(maptooldsig(sig), code, scp, addr, handlers[sig]);
53}
54
55void (*
56signal(int sig, void (*a)(int)))(int)
57{
58	int newsig;
59
60	struct sigvec osv, sv;
61
62	sv.sv_handler = a;
63	sv.sv_mask = 0;
64#ifdef S5EMUL
65	sv.sv_flags = SV_INTERRUPT|SV_RESETHAND;
66#else
67	sv.sv_flags = 0;
68#endif
69	if (sigvec(sig, &sv, &osv) < 0)
70		return (BADSIG);
71	return (osv.sv_handler);
72}
73
74
75int
76sigvec(int sig, struct sigvec *nvec, struct sigvec *ovec)
77{
78	int newsig;
79	struct sigvec tvec, *tvecp;
80	void (*oldhand)(int);
81
82	if ((int)nvec == -1 || (int)ovec == -1) {
83		errno = EFAULT;
84		return (-1);
85	}
86
87	newsig = maptonewsig(sig);
88	oldhand = handlers[newsig];
89
90	if ((tvecp = nvec) != 0) {
91		tvec = *nvec;
92		tvecp = &tvec;
93		/*
94		 * To be compatible with the behavior of SunOS 4.x:
95		 * If the new signal handler is SIG_IGN or SIG_DFL,
96		 * do not change the signal's entry in the handler array.
97		 * This allows a child of vfork(2) to set signal handlers
98		 * to SIG_IGN or SIG_DFL without affecting the parent.
99		 */
100		if (tvecp->sv_handler != SIG_DFL &&
101		    tvecp->sv_handler != SIG_IGN) {
102			handlers[newsig] = tvecp->sv_handler;
103			tvecp->sv_handler = maphandler;
104		}
105	}
106
107	if (ucbsigvec(newsig, tvecp, ovec) == -1) {
108		handlers[newsig] = oldhand;
109		return (-1);
110	}
111
112	if (ovec && ovec->sv_handler != SIG_DFL && ovec->sv_handler != SIG_IGN)
113		ovec->sv_handler = oldhand;
114
115	return (0);
116}
117
118int
119sigsetmask(int mask)
120{
121	int ret;
122	ret = ucbsigsetmask(maptonewmask(mask));
123	return (maptooldmask(ret));
124}
125
126int
127sigblock(int mask)
128{
129	int ret;
130	ret = ucbsigblock(maptonewmask(mask));
131	return (maptooldmask(ret));
132}
133
134
135int
136sigpause(int mask)
137{
138	int ret;
139	return (ucbsigpause(maptonewmask(mask)));
140}
141
142int
143siginterrupt(int sig, int flag)
144{
145	return (ucbsiginterrupt(maptonewsig(sig), flag));
146}
147
148
149int
150maptonewsig(int sig)
151{
152	switch (sig) {
153	case SIGURG:               /* urgent condition on IO channel */
154		return (XSIGURG);
155	case SIGSTOP:              /* sendable stop signal not from tty */
156		return (XSIGSTOP);
157	case SIGTSTP:            /* stop signal from tty */
158		return (XSIGTSTP);
159	case SIGCONT:            /* continue a stopped process */
160		return (XSIGCONT);
161	case SIGCLD:          /* System V name for SIGCHLD */
162		return (XSIGCLD);
163	case SIGTTIN:          /* to readers pgrp upon background tty read */
164		return (XSIGTTIN);
165	case SIGTTOU:         /* like TTIN for output */
166		return (XSIGTTOU);
167	case SIGIO:        /* input/output possible signal */
168		return (XSIGIO);
169	case SIGXCPU:       /* exceeded CPU time limit */
170		return (XSIGXCPU);
171	case SIGXFSZ:       /* exceeded file size limit */
172		return (XSIGXFSZ);
173	case SIGVTALRM:      /* virtual time alarm */
174		return (XSIGVTALRM);
175	case SIGPROF:        /* profiling time alarm */
176		return (XSIGPROF);
177	case SIGWINCH:       /* window changed */
178		return (XSIGWINCH);
179	case SIGLOST:	     /* resource lost, not supported */
180		return (-1);
181	case SIGUSR1:
182		return (XSIGUSR1);
183	case SIGUSR2:      /* user defined signal 2 */
184		return (XSIGUSR2);
185	default:
186		return (sig);
187	}
188}
189
190int
191maptooldsig(int sig)
192{
193	switch (sig) {
194	case XSIGURG:               /* urgent condition on IO channel */
195		return (SIGURG);
196	case XSIGSTOP:              /* sendable stop signal not from tty */
197		return (SIGSTOP);
198	case XSIGTSTP:            /* stop signal from tty */
199		return (SIGTSTP);
200	case XSIGCONT:            /* continue a stopped process */
201		return (SIGCONT);
202	case XSIGCLD:          /* System V name for SIGCHLD */
203		return (SIGCLD);
204	case XSIGTTIN:          /* to readers pgrp upon background tty read */
205		return (SIGTTIN);
206	case XSIGTTOU:         /* like TTIN for output */
207		return (SIGTTOU);
208	case XSIGIO:        /* input/output possible signal */
209		return (SIGIO);
210	case XSIGXCPU:       /* exceeded CPU time limit */
211		return (SIGXCPU);
212	case XSIGXFSZ:       /* exceeded file size limit */
213		return (SIGXFSZ);
214	case XSIGVTALRM:      /* virtual time alarm */
215		return (SIGVTALRM);
216	case XSIGPROF:        /* profiling time alarm */
217		return (SIGPROF);
218	case XSIGWINCH:       /* window changed */
219		return (SIGWINCH);
220	case XSIGUSR1:
221		return (SIGUSR1);
222	case XSIGUSR2:      /* user defined signal 2 */
223		return (SIGUSR2);
224	case XSIGPWR:      /* user defined signal 2 */
225		return (-1);
226	default:
227		return (sig);
228	}
229}
230
231int
232maptooldmask(int mask)
233{
234	int omask;
235
236	omask = mask & 0x7FFF;		/* these signo are same */
237
238	if (mask & sigmask(XSIGURG))
239		omask |= sigmask(SIGURG);
240	if (mask & sigmask(XSIGSTOP))
241		omask |= sigmask(SIGSTOP);
242	if (mask & sigmask(XSIGTSTP))
243		omask |= sigmask(SIGTSTP);
244	if (mask & sigmask(XSIGCONT))
245		omask |= sigmask(SIGCONT);
246	if (mask & sigmask(XSIGCLD))
247		omask |= sigmask(SIGCLD);
248	if (mask & sigmask(XSIGTTIN))
249		omask |= sigmask(SIGTTIN);
250	if (mask & sigmask(XSIGTTOU))
251		omask |= sigmask(SIGTTOU);
252	if (mask & sigmask(XSIGIO))
253		omask |= sigmask(SIGIO);
254	if (mask & sigmask(XSIGXCPU))
255		omask |= sigmask(SIGXCPU);
256	if (mask & sigmask(XSIGXFSZ))
257		omask |= sigmask(SIGXFSZ);
258	if (mask & sigmask(XSIGVTALRM))
259		omask |= sigmask(SIGVTALRM);
260	if (mask & sigmask(XSIGPROF))
261		omask |= sigmask(SIGPROF);
262	if (mask & sigmask(XSIGWINCH))
263		omask |= sigmask(SIGWINCH);
264	if (mask & sigmask(XSIGUSR1))
265		omask |= sigmask(SIGUSR1);
266	if (mask & sigmask(XSIGUSR2))
267		omask |= sigmask(SIGUSR2);
268	return (omask);
269}
270
271
272int
273maptonewmask(int omask)
274{
275	int mask;
276
277	if (omask == -1) {
278		return (-1);
279	}
280
281	mask = omask & 0x7FFF;		/* these signo are the same */
282
283	if (omask & sigmask(SIGURG))
284		mask |= sigmask(XSIGURG);
285	if (omask & sigmask(SIGSTOP))
286		mask |= sigmask(XSIGSTOP);
287	if (omask & sigmask(SIGTSTP))
288		mask |= sigmask(XSIGTSTP);
289	if (omask & sigmask(SIGCONT))
290		mask |= sigmask(XSIGCONT);
291	if (omask & sigmask(SIGCLD))
292		mask |= sigmask(XSIGCLD);
293	if (omask & sigmask(SIGTTIN))
294		mask |= sigmask(XSIGTTIN);
295	if (omask & sigmask(SIGTTOU))
296		mask |= sigmask(XSIGTTOU);
297	if (omask & sigmask(SIGIO))
298		mask |= sigmask(XSIGIO);
299	if (omask & sigmask(SIGXCPU))
300		mask |= sigmask(XSIGXCPU);
301	if (omask & sigmask(SIGXFSZ))
302		mask |= sigmask(XSIGXFSZ);
303	if (omask & sigmask(SIGVTALRM))
304		mask |= sigmask(XSIGVTALRM);
305	if (omask & sigmask(SIGPROF))
306		mask |= sigmask(XSIGPROF);
307	if (omask & sigmask(SIGWINCH))
308		mask |= sigmask(XSIGWINCH);
309	if (omask & sigmask(SIGUSR1))
310		mask |= sigmask(XSIGUSR1);
311	if (omask & sigmask(SIGUSR2))
312		mask |= sigmask(XSIGUSR2);
313	return (mask);
314}
315