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