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
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.
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]
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
27 * University Copyright- Copyright (c) 1982, 1986, 1988
28 * The Regents of the University of California
31 * University Acknowledgment- Portions of this document are derived from
32 * software developed by the University of California, Berkeley, and its
36 #pragma ident "%Z%%M% %I% %E% SMI"
39 * mailx -- a modified version of a University of California at Berkeley
44 * This code is only compiled in if SIG_HOLD is not defined!
46 * Retrofit new signal interface to old signal primitives.
56 * to set all held signals to ignored signals in the
57 * child process after fork(2)
68 typedef void (*sigtype
)();
70 #define SIG_HOLD ((sigtype) 2)
72 # define SIG_ERR ((sigtype) -1)
75 sigtype
sigdisp(), sighold(), sigignore();
79 * The following helps us keep the extended signal semantics together.
80 * We remember for each signal the address of the function we're
81 * supposed to call. s_func is SIG_DFL / SIG_IGN if appropriate.
83 static struct sigtable
{
84 sigtype s_func
; /* What to call */
85 int s_flag
; /* Signal flags; see below */
91 #define SHELD 1 /* Signal is being held */
92 #define SDEFER 2 /* Signal occured while held */
93 #define SSET 4 /* s_func is believable */
94 #define SPAUSE 8 /* are pausing, waiting for sig */
96 jmp_buf _pause
; /* For doing sigpause() */
99 * Approximate sigsys() system call
100 * This is almost useless since one only calls sigsys()
101 * in the child of a vfork(). If you have vfork(), you have new signals
102 * anyway. The real sigsys() does all the stuff needed to support
103 * the real sigset() library. We don't bother here, assuming that
104 * you are either ignoring or defaulting a signal in the child.
107 sigsys(int sig
, sigtype func
)
118 * Set the (permanent) disposition of a signal.
119 * If the signal is subsequently (or even now) held,
120 * the action you set here can be enabled using sigrelse().
123 sigset(int sig
, sigtype func
)
127 if (sig
< 1 || sig
> NSIG
) {
133 * Does anyone actually call sigset with SIG_HOLD!?
135 if (func
== SIG_HOLD
) {
139 sigtable
[sig
].s_flag
|= SSET
;
140 sigtable
[sig
].s_func
= func
;
141 if (func
== SIG_DFL
) {
143 * If signal has been held, must retain
144 * the catch so that we can note occurrance
147 if ((sigtable
[sig
].s_flag
& SHELD
) == 0)
148 signal(sig
, SIG_DFL
);
150 signal(sig
, _Sigtramp
);
153 if (func
== SIG_IGN
) {
155 * Clear pending signal
157 signal(sig
, SIG_IGN
);
158 sigtable
[sig
].s_flag
&= ~SDEFER
;
161 signal(sig
, _Sigtramp
);
167 * This CAN be tricky if the signal's disposition is SIG_DFL.
168 * In that case, we still catch the signal so we can note it
175 if (sig
< 1 || sig
> NSIG
) {
180 if (sigtable
[sig
].s_flag
& SHELD
)
183 * When the default action is required, we have to
184 * set up to catch the signal to note signal's occurrance.
186 if (old
== SIG_DFL
) {
187 sigtable
[sig
].s_flag
|= SSET
;
188 signal(sig
, _Sigtramp
);
190 sigtable
[sig
].s_flag
|= SHELD
;
196 * If the signal occurred while we had it held, cause the signal.
203 if (sig
< 1 || sig
> NSIG
) {
208 if ((sigtable
[sig
].s_flag
& SHELD
) == 0)
210 sigtable
[sig
].s_flag
&= ~SHELD
;
211 if (sigtable
[sig
].s_flag
& SDEFER
)
214 * If disposition was the default, then we can unset the
215 * catch to _Sigtramp() and let the system do the work.
217 if (sigtable
[sig
].s_func
== SIG_DFL
)
218 signal(sig
, SIG_DFL
);
228 return(sigset(sig
, SIG_IGN
));
232 * Pause, waiting for sig to occur.
233 * We assume LUSER called us with the signal held.
234 * When we got the signal, mark the signal as having
235 * occurred. It will actually cause something when
236 * the signal is released.
241 if (sig
< 1 || sig
> NSIG
) {
245 sigtable
[sig
].s_flag
|= SHELD
|SPAUSE
;
246 if (setjmp(_pause
) == 0)
248 sigtable
[sig
].s_flag
&= ~SPAUSE
;
249 sigtable
[sig
].s_flag
|= SDEFER
;
253 * In the child process after fork(2), set the disposition of all held
254 * signals to SIG_IGN. This is a new procedure not in the real sigset()
255 * package, provided for retrofitting purposes.
262 for (i
= 1; i
<= NSIG
; i
++)
263 if (sigtable
[i
].s_flag
& SHELD
)
269 * Return the current disposition of a signal
270 * If we have not set this signal before, we have to
278 if (sig
< 1 || sig
> NSIG
) {
283 * If we have no knowledge of this signal,
284 * ask the system, then save the result for later.
286 if ((sigtable
[sig
].s_flag
& SSET
) == 0) {
287 old
= signal(sig
, SIG_IGN
);
288 sigtable
[sig
].s_func
= old
;
289 sigtable
[sig
].s_flag
|= SSET
;
294 * If we have set this signal before, then sigset()
295 * will have been careful to leave something meaningful
298 return(sigtable
[sig
].s_func
);
302 * The following routine gets called for any signal
303 * that is to be trapped to a user function.
310 if (sig
< 1 || sig
> NSIG
) {
316 old
= signal(sig
, SIG_IGN
);
318 * If signal being paused on, wakeup sigpause()
320 if (sigtable
[sig
].s_flag
& SPAUSE
)
323 * If signal is being held, mark its table entry
324 * so we can trigger it when signal is released.
327 if (sigtable
[sig
].s_flag
& SHELD
) {
328 sigtable
[sig
].s_flag
|= SDEFER
;
329 signal(sig
, _Sigtramp
);
333 * If the signal is being ignored, just return.
334 * This would make SIGCONT more normal, but of course
335 * any system with SIGCONT also has the new signal pkg, so...
337 if (sigtable
[sig
].s_func
== SIG_IGN
)
340 * If the signal is SIG_DFL, then we probably got here
341 * by holding the signal, having it happen, then releasing
344 if (sigtable
[sig
].s_func
== SIG_DFL
) {
345 signal(sig
, SIG_DFL
);
347 /* Will we get back here? */
351 * Looks like we should just cause the signal...
352 * We hold the signal for the duration of the user's
353 * code with the signal re-enabled. If the signal
354 * happens again while in user code, we will recursively
355 * trap here and mark that we had another occurance
356 * and return to the user's trap code. When we return
357 * from there, we can cause the signal again.
359 sigtable
[sig
].s_flag
&= ~SDEFER
;
360 sigtable
[sig
].s_flag
|= SHELD
;
361 signal(sig
, _Sigtramp
);
362 (*sigtable
[sig
].s_func
)(sig
);
364 * If the signal re-occurred while in the user's routine,
365 * just go try it again...
367 sigtable
[sig
].s_flag
&= ~SHELD
;
368 if (sigtable
[sig
].s_flag
& SDEFER
)