4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: $");
39 #include <sys/queue.h>
46 * Mail -- a mail program
51 static sig_t sigarray
[NSIG
];
53 typedef struct q_entry_s
{
56 struct q_entry_s
*qe_next
;
62 } sigqueue
= { NULL
, &sigqueue
.qe_first
};
63 #define SIGQUEUE_INIT(p) do {\
64 (p)->qe_first = NULL;\
65 (p)->qe_last = &((p)->qe_first);\
66 } while (/*CONSTCOND*/ 0)
69 * The routines alloc_entry() and free_entry() manage the queue
72 * Currently, they just assign one element per signo from a fix array
73 * as we don't support POSIX signal queues. We leave them as this may
74 * change in the future and the modifications will be isolated.
77 alloc_entry(int signo
)
79 static q_entry_t entries
[NSIG
];
83 * We currently only post one signal per signal number, so
84 * there is no need to make this complicated.
91 e
->qe_handler
= sigarray
[signo
];
98 free_entry(q_entry_t
*e
)
102 e
->qe_handler
= NULL
;
107 * Attempt to post a signal to the sigqueue.
114 if (sigarray
[signo
] == SIG_DFL
|| sigarray
[signo
] == SIG_IGN
)
117 e
= alloc_entry(signo
);
119 *sigqueue
.qe_last
= e
;
120 sigqueue
.qe_last
= &e
->qe_next
;
125 * Check the sigqueue for any pending signals. If any are found,
126 * preform the required actions and remove them from the queue.
134 void (*handler
)(int);
137 (void)sigfillset(&nset
);
138 (void)sigprocmask(SIG_SETMASK
, &nset
, &oset
);
140 while ((e
= sigqueue
.qe_first
) != NULL
) {
142 handler
= e
->qe_handler
;
145 * Remove the entry from the queue and free it.
147 sigqueue
.qe_first
= e
->qe_next
;
148 if (sigqueue
.qe_first
== NULL
)
149 sigqueue
.qe_last
= &sigqueue
.qe_first
;
152 if (handler
== SIG_DFL
|| handler
== SIG_IGN
) {
153 assert(/*CONSTCOND*/ 0); /* These should not get posted. */
156 (void)sigprocmask(SIG_SETMASK
, &oset
, NULL
);
158 (void)sigprocmask(SIG_SETMASK
, &nset
, NULL
);
161 (void)sigprocmask(SIG_SETMASK
, &oset
, NULL
);
165 sig_signal(int signo
, sig_t handler
)
171 assert(signo
> 0 && signo
< NSIG
);
173 (void)sigemptyset(&nset
);
174 (void)sigaddset(&nset
, signo
);
175 (void)sigprocmask(SIG_BLOCK
, &nset
, &oset
);
177 old_handler
= sigarray
[signo
];
178 sigarray
[signo
] = handler
;
180 (void)sigprocmask(SIG_SETMASK
, &oset
, NULL
);
186 do_default_handler(int signo
, int flags
)
188 struct sigaction nsa
;
189 struct sigaction osa
;
195 (void)sigemptyset(&nsa
.sa_mask
);
196 nsa
.sa_flags
= flags
;
197 nsa
.sa_handler
= SIG_DFL
;
198 (void)sigaction(signo
, &nsa
, &osa
);
200 (void)sigemptyset(&nset
);
201 (void)sigaddset(&nset
, signo
);
202 (void)sigprocmask(SIG_UNBLOCK
, &nset
, &oset
);
204 (void)kill(0, signo
);
206 (void)sigprocmask(SIG_SETMASK
, &oset
, NULL
);
207 (void)sigaction(signo
, &osa
, NULL
);
212 * Our generic signal handler.
215 sig_handler(int signo
)
220 (void)sigfillset(&nset
);
221 (void)sigprocmask(SIG_SETMASK
, &nset
, &oset
);
223 assert (signo
> 0 && signo
< NSIG
); /* Should be guaranteed. */
229 assert(/*CONSTCOND*/ 0); /* We should not be seeing these. */
230 do_default_handler(signo
, 0);
236 do_default_handler(signo
, 0);
244 if (sigarray
[signo
] == SIG_DFL
)
245 do_default_handler(signo
, SA_RESTART
);
248 (void)sigprocmask(SIG_SETMASK
, &oset
, NULL
);
252 * Setup the signal handlers.
260 struct sigaction osa
;
262 /* Block all signals while setting things. */
263 (void)sigfillset(&nset
);
264 (void)sigprocmask(SIG_BLOCK
, &nset
, &oset
);
267 * Flow Control - SIGTSTP, SIGTTIN, SIGTTOU, SIGCONT:
269 * We grab SIGTSTP, SIGTTIN, and SIGTTOU so that we post the
270 * signals before suspending so that they are available when
271 * we resume. If we were to use SIGCONT instead, they will
272 * not get posted until SIGCONT is unblocked, even though the
273 * process has resumed.
275 * NOTE: We default these to SA_RESTART here, but we need to
276 * change this in certain cases, e.g., when reading from a
279 (void)sigemptyset(&sa
.sa_mask
);
280 sa
.sa_flags
= SA_RESTART
;
281 sa
.sa_handler
= sig_handler
;
282 (void)sigaction(SIGTSTP
, &sa
, NULL
);
283 (void)sigaction(SIGTTIN
, &sa
, NULL
);
284 (void)sigaction(SIGTTOU
, &sa
, NULL
);
287 * SIGHUP, SIGINT, and SIGQUIT:
289 * SIGHUP and SIGINT are trapped unless they are being
292 * Currently, we let the default handler deal with SIGQUIT.
294 (void)sigemptyset(&sa
.sa_mask
);
296 sa
.sa_handler
= sig_handler
;
298 if (sigaction(SIGHUP
, &sa
, &osa
) != -1 && osa
.sa_handler
== SIG_IGN
)
299 (void)signal(SIGHUP
, SIG_IGN
);
301 if (sigaction(SIGINT
, &sa
, &osa
) != -1 && osa
.sa_handler
== SIG_IGN
)
302 (void)signal(SIGINT
, SIG_IGN
);
304 if (signal(SIGQUIT
, SIG_DFL
) == SIG_IGN
)
305 (void)signal(SIGQUIT
, SIG_IGN
);
308 * SIGCHLD and SIGPIPE:
310 * SIGCHLD is setup early in main. The handler lives in
311 * popen.c as it uses internals of that module.
313 * SIGPIPE is grabbed here. It is only used in
314 * lex.c:setup_piping(), cmd1.c:type1(), and cmd1.c:pipecmd().
316 (void)sigemptyset(&sa
.sa_mask
);
318 sa
.sa_handler
= sig_handler
;
319 (void)sigaction(SIGPIPE
, &sa
, NULL
);
322 * Make sure our structures are initialized.
323 * XXX: This should be unnecessary.
325 (void)memset(sigarray
, 0, sizeof(sigarray
));
326 SIGQUEUE_INIT(&sigqueue
);
328 /* Restore the signal mask. */
329 (void)sigprocmask(SIG_SETMASK
, &oset
, NULL
);
332 static struct { /* data shared by sig_hold() and sig_release() */
333 int depth
; /* depth of sig_hold() */
334 sigset_t oset
; /* old signal mask saved by sig_hold() */
338 * Hold signals SIGHUP, SIGINT, and SIGQUIT.
345 if (hold
.depth
++ == 0) {
346 (void)sigemptyset(&nset
);
347 (void)sigaddset(&nset
, SIGHUP
);
348 (void)sigaddset(&nset
, SIGINT
);
349 (void)sigaddset(&nset
, SIGQUIT
);
350 (void)sigprocmask(SIG_BLOCK
, &nset
, &hold
.oset
);
355 * Release signals SIGHUP, SIGINT, and SIGQUIT.
361 if (--hold
.depth
== 0)
362 (void)sigprocmask(SIG_SETMASK
, &hold
.oset
, NULL
);
366 * Unblock and ignore a signal.
369 sig_ignore(int sig
, struct sigaction
*osa
, sigset_t
*oset
)
371 struct sigaction act
;
375 (void)sigemptyset(&act
.sa_mask
);
376 act
.sa_flags
= SA_RESTART
;
377 act
.sa_handler
= SIG_IGN
;
378 error
= sigaction(sig
, &act
, osa
);
381 (void)sigemptyset(&nset
);
382 (void)sigaddset(&nset
, sig
);
383 (void)sigprocmask(SIG_UNBLOCK
, &nset
, oset
);
384 } else if (oset
!= NULL
)
385 (void)sigprocmask(SIG_UNBLOCK
, NULL
, oset
);
391 * Restore a signal and the current signal mask.
394 sig_restore(int sig
, struct sigaction
*osa
, sigset_t
*oset
)
400 error
= sigprocmask(SIG_SETMASK
, oset
, NULL
);
402 error
= sigaction(sig
, osa
, NULL
);
408 * Change the current flags and (optionally) return the old sigaction
409 * structure so we can restore things later. This is used to turn
410 * SA_RESTART on or off.
413 sig_setflags(int signo
, int flags
, struct sigaction
*osa
)
417 if (sigaction(signo
, NULL
, &sa
) == -1)
422 return sigaction(signo
, &sa
, NULL
);