1 /* sig.c - interface for shell signal handlers and signal initialization. */
3 /* Copyright (C) 1994-2006 Free Software Foundation, Inc.
5 This file is part of GNU Bash, the Bourne Again SHell.
7 Bash is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
23 #include "bashtypes.h"
25 #if defined (HAVE_UNISTD_H)
27 # include <sys/types.h>
38 #if defined (JOB_CONTROL)
40 #endif /* JOB_CONTROL */
45 #include "builtins/common.h"
47 #if defined (READLINE)
48 # include "bashline.h"
52 # include "bashhist.h"
55 extern int last_command_exit_value
;
56 extern int last_command_exit_signal
;
57 extern int return_catch_flag
;
58 extern int loop_level
, continuing
, breaking
;
59 extern int parse_and_execute_level
, shell_initialized
;
61 /* Non-zero after SIGINT. */
62 volatile int interrupt_state
= 0;
64 /* Non-zero after SIGWINCH */
65 volatile int sigwinch_received
= 0;
67 /* Set to the value of any terminating signal received. */
68 volatile int terminating_signal
= 0;
70 /* The environment at the top-level R-E loop. We use this in
71 the case of error return. */
74 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
75 /* The signal masks that this shell runs with. */
76 sigset_t top_level_mask
;
77 #endif /* JOB_CONTROL */
79 /* When non-zero, we throw_to_top_level (). */
80 int interrupt_immediately
= 0;
82 /* When non-zero, we call the terminating signal handler immediately. */
83 int terminate_immediately
= 0;
85 #if defined (SIGWINCH)
86 static SigHandler
*old_winch
= (SigHandler
*)SIG_DFL
;
89 static void initialize_shell_signals
__P((void));
92 initialize_signals (reinit
)
95 initialize_shell_signals ();
96 initialize_job_signals ();
97 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
99 initialize_siglist ();
100 #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
103 /* A structure describing a signal that terminates the shell if not
104 caught. The orig_handler member is present so children can reset
105 these signals back to their original handlers. */
108 SigHandler
*orig_handler
;
112 #define NULL_HANDLER (SigHandler *)SIG_DFL
114 /* The list of signals that would terminate the shell if not caught.
115 We catch them, but just so that we can write the history file,
117 static struct termsig terminating_signals
[] = {
119 { SIGHUP
, NULL_HANDLER
, 0 },
123 { SIGINT
, NULL_HANDLER
, 0 },
127 { SIGILL
, NULL_HANDLER
, 0 },
131 { SIGTRAP
, NULL_HANDLER
, 0 },
135 { SIGIOT
, NULL_HANDLER
, 0 },
139 { SIGDANGER
, NULL_HANDLER
, 0 },
143 { SIGEMT
, NULL_HANDLER
, 0 },
147 { SIGFPE
, NULL_HANDLER
, 0 },
151 { SIGBUS
, NULL_HANDLER
, 0 },
155 { SIGSEGV
, NULL_HANDLER
, 0 },
159 { SIGSYS
, NULL_HANDLER
, 0 },
163 { SIGPIPE
, NULL_HANDLER
, 0 },
167 { SIGALRM
, NULL_HANDLER
, 0 },
171 { SIGTERM
, NULL_HANDLER
, 0 },
175 { SIGXCPU
, NULL_HANDLER
, 0 },
179 { SIGXFSZ
, NULL_HANDLER
, 0 },
183 { SIGVTALRM
, NULL_HANDLER
, 0 },
188 { SIGPROF
, NULL_HANDLER
, 0 },
193 { SIGLOST
, NULL_HANDLER
, 0 },
197 { SIGUSR1
, NULL_HANDLER
, 0 },
201 { SIGUSR2
, NULL_HANDLER
, 0 },
205 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
207 #define XSIG(x) (terminating_signals[x].signum)
208 #define XHANDLER(x) (terminating_signals[x].orig_handler)
209 #define XSAFLAGS(x) (terminating_signals[x].orig_flags)
211 static int termsigs_initialized
= 0;
213 /* Initialize signals that will terminate the shell to do some
214 unwind protection. For non-interactive shells, we only call
215 this when a trap is defined for EXIT (0). */
217 initialize_terminating_signals ()
220 #if defined (HAVE_POSIX_SIGNALS)
221 struct sigaction act
, oact
;
224 if (termsigs_initialized
)
227 /* The following code is to avoid an expensive call to
228 set_signal_handler () for each terminating_signals. Fortunately,
229 this is possible in Posix. Unfortunately, we have to call signal ()
230 on non-Posix systems for each signal in terminating_signals. */
231 #if defined (HAVE_POSIX_SIGNALS)
232 act
.sa_handler
= termsig_sighandler
;
234 sigemptyset (&act
.sa_mask
);
235 sigemptyset (&oact
.sa_mask
);
236 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
237 sigaddset (&act
.sa_mask
, XSIG (i
));
238 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
240 /* If we've already trapped it, don't do anything. */
241 if (signal_is_trapped (XSIG (i
)))
244 sigaction (XSIG (i
), &act
, &oact
);
245 XHANDLER(i
) = oact
.sa_handler
;
246 XSAFLAGS(i
) = oact
.sa_flags
;
247 /* Don't do anything with signals that are ignored at shell entry
248 if the shell is not interactive. */
249 if (!interactive_shell
&& XHANDLER (i
) == SIG_IGN
)
251 sigaction (XSIG (i
), &oact
, &act
);
252 set_signal_ignored (XSIG (i
));
254 #if defined (SIGPROF) && !defined (_MINIX)
255 if (XSIG (i
) == SIGPROF
&& XHANDLER (i
) != SIG_DFL
&& XHANDLER (i
) != SIG_IGN
)
256 sigaction (XSIG (i
), &oact
, (struct sigaction
*)NULL
);
257 #endif /* SIGPROF && !_MINIX */
260 #else /* !HAVE_POSIX_SIGNALS */
262 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
264 /* If we've already trapped it, don't do anything. */
265 if (signal_is_trapped (XSIG (i
)))
268 XHANDLER(i
) = signal (XSIG (i
), termsig_sighandler
);
270 /* Don't do anything with signals that are ignored at shell entry
271 if the shell is not interactive. */
272 if (!interactive_shell
&& XHANDLER (i
) == SIG_IGN
)
274 signal (XSIG (i
), SIG_IGN
);
275 set_signal_ignored (XSIG (i
));
278 if (XSIG (i
) == SIGPROF
&& XHANDLER (i
) != SIG_DFL
&& XHANDLER (i
) != SIG_IGN
)
279 signal (XSIG (i
), XHANDLER (i
));
283 #endif /* !HAVE_POSIX_SIGNALS */
285 termsigs_initialized
= 1;
289 initialize_shell_signals ()
292 initialize_terminating_signals ();
294 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
295 /* All shells use the signal mask they inherit, and pass it along
296 to child processes. Children will never block SIGCHLD, though. */
297 sigemptyset (&top_level_mask
);
298 sigprocmask (SIG_BLOCK
, (sigset_t
*)NULL
, &top_level_mask
);
299 # if defined (SIGCHLD)
300 sigdelset (&top_level_mask
, SIGCHLD
);
302 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
304 /* And, some signals that are specifically ignored by the shell. */
305 set_signal_handler (SIGQUIT
, SIG_IGN
);
309 set_signal_handler (SIGINT
, sigint_sighandler
);
310 set_signal_handler (SIGTERM
, SIG_IGN
);
311 set_sigwinch_handler ();
316 reset_terminating_signals ()
319 #if defined (HAVE_POSIX_SIGNALS)
320 struct sigaction act
;
323 if (termsigs_initialized
== 0)
326 #if defined (HAVE_POSIX_SIGNALS)
328 sigemptyset (&act
.sa_mask
);
329 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
331 /* Skip a signal if it's trapped or handled specially, because the
332 trap code will restore the correct value. */
333 if (signal_is_trapped (XSIG (i
)) || signal_is_special (XSIG (i
)))
336 act
.sa_handler
= XHANDLER (i
);
337 act
.sa_flags
= XSAFLAGS (i
);
338 sigaction (XSIG (i
), &act
, (struct sigaction
*) NULL
);
340 #else /* !HAVE_POSIX_SIGNALS */
341 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
343 if (signal_is_trapped (XSIG (i
)) || signal_is_special (XSIG (i
)))
346 signal (XSIG (i
), XHANDLER (i
));
348 #endif /* !HAVE_POSIX_SIGNALS */
353 /* Run some of the cleanups that should be performed when we run
354 jump_to_top_level from a builtin command context. XXX - might want to
355 also call reset_parser here. */
359 /* Clean up string parser environment. */
360 while (parse_and_execute_level
)
361 parse_and_execute_cleanup ();
363 #if defined (PROCESS_SUBSTITUTION)
365 #endif /* PROCESS_SUBSTITUTION */
367 run_unwind_protects ();
368 loop_level
= continuing
= breaking
= 0;
369 return_catch_flag
= 0;
372 /* What to do when we've been interrupted, and it is safe to handle it. */
374 throw_to_top_level ()
376 int print_newline
= 0;
387 last_command_exit_signal
= (last_command_exit_value
> 128) ?
388 (last_command_exit_value
- 128) : 0;
389 last_command_exit_value
|= 128;
391 /* Run any traps set on SIGINT. */
392 run_interrupt_trap ();
394 /* Cleanup string parser environment. */
395 while (parse_and_execute_level
)
396 parse_and_execute_cleanup ();
398 #if defined (JOB_CONTROL)
399 give_terminal_to (shell_pgrp
, 0);
400 #endif /* JOB_CONTROL */
402 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
403 /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
404 sigprocmask (SIG_SETMASK
, &top_level_mask
, (sigset_t
*)NULL
);
409 #if defined (READLINE)
411 bashline_reinitialize ();
412 #endif /* READLINE */
414 #if defined (PROCESS_SUBSTITUTION)
416 #endif /* PROCESS_SUBSTITUTION */
418 run_unwind_protects ();
419 loop_level
= continuing
= breaking
= 0;
420 return_catch_flag
= 0;
422 if (interactive
&& print_newline
)
425 fprintf (stderr
, "\n");
429 /* An interrupted `wait' command in a script does not exit the script. */
430 if (interactive
|| (interactive_shell
&& !shell_initialized
) ||
431 (print_newline
&& signal_is_trapped (SIGINT
)))
432 jump_to_top_level (DISCARD
);
434 jump_to_top_level (EXITPROG
);
437 /* This is just here to isolate the longjmp calls. */
439 jump_to_top_level (value
)
442 longjmp (top_level
, value
);
446 termsig_sighandler (sig
)
449 terminating_signal
= sig
;
451 if (terminate_immediately
)
453 terminate_immediately
= 0;
454 termsig_handler (sig
);
461 termsig_handler (sig
)
464 static int handling_termsig
= 0;
466 /* Simple semaphore to keep this function from being executed multiple
467 times. Since we no longer are running as a signal handler, we don't
468 block multiple occurrences of the terminating signals while running. */
469 if (handling_termsig
)
471 handling_termsig
= 1;
472 terminating_signal
= 0; /* keep macro from re-testing true. */
474 /* I don't believe this condition ever tests true. */
475 if (sig
== SIGINT
&& signal_is_trapped (SIGINT
))
476 run_interrupt_trap ();
478 #if defined (HISTORY)
479 if (interactive_shell
&& sig
!= SIGABRT
)
480 maybe_save_shell_history ();
483 #if defined (JOB_CONTROL)
484 if (interactive
&& sig
== SIGHUP
)
487 #endif /* JOB_CONTROL */
489 #if defined (PROCESS_SUBSTITUTION)
491 #endif /* PROCESS_SUBSTITUTION */
494 set_signal_handler (sig
, SIG_DFL
);
495 kill (getpid (), sig
);
498 /* What we really do when SIGINT occurs. */
500 sigint_sighandler (sig
)
503 #if defined (MUST_REINSTALL_SIGHANDLERS)
504 signal (sig
, sigint_sighandler
);
507 /* interrupt_state needs to be set for the stack of interrupts to work
508 right. Should it be set unconditionally? */
509 if (interrupt_state
== 0)
512 if (interrupt_immediately
)
514 interrupt_immediately
= 0;
515 throw_to_top_level ();
521 #if defined (SIGWINCH)
523 sigwinch_sighandler (sig
)
526 #if defined (MUST_REINSTALL_SIGHANDLERS)
527 set_signal_handler (SIGWINCH
, sigwinch_sighandler
);
528 #endif /* MUST_REINSTALL_SIGHANDLERS */
529 sigwinch_received
= 1;
532 #endif /* SIGWINCH */
535 set_sigwinch_handler ()
537 #if defined (SIGWINCH)
538 old_winch
= set_signal_handler (SIGWINCH
, sigwinch_sighandler
);
543 unset_sigwinch_handler ()
545 #if defined (SIGWINCH)
546 set_signal_handler (SIGWINCH
, old_winch
);
550 /* Signal functions used by the rest of the code. */
551 #if !defined (HAVE_POSIX_SIGNALS)
553 #if defined (JOB_CONTROL)
554 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
555 sigprocmask (operation
, newset
, oldset
)
556 int operation
, *newset
, *oldset
;
568 old
= sigblock (new);
576 internal_error (_("sigprocmask: %d: invalid operation"), operation
);
582 #endif /* JOB_CONTROL */
586 #if !defined (SA_INTERRUPT)
587 # define SA_INTERRUPT 0
590 #if !defined (SA_RESTART)
591 # define SA_RESTART 0
595 set_signal_handler (sig
, handler
)
599 struct sigaction act
, oact
;
601 act
.sa_handler
= handler
;
605 act
.sa_flags
|= SA_INTERRUPT
; /* XXX */
607 act
.sa_flags
|= SA_RESTART
; /* XXX */
609 sigemptyset (&act
.sa_mask
);
610 sigemptyset (&oact
.sa_mask
);
611 sigaction (sig
, &act
, &oact
);
612 return (oact
.sa_handler
);
614 #endif /* HAVE_POSIX_SIGNALS */