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