1 /* sig.c - interface for shell signal handlers and signal initialization. */
3 /* Copyright (C) 1994 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>
36 #if defined (JOB_CONTROL)
38 #endif /* JOB_CONTROL */
43 #include "builtins/common.h"
45 #if defined (READLINE)
46 # include "bashline.h"
50 # include "bashhist.h"
53 extern int last_command_exit_value;
54 extern int return_catch_flag;
55 extern int loop_level, continuing, breaking;
56 extern int parse_and_execute_level, shell_initialized;
57 extern int startup_state;
59 /* Non-zero after SIGINT. */
62 /* The environment at the top-level R-E loop. We use this in
63 the case of error return. */
66 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
67 /* The signal masks that this shell runs with. */
68 sigset_t top_level_mask;
69 #endif /* JOB_CONTROL */
71 /* When non-zero, we throw_to_top_level (). */
72 int interrupt_immediately = 0;
74 static void initialize_shell_signals __P((void));
79 initialize_shell_signals ();
80 initialize_job_signals ();
81 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
82 initialize_siglist ();
83 #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
87 reinitialize_signals ()
89 initialize_shell_signals ();
90 initialize_job_signals ();
93 /* A structure describing a signal that terminates the shell if not
94 caught. The orig_handler member is present so children can reset
95 these signals back to their original handlers. */
98 SigHandler *orig_handler;
101 #define NULL_HANDLER (SigHandler *)SIG_DFL
103 /* The list of signals that would terminate the shell if not caught.
104 We catch them, but just so that we can write the history file,
106 static struct termsig terminating_signals[] = {
108 { SIGHUP, NULL_HANDLER },
112 { SIGINT, NULL_HANDLER },
116 { SIGILL, NULL_HANDLER },
120 { SIGTRAP, NULL_HANDLER },
124 { SIGIOT, NULL_HANDLER },
128 { SIGDANGER, NULL_HANDLER },
132 { SIGEMT, NULL_HANDLER },
136 { SIGFPE, NULL_HANDLER },
140 { SIGBUS, NULL_HANDLER },
144 { SIGSEGV, NULL_HANDLER },
148 { SIGSYS, NULL_HANDLER },
152 { SIGPIPE, NULL_HANDLER },
156 { SIGALRM, NULL_HANDLER },
160 { SIGTERM, NULL_HANDLER },
164 { SIGXCPU, NULL_HANDLER },
168 { SIGXFSZ, NULL_HANDLER },
172 { SIGVTALRM, NULL_HANDLER },
177 { SIGPROF, NULL_HANDLER },
182 { SIGLOST, NULL_HANDLER },
186 { SIGUSR1, NULL_HANDLER },
190 { SIGUSR2, NULL_HANDLER },
194 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
196 #define XSIG(x) (terminating_signals[x].signum)
197 #define XHANDLER(x) (terminating_signals[x].orig_handler)
199 static int termsigs_initialized = 0;
201 /* Initialize signals that will terminate the shell to do some
202 unwind protection. For non-interactive shells, we only call
203 this when a trap is defined for EXIT (0). */
205 initialize_terminating_signals ()
208 #if defined (HAVE_POSIX_SIGNALS)
209 struct sigaction act, oact;
212 if (termsigs_initialized)
215 /* The following code is to avoid an expensive call to
216 set_signal_handler () for each terminating_signals. Fortunately,
217 this is possible in Posix. Unfortunately, we have to call signal ()
218 on non-Posix systems for each signal in terminating_signals. */
219 #if defined (HAVE_POSIX_SIGNALS)
220 act.sa_handler = termination_unwind_protect;
222 sigemptyset (&act.sa_mask);
223 sigemptyset (&oact.sa_mask);
224 for (i = 0; i < TERMSIGS_LENGTH; i++)
225 sigaddset (&act.sa_mask, XSIG (i));
226 for (i = 0; i < TERMSIGS_LENGTH; i++)
228 sigaction (XSIG (i), &act, &oact);
229 XHANDLER(i) = oact.sa_handler;
230 /* Don't do anything with signals that are ignored at shell entry
231 if the shell is not interactive. */
232 if (!interactive_shell && XHANDLER (i) == SIG_IGN)
234 sigaction (XSIG (i), &oact, &act);
235 set_signal_ignored (XSIG (i));
237 #if defined (SIGPROF) && !defined (_MINIX)
238 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
239 sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
240 #endif /* SIGPROF && !_MINIX */
243 #else /* !HAVE_POSIX_SIGNALS */
245 for (i = 0; i < TERMSIGS_LENGTH; i++)
247 XHANDLER(i) = signal (XSIG (i), termination_unwind_protect);
248 /* Don't do anything with signals that are ignored at shell entry
249 if the shell is not interactive. */
250 if (!interactive_shell && XHANDLER (i) == SIG_IGN)
252 signal (XSIG (i), SIG_IGN);
253 set_signal_ignored (XSIG (i));
256 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
257 signal (XSIG (i), XHANDLER (i));
261 #endif /* !HAVE_POSIX_SIGNALS */
263 termsigs_initialized = 1;
267 initialize_shell_signals ()
270 initialize_terminating_signals ();
272 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
273 /* All shells use the signal mask they inherit, and pass it along
274 to child processes. Children will never block SIGCHLD, though. */
275 sigemptyset (&top_level_mask);
276 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
277 # if defined (SIGCHLD)
278 sigdelset (&top_level_mask, SIGCHLD);
280 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
282 /* And, some signals that are specifically ignored by the shell. */
283 set_signal_handler (SIGQUIT, SIG_IGN);
287 set_signal_handler (SIGINT, sigint_sighandler);
288 set_signal_handler (SIGTERM, SIG_IGN);
293 reset_terminating_signals ()
296 #if defined (HAVE_POSIX_SIGNALS)
297 struct sigaction act;
300 if (termsigs_initialized == 0)
303 #if defined (HAVE_POSIX_SIGNALS)
305 sigemptyset (&act.sa_mask);
306 for (i = 0; i < TERMSIGS_LENGTH; i++)
308 /* Skip a signal if it's trapped or handled specially, because the
309 trap code will restore the correct value. */
310 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
313 act.sa_handler = XHANDLER (i);
314 sigaction (XSIG (i), &act, (struct sigaction *) NULL);
316 #else /* !HAVE_POSIX_SIGNALS */
317 for (i = 0; i < TERMSIGS_LENGTH; i++)
319 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
322 signal (XSIG (i), XHANDLER (i));
324 #endif /* !HAVE_POSIX_SIGNALS */
329 /* What to do when we've been interrupted, and it is safe to handle it. */
331 throw_to_top_level ()
333 int print_newline = 0;
344 last_command_exit_value |= 128;
346 /* Run any traps set on SIGINT. */
347 run_interrupt_trap ();
349 /* Cleanup string parser environment. */
350 while (parse_and_execute_level)
351 parse_and_execute_cleanup ();
353 #if defined (JOB_CONTROL)
354 give_terminal_to (shell_pgrp, 0);
355 #endif /* JOB_CONTROL */
357 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
358 /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
359 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
364 #if defined (READLINE)
366 bashline_reinitialize ();
367 #endif /* READLINE */
369 #if defined (PROCESS_SUBSTITUTION)
371 #endif /* PROCESS_SUBSTITUTION */
373 run_unwind_protects ();
374 loop_level = continuing = breaking = 0;
375 return_catch_flag = 0;
377 if (interactive && print_newline)
380 fprintf (stderr, "\n");
384 /* An interrupted `wait' command in a script does not exit the script. */
385 if (interactive || (interactive_shell && !shell_initialized) ||
386 (print_newline && signal_is_trapped (SIGINT)))
387 jump_to_top_level (DISCARD);
389 jump_to_top_level (EXITPROG);
392 /* This is just here to isolate the longjmp calls. */
394 jump_to_top_level (value)
397 longjmp (top_level, value);
401 termination_unwind_protect (sig)
404 if (sig == SIGINT && signal_is_trapped (SIGINT))
405 run_interrupt_trap ();
407 #if defined (HISTORY)
408 if (interactive_shell && sig != SIGABRT)
409 maybe_save_shell_history ();
412 #if defined (JOB_CONTROL)
413 if (interactive && sig == SIGHUP)
416 #endif /* JOB_CONTROL */
418 #if defined (PROCESS_SUBSTITUTION)
420 #endif /* PROCESS_SUBSTITUTION */
423 set_signal_handler (sig, SIG_DFL);
424 kill (getpid (), sig);
429 /* What we really do when SIGINT occurs. */
431 sigint_sighandler (sig)
434 #if defined (MUST_REINSTALL_SIGHANDLERS)
435 signal (sig, sigint_sighandler);
438 /* interrupt_state needs to be set for the stack of interrupts to work
439 right. Should it be set unconditionally? */
440 if (interrupt_state == 0)
443 if (interrupt_immediately)
445 interrupt_immediately = 0;
446 throw_to_top_level ();
452 /* Signal functions used by the rest of the code. */
453 #if !defined (HAVE_POSIX_SIGNALS)
455 #if defined (JOB_CONTROL)
456 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
457 sigprocmask (operation, newset, oldset)
458 int operation, *newset, *oldset;
470 old = sigblock (new);
478 internal_error ("Bad code in sig.c: sigprocmask");
484 #endif /* JOB_CONTROL */
488 #if !defined (SA_INTERRUPT)
489 # define SA_INTERRUPT 0
492 #if !defined (SA_RESTART)
493 # define SA_RESTART 0
497 set_signal_handler (sig, handler)
501 struct sigaction act, oact;
503 act.sa_handler = handler;
507 act.sa_flags |= SA_INTERRUPT; /* XXX */
509 act.sa_flags |= SA_RESTART; /* XXX */
511 sigemptyset (&act.sa_mask);
512 sigemptyset (&oact.sa_mask);
513 sigaction (sig, &act, &oact);
514 return (oact.sa_handler);
516 #endif /* HAVE_POSIX_SIGNALS */