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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 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 #pragma weak _signal = signal
30 #pragma weak _sighold = sighold
31 #pragma weak _sigrelse = sigrelse
32 #pragma weak _sigignore = sigignore
33 #pragma weak _sigset = sigset
34
35 #include "lint.h"
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <errno.h>
39 #include <signal.h>
40 #include <wait.h>
41
42 /*
43 * Check for valid signal number as per SVID.
44 */
45 #define CHECK_SIG(s, code) \
46 if ((s) <= 0 || (s) >= NSIG || (s) == SIGKILL || (s) == SIGSTOP) { \
47 errno = EINVAL; \
48 return (code); \
49 }
50
51 /*
52 * Equivalent to stopdefault set in the kernel implementation (sig.c).
53 */
54 #define STOPDEFAULT(s) \
55 ((s) == SIGSTOP || (s) == SIGTSTP || (s) == SIGTTOU || (s) == SIGTTIN)
56
57
58 /*
59 * SVr3.x signal compatibility routines. They are now
60 * implemented as library routines instead of system
61 * calls.
62 */
63
64 void(*
signal(int sig,void (* func)(int))65 signal(int sig, void(*func)(int)))(int)
66 {
67 struct sigaction nact;
68 struct sigaction oact;
69
70 CHECK_SIG(sig, SIG_ERR);
71
72 nact.sa_handler = func;
73 nact.sa_flags = SA_RESETHAND|SA_NODEFER;
74 (void) sigemptyset(&nact.sa_mask);
75
76 /*
77 * Pay special attention if sig is SIGCHLD and
78 * the disposition is SIG_IGN, per sysV signal man page.
79 */
80 if (sig == SIGCHLD) {
81 nact.sa_flags |= SA_NOCLDSTOP;
82 if (func == SIG_IGN)
83 nact.sa_flags |= SA_NOCLDWAIT;
84 }
85
86 if (STOPDEFAULT(sig))
87 nact.sa_flags |= SA_RESTART;
88
89 if (sigaction(sig, &nact, &oact) < 0)
90 return (SIG_ERR);
91
92 return (oact.sa_handler);
93 }
94
95 int
sighold(int sig)96 sighold(int sig)
97 {
98 sigset_t set;
99
100 CHECK_SIG(sig, -1);
101
102 /*
103 * errno set on failure by either sigaddset or sigprocmask.
104 */
105 (void) sigemptyset(&set);
106 if (sigaddset(&set, sig) < 0)
107 return (-1);
108 return (sigprocmask(SIG_BLOCK, &set, (sigset_t *)0));
109 }
110
111 int
sigrelse(int sig)112 sigrelse(int sig)
113 {
114 sigset_t set;
115
116 CHECK_SIG(sig, -1);
117
118 /*
119 * errno set on failure by either sigaddset or sigprocmask.
120 */
121 (void) sigemptyset(&set);
122 if (sigaddset(&set, sig) < 0)
123 return (-1);
124 return (sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0));
125 }
126
127 int
sigignore(int sig)128 sigignore(int sig)
129 {
130 struct sigaction act;
131 sigset_t set;
132
133 CHECK_SIG(sig, -1);
134
135 act.sa_handler = SIG_IGN;
136 act.sa_flags = 0;
137 (void) sigemptyset(&act.sa_mask);
138
139 /*
140 * Pay special attention if sig is SIGCHLD and
141 * the disposition is SIG_IGN, per sysV signal man page.
142 */
143 if (sig == SIGCHLD) {
144 act.sa_flags |= SA_NOCLDSTOP;
145 act.sa_flags |= SA_NOCLDWAIT;
146 }
147
148 if (STOPDEFAULT(sig))
149 act.sa_flags |= SA_RESTART;
150
151 if (sigaction(sig, &act, (struct sigaction *)0) < 0)
152 return (-1);
153
154 (void) sigemptyset(&set);
155 if (sigaddset(&set, sig) < 0)
156 return (-1);
157 return (sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0));
158 }
159
160 int
__sigpause(int sig)161 __sigpause(int sig)
162 {
163 sigset_t set;
164 int rval;
165
166 CHECK_SIG(sig, -1);
167
168 /*
169 * sigpause() is defined to unblock the signal
170 * and not block it again on return.
171 * sigsuspend() restores the original signal set,
172 * so we have to unblock sig overtly.
173 */
174 (void) sigprocmask(0, (sigset_t *)0, &set);
175 if (sigdelset(&set, sig) < 0)
176 return (-1);
177 rval = sigsuspend(&set);
178 (void) sigrelse(sig);
179 return (rval);
180 }
181
182 void(*
sigset(int sig,void (* func)(int))183 sigset(int sig, void(*func)(int)))(int)
184 {
185 struct sigaction nact;
186 struct sigaction oact;
187 sigset_t nset;
188 sigset_t oset;
189 int code;
190
191 CHECK_SIG(sig, SIG_ERR);
192
193 (void) sigemptyset(&nset);
194 if (sigaddset(&nset, sig) < 0)
195 return (SIG_ERR);
196
197 if (func == SIG_HOLD) {
198 if (sigprocmask(SIG_BLOCK, &nset, &oset) < 0)
199 return (SIG_ERR);
200 if (sigaction(sig, (struct sigaction *)0, &oact) < 0)
201 return (SIG_ERR);
202 } else {
203 nact.sa_handler = func;
204 nact.sa_flags = 0;
205 (void) sigemptyset(&nact.sa_mask);
206 /*
207 * Pay special attention if sig is SIGCHLD and
208 * the disposition is SIG_IGN, per sysV signal man page.
209 */
210 if (sig == SIGCHLD) {
211 nact.sa_flags |= SA_NOCLDSTOP;
212 if (func == SIG_IGN)
213 nact.sa_flags |= SA_NOCLDWAIT;
214 }
215
216 if (STOPDEFAULT(sig))
217 nact.sa_flags |= SA_RESTART;
218
219 if (sigaction(sig, &nact, &oact) < 0)
220 return (SIG_ERR);
221
222 if (sigprocmask(SIG_UNBLOCK, &nset, &oset) < 0)
223 return (SIG_ERR);
224 }
225
226 if ((code = sigismember(&oset, sig)) < 0)
227 return (SIG_ERR);
228 else if (code == 1)
229 return (SIG_HOLD);
230
231 return (oact.sa_handler);
232 }
233