]> git.ipfire.org Git - thirdparty/bash.git/blame - sig.c
Bash-4.3 patch 7
[thirdparty/bash.git] / sig.c
CommitLineData
ccc6cda3
JA
1/* sig.c - interface for shell signal handlers and signal initialization. */
2
ac50fbac 3/* Copyright (C) 1994-2013 Free Software Foundation, Inc.
ccc6cda3
JA
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
3185942a
JA
7 Bash is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
ccc6cda3 11
3185942a
JA
12 Bash is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
ccc6cda3 16
3185942a
JA
17 You should have received a copy of the GNU General Public License
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.
19*/
ccc6cda3
JA
20
21#include "config.h"
22
23#include "bashtypes.h"
24
25#if defined (HAVE_UNISTD_H)
cce855bc
JA
26# ifdef _MINIX
27# include <sys/types.h>
28# endif
ccc6cda3
JA
29# include <unistd.h>
30#endif
31
32#include <stdio.h>
33#include <signal.h>
34
b80f6443
JA
35#include "bashintl.h"
36
ccc6cda3
JA
37#include "shell.h"
38#if defined (JOB_CONTROL)
39#include "jobs.h"
40#endif /* JOB_CONTROL */
41#include "siglist.h"
42#include "sig.h"
43#include "trap.h"
44
45#include "builtins/common.h"
ac50fbac 46#include "builtins/builtext.h"
ccc6cda3
JA
47
48#if defined (READLINE)
49# include "bashline.h"
d5d00961 50# include <readline/readline.h>
ccc6cda3
JA
51#endif
52
53#if defined (HISTORY)
54# include "bashhist.h"
55#endif
56
57extern int last_command_exit_value;
b80f6443 58extern int last_command_exit_signal;
ccc6cda3 59extern int return_catch_flag;
495aee44 60extern int loop_level, continuing, breaking, funcnest;
3185942a
JA
61extern int executing_list;
62extern int comsub_ignore_return;
ccc6cda3 63extern int parse_and_execute_level, shell_initialized;
495aee44
CR
64#if defined (HISTORY)
65extern int history_lines_this_session;
66#endif
d5d00961 67extern int no_line_editing;
ac50fbac
CR
68extern int wait_signal_received;
69extern sh_builtin_func_t *this_shell_builtin;
495aee44
CR
70
71extern void initialize_siglist ();
ccc6cda3
JA
72
73/* Non-zero after SIGINT. */
ac50fbac 74volatile sig_atomic_t interrupt_state = 0;
ccc6cda3 75
95732b49 76/* Non-zero after SIGWINCH */
ac50fbac
CR
77volatile sig_atomic_t sigwinch_received = 0;
78
79/* Non-zero after SIGTERM */
80volatile sig_atomic_t sigterm_received = 0;
95732b49 81
0628567a 82/* Set to the value of any terminating signal received. */
ac50fbac 83volatile sig_atomic_t terminating_signal = 0;
0628567a 84
ccc6cda3
JA
85/* The environment at the top-level R-E loop. We use this in
86 the case of error return. */
87procenv_t top_level;
88
89#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
90/* The signal masks that this shell runs with. */
91sigset_t top_level_mask;
92#endif /* JOB_CONTROL */
93
94/* When non-zero, we throw_to_top_level (). */
95int interrupt_immediately = 0;
96
0628567a
JA
97/* When non-zero, we call the terminating signal handler immediately. */
98int terminate_immediately = 0;
99
95732b49
JA
100#if defined (SIGWINCH)
101static SigHandler *old_winch = (SigHandler *)SIG_DFL;
102#endif
103
f73dda09 104static void initialize_shell_signals __P((void));
ccc6cda3
JA
105
106void
7117c2d2
JA
107initialize_signals (reinit)
108 int reinit;
ccc6cda3 109{
d166f048 110 initialize_shell_signals ();
ccc6cda3 111 initialize_job_signals ();
e8ce775d 112#if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
7117c2d2
JA
113 if (reinit == 0)
114 initialize_siglist ();
e8ce775d 115#endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
ccc6cda3
JA
116}
117
ccc6cda3
JA
118/* A structure describing a signal that terminates the shell if not
119 caught. The orig_handler member is present so children can reset
120 these signals back to their original handlers. */
121struct termsig {
122 int signum;
123 SigHandler *orig_handler;
95732b49 124 int orig_flags;
ccc6cda3
JA
125};
126
127#define NULL_HANDLER (SigHandler *)SIG_DFL
128
129/* The list of signals that would terminate the shell if not caught.
130 We catch them, but just so that we can write the history file,
131 and so forth. */
132static struct termsig terminating_signals[] = {
133#ifdef SIGHUP
95732b49 134{ SIGHUP, NULL_HANDLER, 0 },
ccc6cda3
JA
135#endif
136
137#ifdef SIGINT
95732b49 138{ SIGINT, NULL_HANDLER, 0 },
ccc6cda3
JA
139#endif
140
141#ifdef SIGILL
95732b49 142{ SIGILL, NULL_HANDLER, 0 },
ccc6cda3
JA
143#endif
144
145#ifdef SIGTRAP
95732b49 146{ SIGTRAP, NULL_HANDLER, 0 },
ccc6cda3
JA
147#endif
148
149#ifdef SIGIOT
95732b49 150{ SIGIOT, NULL_HANDLER, 0 },
ccc6cda3
JA
151#endif
152
153#ifdef SIGDANGER
95732b49 154{ SIGDANGER, NULL_HANDLER, 0 },
ccc6cda3
JA
155#endif
156
157#ifdef SIGEMT
95732b49 158{ SIGEMT, NULL_HANDLER, 0 },
ccc6cda3
JA
159#endif
160
161#ifdef SIGFPE
95732b49 162{ SIGFPE, NULL_HANDLER, 0 },
ccc6cda3
JA
163#endif
164
165#ifdef SIGBUS
95732b49 166{ SIGBUS, NULL_HANDLER, 0 },
ccc6cda3
JA
167#endif
168
169#ifdef SIGSEGV
95732b49 170{ SIGSEGV, NULL_HANDLER, 0 },
ccc6cda3
JA
171#endif
172
173#ifdef SIGSYS
95732b49 174{ SIGSYS, NULL_HANDLER, 0 },
ccc6cda3
JA
175#endif
176
177#ifdef SIGPIPE
95732b49 178{ SIGPIPE, NULL_HANDLER, 0 },
ccc6cda3
JA
179#endif
180
181#ifdef SIGALRM
95732b49 182{ SIGALRM, NULL_HANDLER, 0 },
ccc6cda3
JA
183#endif
184
185#ifdef SIGTERM
95732b49 186{ SIGTERM, NULL_HANDLER, 0 },
ccc6cda3
JA
187#endif
188
189#ifdef SIGXCPU
95732b49 190{ SIGXCPU, NULL_HANDLER, 0 },
ccc6cda3
JA
191#endif
192
193#ifdef SIGXFSZ
95732b49 194{ SIGXFSZ, NULL_HANDLER, 0 },
ccc6cda3
JA
195#endif
196
197#ifdef SIGVTALRM
95732b49 198{ SIGVTALRM, NULL_HANDLER, 0 },
ccc6cda3
JA
199#endif
200
bb70624e 201#if 0
ccc6cda3 202#ifdef SIGPROF
95732b49 203{ SIGPROF, NULL_HANDLER, 0 },
ccc6cda3 204#endif
bb70624e 205#endif
ccc6cda3
JA
206
207#ifdef SIGLOST
95732b49 208{ SIGLOST, NULL_HANDLER, 0 },
ccc6cda3
JA
209#endif
210
211#ifdef SIGUSR1
95732b49 212{ SIGUSR1, NULL_HANDLER, 0 },
ccc6cda3
JA
213#endif
214
215#ifdef SIGUSR2
95732b49 216{ SIGUSR2, NULL_HANDLER, 0 },
ccc6cda3
JA
217#endif
218};
219
220#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
221
222#define XSIG(x) (terminating_signals[x].signum)
223#define XHANDLER(x) (terminating_signals[x].orig_handler)
95732b49 224#define XSAFLAGS(x) (terminating_signals[x].orig_flags)
ccc6cda3 225
d166f048
JA
226static int termsigs_initialized = 0;
227
ccc6cda3 228/* Initialize signals that will terminate the shell to do some
d166f048 229 unwind protection. For non-interactive shells, we only call
495aee44
CR
230 this when a trap is defined for EXIT (0) or when trap is run
231 to display signal dispositions. */
d166f048 232void
ccc6cda3
JA
233initialize_terminating_signals ()
234{
235 register int i;
d166f048
JA
236#if defined (HAVE_POSIX_SIGNALS)
237 struct sigaction act, oact;
238#endif
239
240 if (termsigs_initialized)
241 return;
ccc6cda3
JA
242
243 /* The following code is to avoid an expensive call to
244 set_signal_handler () for each terminating_signals. Fortunately,
245 this is possible in Posix. Unfortunately, we have to call signal ()
246 on non-Posix systems for each signal in terminating_signals. */
247#if defined (HAVE_POSIX_SIGNALS)
0628567a 248 act.sa_handler = termsig_sighandler;
ccc6cda3
JA
249 act.sa_flags = 0;
250 sigemptyset (&act.sa_mask);
251 sigemptyset (&oact.sa_mask);
252 for (i = 0; i < TERMSIGS_LENGTH; i++)
253 sigaddset (&act.sa_mask, XSIG (i));
254 for (i = 0; i < TERMSIGS_LENGTH; i++)
255 {
7117c2d2
JA
256 /* If we've already trapped it, don't do anything. */
257 if (signal_is_trapped (XSIG (i)))
258 continue;
259
ccc6cda3 260 sigaction (XSIG (i), &act, &oact);
d166f048 261 XHANDLER(i) = oact.sa_handler;
95732b49 262 XSAFLAGS(i) = oact.sa_flags;
ccc6cda3
JA
263 /* Don't do anything with signals that are ignored at shell entry
264 if the shell is not interactive. */
495aee44
CR
265 /* XXX - should we do this for interactive shells, too? */
266 if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
28ef6c31 267 {
ccc6cda3 268 sigaction (XSIG (i), &oact, &act);
ac50fbac 269 set_signal_hard_ignored (XSIG (i));
28ef6c31 270 }
cce855bc 271#if defined (SIGPROF) && !defined (_MINIX)
d166f048 272 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
28ef6c31 273 sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
cce855bc 274#endif /* SIGPROF && !_MINIX */
ccc6cda3
JA
275 }
276
277#else /* !HAVE_POSIX_SIGNALS */
278
279 for (i = 0; i < TERMSIGS_LENGTH; i++)
280 {
7117c2d2
JA
281 /* If we've already trapped it, don't do anything. */
282 if (signal_is_trapped (XSIG (i)))
283 continue;
284
0628567a 285 XHANDLER(i) = signal (XSIG (i), termsig_sighandler);
95732b49 286 XSAFLAGS(i) = 0;
ccc6cda3
JA
287 /* Don't do anything with signals that are ignored at shell entry
288 if the shell is not interactive. */
495aee44
CR
289 /* XXX - should we do this for interactive shells, too? */
290 if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
ccc6cda3 291 {
28ef6c31 292 signal (XSIG (i), SIG_IGN);
ac50fbac 293 set_signal_hard_ignored (XSIG (i));
ccc6cda3 294 }
cce855bc 295#ifdef SIGPROF
d166f048 296 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
28ef6c31 297 signal (XSIG (i), XHANDLER (i));
cce855bc 298#endif
ccc6cda3
JA
299 }
300
301#endif /* !HAVE_POSIX_SIGNALS */
302
d166f048
JA
303 termsigs_initialized = 1;
304}
305
306static void
307initialize_shell_signals ()
308{
309 if (interactive)
310 initialize_terminating_signals ();
311
ccc6cda3
JA
312#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
313 /* All shells use the signal mask they inherit, and pass it along
314 to child processes. Children will never block SIGCHLD, though. */
315 sigemptyset (&top_level_mask);
316 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
bb70624e 317# if defined (SIGCHLD)
ccc6cda3 318 sigdelset (&top_level_mask, SIGCHLD);
bb70624e 319# endif
ccc6cda3
JA
320#endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
321
322 /* And, some signals that are specifically ignored by the shell. */
323 set_signal_handler (SIGQUIT, SIG_IGN);
324
325 if (interactive)
326 {
327 set_signal_handler (SIGINT, sigint_sighandler);
ac50fbac
CR
328 get_original_signal (SIGTERM);
329 if (signal_is_hard_ignored (SIGTERM) == 0)
330 set_signal_handler (SIGTERM, sigterm_sighandler);
95732b49 331 set_sigwinch_handler ();
ccc6cda3
JA
332 }
333}
334
335void
336reset_terminating_signals ()
337{
338 register int i;
ccc6cda3
JA
339#if defined (HAVE_POSIX_SIGNALS)
340 struct sigaction act;
d166f048 341#endif
ccc6cda3 342
d166f048
JA
343 if (termsigs_initialized == 0)
344 return;
345
346#if defined (HAVE_POSIX_SIGNALS)
ccc6cda3
JA
347 act.sa_flags = 0;
348 sigemptyset (&act.sa_mask);
349 for (i = 0; i < TERMSIGS_LENGTH; i++)
350 {
351 /* Skip a signal if it's trapped or handled specially, because the
352 trap code will restore the correct value. */
353 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
354 continue;
355
356 act.sa_handler = XHANDLER (i);
95732b49 357 act.sa_flags = XSAFLAGS (i);
ccc6cda3
JA
358 sigaction (XSIG (i), &act, (struct sigaction *) NULL);
359 }
360#else /* !HAVE_POSIX_SIGNALS */
361 for (i = 0; i < TERMSIGS_LENGTH; i++)
362 {
363 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
364 continue;
365
366 signal (XSIG (i), XHANDLER (i));
367 }
368#endif /* !HAVE_POSIX_SIGNALS */
ac50fbac
CR
369
370 termsigs_initialized = 0;
ccc6cda3
JA
371}
372#undef XSIG
373#undef XHANDLER
374
f1be666c
JA
375/* Run some of the cleanups that should be performed when we run
376 jump_to_top_level from a builtin command context. XXX - might want to
377 also call reset_parser here. */
378void
379top_level_cleanup ()
380{
381 /* Clean up string parser environment. */
382 while (parse_and_execute_level)
383 parse_and_execute_cleanup ();
384
385#if defined (PROCESS_SUBSTITUTION)
386 unlink_fifo_list ();
387#endif /* PROCESS_SUBSTITUTION */
388
389 run_unwind_protects ();
495aee44 390 loop_level = continuing = breaking = funcnest = 0;
3185942a 391 executing_list = comsub_ignore_return = return_catch_flag = 0;
f1be666c
JA
392}
393
ccc6cda3
JA
394/* What to do when we've been interrupted, and it is safe to handle it. */
395void
396throw_to_top_level ()
397{
398 int print_newline = 0;
399
400 if (interrupt_state)
401 {
ac50fbac
CR
402 if (last_command_exit_value < 128)
403 last_command_exit_value = 128 + SIGINT;
ccc6cda3
JA
404 print_newline = 1;
405 DELINTERRUPT;
406 }
407
408 if (interrupt_state)
409 return;
410
b80f6443
JA
411 last_command_exit_signal = (last_command_exit_value > 128) ?
412 (last_command_exit_value - 128) : 0;
ccc6cda3
JA
413 last_command_exit_value |= 128;
414
415 /* Run any traps set on SIGINT. */
416 run_interrupt_trap ();
417
3185942a 418 /* Clean up string parser environment. */
ccc6cda3
JA
419 while (parse_and_execute_level)
420 parse_and_execute_cleanup ();
421
422#if defined (JOB_CONTROL)
28ef6c31 423 give_terminal_to (shell_pgrp, 0);
ccc6cda3
JA
424#endif /* JOB_CONTROL */
425
426#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
ac50fbac
CR
427 /* This needs to stay because jobs.c:make_child() uses it without resetting
428 the signal mask. */
ccc6cda3
JA
429 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
430#endif
431
432 reset_parser ();
433
434#if defined (READLINE)
435 if (interactive)
3185942a 436 bashline_reset ();
ccc6cda3
JA
437#endif /* READLINE */
438
439#if defined (PROCESS_SUBSTITUTION)
440 unlink_fifo_list ();
441#endif /* PROCESS_SUBSTITUTION */
442
443 run_unwind_protects ();
495aee44 444 loop_level = continuing = breaking = funcnest = 0;
3185942a 445 executing_list = comsub_ignore_return = return_catch_flag = 0;
ccc6cda3
JA
446
447 if (interactive && print_newline)
448 {
449 fflush (stdout);
450 fprintf (stderr, "\n");
451 fflush (stderr);
452 }
453
454 /* An interrupted `wait' command in a script does not exit the script. */
455 if (interactive || (interactive_shell && !shell_initialized) ||
456 (print_newline && signal_is_trapped (SIGINT)))
457 jump_to_top_level (DISCARD);
458 else
459 jump_to_top_level (EXITPROG);
460}
461
462/* This is just here to isolate the longjmp calls. */
463void
464jump_to_top_level (value)
465 int value;
466{
467 longjmp (top_level, value);
468}
469
470sighandler
0628567a 471termsig_sighandler (sig)
ccc6cda3
JA
472 int sig;
473{
89a92869
CR
474 /* If we get called twice with the same signal before handling it,
475 terminate right away. */
476 if (
477#ifdef SIGHUP
478 sig != SIGHUP &&
479#endif
480#ifdef SIGINT
481 sig != SIGINT &&
482#endif
483#ifdef SIGDANGER
484 sig != SIGDANGER &&
485#endif
486#ifdef SIGPIPE
487 sig != SIGPIPE &&
488#endif
489#ifdef SIGALRM
490 sig != SIGALRM &&
491#endif
492#ifdef SIGTERM
493 sig != SIGTERM &&
494#endif
495#ifdef SIGXCPU
496 sig != SIGXCPU &&
497#endif
498#ifdef SIGXFSZ
499 sig != SIGXFSZ &&
500#endif
501#ifdef SIGVTALRM
502 sig != SIGVTALRM &&
503#endif
504#ifdef SIGLOST
505 sig != SIGLOST &&
506#endif
507#ifdef SIGUSR1
508 sig != SIGUSR1 &&
509#endif
510#ifdef SIGUSR2
511 sig != SIGUSR2 &&
512#endif
513 sig == terminating_signal)
514 terminate_immediately = 1;
515
0628567a
JA
516 terminating_signal = sig;
517
3185942a 518 /* XXX - should this also trigger when interrupt_immediately is set? */
0628567a
JA
519 if (terminate_immediately)
520 {
495aee44
CR
521#if defined (HISTORY)
522 /* XXX - will inhibit history file being written */
d5d00961
CR
523# if defined (READLINE)
524 if (interactive_shell == 0 || interactive == 0 || (sig != SIGHUP && sig != SIGTERM) || no_line_editing || (RL_ISSTATE (RL_STATE_READCMD) == 0))
525# endif
526 history_lines_this_session = 0;
495aee44 527#endif
0628567a
JA
528 terminate_immediately = 0;
529 termsig_handler (sig);
530 }
531
ac50fbac
CR
532#if defined (READLINE)
533 /* Set the event hook so readline will call it after the signal handlers
534 finish executing, so if this interrupted character input we can get
535 quick response. */
536 if (interactive_shell && interactive && no_line_editing == 0)
537 bashline_set_event_hook ();
538#endif
539
0628567a
JA
540 SIGRETURN (0);
541}
542
543void
544termsig_handler (sig)
545 int sig;
546{
547 static int handling_termsig = 0;
548
549 /* Simple semaphore to keep this function from being executed multiple
550 times. Since we no longer are running as a signal handler, we don't
551 block multiple occurrences of the terminating signals while running. */
552 if (handling_termsig)
553 return;
554 handling_termsig = 1;
555 terminating_signal = 0; /* keep macro from re-testing true. */
556
95732b49 557 /* I don't believe this condition ever tests true. */
ccc6cda3
JA
558 if (sig == SIGINT && signal_is_trapped (SIGINT))
559 run_interrupt_trap ();
560
561#if defined (HISTORY)
ac50fbac
CR
562 /* If we don't do something like this, the history will not be saved when
563 an interactive shell is running in a terminal window that gets closed
564 with the `close' button. We can't test for RL_STATE_READCMD because
565 readline no longer handles SIGTERM synchronously. */
566 if (interactive_shell && interactive && (sig == SIGHUP || sig == SIGTERM) && remember_on_history)
ccc6cda3
JA
567 maybe_save_shell_history ();
568#endif /* HISTORY */
569
570#if defined (JOB_CONTROL)
0001803f 571 if (sig == SIGHUP && (interactive || (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB))))
ccc6cda3
JA
572 hangup_all_jobs ();
573 end_job_control ();
574#endif /* JOB_CONTROL */
575
576#if defined (PROCESS_SUBSTITUTION)
577 unlink_fifo_list ();
578#endif /* PROCESS_SUBSTITUTION */
579
3185942a 580 /* Reset execution context */
495aee44 581 loop_level = continuing = breaking = funcnest = 0;
3185942a
JA
582 executing_list = comsub_ignore_return = return_catch_flag = 0;
583
ac50fbac 584 run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
ccc6cda3
JA
585 set_signal_handler (sig, SIG_DFL);
586 kill (getpid (), sig);
ccc6cda3
JA
587}
588
589/* What we really do when SIGINT occurs. */
590sighandler
591sigint_sighandler (sig)
592 int sig;
593{
594#if defined (MUST_REINSTALL_SIGHANDLERS)
595 signal (sig, sigint_sighandler);
596#endif
597
598 /* interrupt_state needs to be set for the stack of interrupts to work
599 right. Should it be set unconditionally? */
600 if (interrupt_state == 0)
601 ADDINTERRUPT;
602
ac50fbac
CR
603 /* We will get here in interactive shells with job control active; allow
604 an interactive wait to be interrupted. */
605 if (this_shell_builtin && this_shell_builtin == wait_builtin)
606 {
607 last_command_exit_value = 128 + sig;
608 wait_signal_received = sig;
609 SIGRETURN (0);
610 }
611
ccc6cda3
JA
612 if (interrupt_immediately)
613 {
614 interrupt_immediately = 0;
0001803f 615 last_command_exit_value = 128 + sig;
ccc6cda3
JA
616 throw_to_top_level ();
617 }
ac50fbac
CR
618#if defined (READLINE)
619 /* Set the event hook so readline will call it after the signal handlers
620 finish executing, so if this interrupted character input we can get
621 quick response. */
622 else if (RL_ISSTATE (RL_STATE_SIGHANDLER))
623 bashline_set_event_hook ();
624#endif
ccc6cda3
JA
625
626 SIGRETURN (0);
627}
628
95732b49
JA
629#if defined (SIGWINCH)
630sighandler
631sigwinch_sighandler (sig)
632 int sig;
633{
634#if defined (MUST_REINSTALL_SIGHANDLERS)
635 set_signal_handler (SIGWINCH, sigwinch_sighandler);
636#endif /* MUST_REINSTALL_SIGHANDLERS */
637 sigwinch_received = 1;
638 SIGRETURN (0);
639}
640#endif /* SIGWINCH */
641
642void
643set_sigwinch_handler ()
644{
645#if defined (SIGWINCH)
646 old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
647#endif
648}
649
650void
651unset_sigwinch_handler ()
652{
653#if defined (SIGWINCH)
654 set_signal_handler (SIGWINCH, old_winch);
655#endif
656}
657
ac50fbac
CR
658sighandler
659sigterm_sighandler (sig)
660 int sig;
661{
662 sigterm_received = 1; /* XXX - counter? */
663 SIGRETURN (0);
664}
665
ccc6cda3
JA
666/* Signal functions used by the rest of the code. */
667#if !defined (HAVE_POSIX_SIGNALS)
668
ccc6cda3
JA
669/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
670sigprocmask (operation, newset, oldset)
671 int operation, *newset, *oldset;
672{
673 int old, new;
674
675 if (newset)
676 new = *newset;
677 else
678 new = 0;
679
680 switch (operation)
681 {
682 case SIG_BLOCK:
683 old = sigblock (new);
684 break;
685
686 case SIG_SETMASK:
ac50fbac 687 old = sigsetmask (new);
ccc6cda3
JA
688 break;
689
690 default:
b80f6443 691 internal_error (_("sigprocmask: %d: invalid operation"), operation);
ccc6cda3
JA
692 }
693
694 if (oldset)
695 *oldset = old;
696}
ccc6cda3
JA
697
698#else
699
700#if !defined (SA_INTERRUPT)
701# define SA_INTERRUPT 0
702#endif
703
704#if !defined (SA_RESTART)
705# define SA_RESTART 0
706#endif
707
708SigHandler *
709set_signal_handler (sig, handler)
710 int sig;
711 SigHandler *handler;
712{
713 struct sigaction act, oact;
714
715 act.sa_handler = handler;
716 act.sa_flags = 0;
495aee44
CR
717
718 /* XXX - bash-4.2 */
719 /* We don't want a child death to interrupt interruptible system calls, even
720 if we take the time to reap children */
ac50fbac 721#if defined (SIGCHLD)
30d188c2 722 if (sig == SIGCHLD)
495aee44 723 act.sa_flags |= SA_RESTART; /* XXX */
ac50fbac
CR
724#endif
725 /* If we're installing a SIGTERM handler for interactive shells, we want
726 it to be as close to SIG_IGN as possible. */
727 if (sig == SIGTERM && handler == sigterm_sighandler)
728 act.sa_flags |= SA_RESTART; /* XXX */
495aee44 729
ccc6cda3
JA
730 sigemptyset (&act.sa_mask);
731 sigemptyset (&oact.sa_mask);
ac50fbac
CR
732 if (sigaction (sig, &act, &oact) == 0)
733 return (oact.sa_handler);
734 else
735 return (SIG_DFL);
ccc6cda3
JA
736}
737#endif /* HAVE_POSIX_SIGNALS */