xref: /titanic_50/usr/src/lib/libbc/libc/sys/common/sigaction.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
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 2004 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 <stdio.h>
30 #include <errno.h>
31 #include <signal.h>
32 #include "signalmap.h"
33 
34 static void signal_init(void);
35 #pragma init(signal_init)
36 
37 extern void (*handlers[])();
38 extern void maphandler(int, int, struct sigcontext *, char *);
39 extern void (*_siguhandler[])();		/* libucb */
40 extern void _sigvechandler(int, void*, void*);	/* libucb */
41 
42 extern int maptonewsig();
43 extern int _sigaction();
44 extern int maptonewmask();
45 extern int maptooldmask();
46 extern int _signal();
47 extern int _sigprocmask();
48 extern char *memset();
49 extern int _sigpending();
50 
51 typedef struct {
52 	unsigned long	__sigbits[4];
53 } S5_sigset_t;
54 
55 typedef struct {
56 	int		sa_flags;
57 	void		(*sa_handler)();
58 	S5_sigset_t	sa_mask;
59 	int		sa_resv[2];
60 } S5_sigaction;
61 
62 #define	S5_SA_ONSTACK	0x00000001
63 #define	S5_SA_RESETHAND	0x00000002
64 #define	S5_SA_RESTART	0x00000004
65 #define	S5_SA_NOCLDSTOP	0x00020000
66 
67 int
68 sigaction(sig, act, oact)
69 int sig;
70 struct sigaction *act, *oact;
71 {
72 	S5_sigaction	S5_act;
73 	S5_sigaction	S5_oact;
74 	int		ret;
75 	int		newsig;
76 	void		(*oldhand)();
77 	void		(*oldsiguhand)();
78 
79 	newsig = maptonewsig(sig);
80 	oldhand = handlers[newsig];
81 	oldsiguhand = _siguhandler[newsig];
82 	if (act == NULL) {
83 		ret = _sigaction(newsig, (S5_sigaction *)NULL, &S5_oact);
84 	} else {
85 		S5_act.sa_flags = 0;
86 		if (act->sa_flags & SA_ONSTACK)
87 			S5_act.sa_flags |= S5_SA_ONSTACK;
88 		if (act->sa_flags & SA_RESETHAND)
89 			S5_act.sa_flags |= S5_SA_RESETHAND;
90 		if (act->sa_flags & SA_NOCLDSTOP)
91 			S5_act.sa_flags |= S5_SA_NOCLDSTOP;
92 		if (!(act->sa_flags & SA_INTERRUPT))
93 			S5_act.sa_flags |= S5_SA_RESTART;
94 		/*
95 		 * _sigvechandler() receives control from the OS.
96 		 * It calls through _siguhandler[] to maphandler(),
97 		 * which maps the signal number new-to-old, and
98 		 * calls the user's handler through handlers[].
99 		 */
100 		handlers[newsig] = act->sa_handler;
101 		_siguhandler[newsig] = maphandler;
102 		if ((act->sa_handler == SIG_DFL) ||
103 		    (act->sa_handler == SIG_IGN))
104 			S5_act.sa_handler = act->sa_handler;
105 		else
106 			S5_act.sa_handler = _sigvechandler;
107 		S5_act.sa_mask.__sigbits[0] = maptonewmask(act->sa_mask);
108 		S5_act.sa_mask.__sigbits[1] = 0;
109 		S5_act.sa_mask.__sigbits[2] = 0;
110 		S5_act.sa_mask.__sigbits[3] = 0;
111 
112 		ret = _sigaction(newsig, &S5_act, &S5_oact);
113 	}
114 
115 	if ((oact != NULL) && (ret != -1)) {
116 		oact->sa_flags = 0;
117 		if (S5_oact.sa_flags & S5_SA_ONSTACK)
118 			oact->sa_flags |= SA_ONSTACK;
119 		if (S5_oact.sa_flags & S5_SA_RESETHAND)
120 			oact->sa_flags |= SA_RESETHAND;
121 		if (S5_oact.sa_flags & S5_SA_NOCLDSTOP)
122 			oact->sa_flags |= SA_NOCLDSTOP;
123 		if (!(S5_oact.sa_flags & S5_SA_RESTART))
124 			oact->sa_flags |= SA_INTERRUPT;
125 		if ((S5_oact.sa_handler == SIG_DFL) ||
126 		    (S5_oact.sa_handler == SIG_IGN))
127 			oact->sa_handler = S5_oact.sa_handler;
128 		else
129 			oact->sa_handler = oldhand;
130 		oact->sa_mask = maptooldmask(S5_oact.sa_mask.__sigbits[0]);
131 	}
132 	if (ret == -1) {
133 		handlers[newsig] = oldhand;
134 		_siguhandler[newsig] = oldsiguhand;
135 	}
136 	return (ret);
137 }
138 
139 static void
140 signal_init() {
141 #define	S5_SIGPOLL	22
142 	_signal(S5_SIGPOLL, SIG_IGN);
143 #undef S5_SIGPOLL
144 }
145 
146 int
147 sigprocmask(how, set, oset)
148 int how;
149 sigset_t *set, *oset;
150 {
151 	int		how_map[] = {0, 1, 2, 0, 3};
152 	int		ret;
153 	S5_sigset_t	s5_set, s5_oset;
154 
155 	if (set == NULL) /* query */
156 		ret = _sigprocmask(how_map[how], NULL, &s5_oset);
157 	else {
158 		memset(&s5_set, 0, sizeof (S5_sigset_t));
159 		s5_set.__sigbits[0] = maptonewmask(*set);
160 		ret = _sigprocmask(how_map[how], &s5_set, &s5_oset);
161 	}
162 	if ((oset != NULL) && (ret == 0))
163 		*oset = maptooldmask(s5_oset.__sigbits[0]);
164 	return (ret);
165 }
166 
167 int
168 sigpending(set)
169 sigset_t *set;
170 {
171 	S5_sigset_t	s5_set;
172 	int		ret;
173 
174 	ret = _sigpending(&s5_set);
175 	*set = maptooldmask(s5_set.__sigbits[0]);
176 	return (ret);
177 }
178