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