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