1 /* sig.c - interface for shell signal handlers and signal initialization. */
3 /* Copyright (C) 1994-2005 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. */
64 /* Non-zero after SIGWINCH */
65 volatile int sigwinch_received = 0;
67 /* The environment at the top-level R-E loop. We use this in
68 the case of error return. */
71 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
72 /* The signal masks that this shell runs with. */
73 sigset_t top_level_mask;
74 #endif /* JOB_CONTROL */
76 /* When non-zero, we throw_to_top_level (). */
77 int interrupt_immediately = 0;
79 #if defined (SIGWINCH)
80 static SigHandler *old_winch = (SigHandler *)SIG_DFL;
83 static void initialize_shell_signals __P((void));
86 initialize_signals (reinit)
89 initialize_shell_signals ();
90 initialize_job_signals ();
91 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
93 initialize_siglist ();
94 #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
97 /* A structure describing a signal that terminates the shell if not
98 caught. The orig_handler member is present so children can reset
99 these signals back to their original handlers. */
102 SigHandler *orig_handler;
106 #define NULL_HANDLER (SigHandler *)SIG_DFL
108 /* The list of signals that would terminate the shell if not caught.
109 We catch them, but just so that we can write the history file,
111 static struct termsig terminating_signals[] = {
113 { SIGHUP, NULL_HANDLER, 0 },
117 { SIGINT, NULL_HANDLER, 0 },
121 { SIGILL, NULL_HANDLER, 0 },
125 { SIGTRAP, NULL_HANDLER, 0 },
129 { SIGIOT, NULL_HANDLER, 0 },
133 { SIGDANGER, NULL_HANDLER, 0 },
137 { SIGEMT, NULL_HANDLER, 0 },
141 { SIGFPE, NULL_HANDLER, 0 },
145 { SIGBUS, NULL_HANDLER, 0 },
149 { SIGSEGV, NULL_HANDLER, 0 },
153 { SIGSYS, NULL_HANDLER, 0 },
157 { SIGPIPE, NULL_HANDLER, 0 },
161 { SIGALRM, NULL_HANDLER, 0 },
165 { SIGTERM, NULL_HANDLER, 0 },
169 { SIGXCPU, NULL_HANDLER, 0 },
173 { SIGXFSZ, NULL_HANDLER, 0 },
177 { SIGVTALRM, NULL_HANDLER, 0 },
182 { SIGPROF, NULL_HANDLER, 0 },
187 { SIGLOST, NULL_HANDLER, 0 },
191 { SIGUSR1, NULL_HANDLER, 0 },
195 { SIGUSR2, NULL_HANDLER, 0 },
199 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
201 #define XSIG(x) (terminating_signals[x].signum)
202 #define XHANDLER(x) (terminating_signals[x].orig_handler)
203 #define XSAFLAGS(x) (terminating_signals[x].orig_flags)
205 static int termsigs_initialized = 0;
207 /* Initialize signals that will terminate the shell to do some
208 unwind protection. For non-interactive shells, we only call
209 this when a trap is defined for EXIT (0). */
211 initialize_terminating_signals ()
214 #if defined (HAVE_POSIX_SIGNALS)
215 struct sigaction act, oact;
218 if (termsigs_initialized)
221 /* The following code is to avoid an expensive call to
222 set_signal_handler () for each terminating_signals. Fortunately,
223 this is possible in Posix. Unfortunately, we have to call signal ()
224 on non-Posix systems for each signal in terminating_signals. */
225 #if defined (HAVE_POSIX_SIGNALS)
226 act.sa_handler = termination_unwind_protect;
228 sigemptyset (&act.sa_mask);
229 sigemptyset (&oact.sa_mask);
230 for (i = 0; i < TERMSIGS_LENGTH; i++)
231 sigaddset (&act.sa_mask, XSIG (i));
232 for (i = 0; i < TERMSIGS_LENGTH; i++)
234 /* If we've already trapped it, don't do anything. */
235 if (signal_is_trapped (XSIG (i)))
238 sigaction (XSIG (i), &act, &oact);
239 XHANDLER(i) = oact.sa_handler;
240 XSAFLAGS(i) = oact.sa_flags;
241 /* Don't do anything with signals that are ignored at shell entry
242 if the shell is not interactive. */
243 if (!interactive_shell && XHANDLER (i) == SIG_IGN)
245 sigaction (XSIG (i), &oact, &act);
246 set_signal_ignored (XSIG (i));
248 #if defined (SIGPROF) && !defined (_MINIX)
249 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
250 sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
251 #endif /* SIGPROF && !_MINIX */
254 #else /* !HAVE_POSIX_SIGNALS */
256 for (i = 0; i < TERMSIGS_LENGTH; i++)
258 /* If we've already trapped it, don't do anything. */
259 if (signal_is_trapped (XSIG (i)))
262 XHANDLER(i) = signal (XSIG (i), termination_unwind_protect);
264 /* Don't do anything with signals that are ignored at shell entry
265 if the shell is not interactive. */
266 if (!interactive_shell && XHANDLER (i) == SIG_IGN)
268 signal (XSIG (i), SIG_IGN);
269 set_signal_ignored (XSIG (i));
272 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
273 signal (XSIG (i), XHANDLER (i));
277 #endif /* !HAVE_POSIX_SIGNALS */
279 termsigs_initialized = 1;
283 initialize_shell_signals ()
286 initialize_terminating_signals ();
288 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
289 /* All shells use the signal mask they inherit, and pass it along
290 to child processes. Children will never block SIGCHLD, though. */
291 sigemptyset (&top_level_mask);
292 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
293 # if defined (SIGCHLD)
294 sigdelset (&top_level_mask, SIGCHLD);
296 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
298 /* And, some signals that are specifically ignored by the shell. */
299 set_signal_handler (SIGQUIT, SIG_IGN);
303 set_signal_handler (SIGINT, sigint_sighandler);
304 set_signal_handler (SIGTERM, SIG_IGN);
305 set_sigwinch_handler ();
310 reset_terminating_signals ()
313 #if defined (HAVE_POSIX_SIGNALS)
314 struct sigaction act;
317 if (termsigs_initialized == 0)
320 #if defined (HAVE_POSIX_SIGNALS)
322 sigemptyset (&act.sa_mask);
323 for (i = 0; i < TERMSIGS_LENGTH; i++)
325 /* Skip a signal if it's trapped or handled specially, because the
326 trap code will restore the correct value. */
327 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
330 act.sa_handler = XHANDLER (i);
331 act.sa_flags = XSAFLAGS (i);
332 sigaction (XSIG (i), &act, (struct sigaction *) NULL);
334 #else /* !HAVE_POSIX_SIGNALS */
335 for (i = 0; i < TERMSIGS_LENGTH; i++)
337 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
340 signal (XSIG (i), XHANDLER (i));
342 #endif /* !HAVE_POSIX_SIGNALS */
347 /* What to do when we've been interrupted, and it is safe to handle it. */
349 throw_to_top_level ()
351 int print_newline = 0;
362 last_command_exit_signal = (last_command_exit_value > 128) ?
363 (last_command_exit_value - 128) : 0;
364 last_command_exit_value |= 128;
366 /* Run any traps set on SIGINT. */
367 run_interrupt_trap ();
369 /* Cleanup string parser environment. */
370 while (parse_and_execute_level)
371 parse_and_execute_cleanup ();
373 #if defined (JOB_CONTROL)
374 give_terminal_to (shell_pgrp, 0);
375 #endif /* JOB_CONTROL */
377 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
378 /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
379 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
384 #if defined (READLINE)
386 bashline_reinitialize ();
387 #endif /* READLINE */
389 #if defined (PROCESS_SUBSTITUTION)
391 #endif /* PROCESS_SUBSTITUTION */
393 run_unwind_protects ();
394 loop_level = continuing = breaking = 0;
395 return_catch_flag = 0;
397 if (interactive && print_newline)
400 fprintf (stderr, "\n");
404 /* An interrupted `wait' command in a script does not exit the script. */
405 if (interactive || (interactive_shell && !shell_initialized) ||
406 (print_newline && signal_is_trapped (SIGINT)))
407 jump_to_top_level (DISCARD);
409 jump_to_top_level (EXITPROG);
412 /* This is just here to isolate the longjmp calls. */
414 jump_to_top_level (value)
417 longjmp (top_level, value);
421 termination_unwind_protect (sig)
424 /* I don't believe this condition ever tests true. */
425 if (sig == SIGINT && signal_is_trapped (SIGINT))
426 run_interrupt_trap ();
428 #if defined (HISTORY)
429 /* This might be unsafe, since it eventually calls functions POSIX says
430 not to call from signal handlers. If it's a problem, take this code
432 if (interactive_shell && sig != SIGABRT)
433 maybe_save_shell_history ();
436 #if defined (JOB_CONTROL)
437 if (interactive && sig == SIGHUP)
440 #endif /* JOB_CONTROL */
442 #if defined (PROCESS_SUBSTITUTION)
444 #endif /* PROCESS_SUBSTITUTION */
447 set_signal_handler (sig, SIG_DFL);
448 kill (getpid (), sig);
453 /* What we really do when SIGINT occurs. */
455 sigint_sighandler (sig)
458 #if defined (MUST_REINSTALL_SIGHANDLERS)
459 signal (sig, sigint_sighandler);
462 /* interrupt_state needs to be set for the stack of interrupts to work
463 right. Should it be set unconditionally? */
464 if (interrupt_state == 0)
467 if (interrupt_immediately)
469 interrupt_immediately = 0;
470 throw_to_top_level ();
476 #if defined (SIGWINCH)
478 sigwinch_sighandler (sig)
481 #if defined (MUST_REINSTALL_SIGHANDLERS)
482 set_signal_handler (SIGWINCH, sigwinch_sighandler);
483 #endif /* MUST_REINSTALL_SIGHANDLERS */
484 sigwinch_received = 1;
487 #endif /* SIGWINCH */
490 set_sigwinch_handler ()
492 #if defined (SIGWINCH)
493 old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
498 unset_sigwinch_handler ()
500 #if defined (SIGWINCH)
501 set_signal_handler (SIGWINCH, old_winch);
505 /* Signal functions used by the rest of the code. */
506 #if !defined (HAVE_POSIX_SIGNALS)
508 #if defined (JOB_CONTROL)
509 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
510 sigprocmask (operation, newset, oldset)
511 int operation, *newset, *oldset;
523 old = sigblock (new);
531 internal_error (_("sigprocmask: %d: invalid operation"), operation);
537 #endif /* JOB_CONTROL */
541 #if !defined (SA_INTERRUPT)
542 # define SA_INTERRUPT 0
545 #if !defined (SA_RESTART)
546 # define SA_RESTART 0
550 set_signal_handler (sig, handler)
554 struct sigaction act, oact;
556 act.sa_handler = handler;
560 act.sa_flags |= SA_INTERRUPT; /* XXX */
562 act.sa_flags |= SA_RESTART; /* XXX */
564 sigemptyset (&act.sa_mask);
565 sigemptyset (&oact.sa_mask);
566 sigaction (sig, &act, &oact);
567 return (oact.sa_handler);
569 #endif /* HAVE_POSIX_SIGNALS */