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, 675 Mass Ave, Cambridge, MA 02139, 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 interactive, interactive_shell, login_shell, 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 ();
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 (1);
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,
176 SIGPROF, NULL_HANDLER,
180 SIGLOST, NULL_HANDLER,
184 SIGUSR1, NULL_HANDLER,
188 SIGUSR2, NULL_HANDLER,
192 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
194 #define XSIG(x) (terminating_signals[x].signum)
195 #define XHANDLER(x) (terminating_signals[x].orig_handler)
197 static int termsigs_initialized = 0;
199 /* Initialize signals that will terminate the shell to do some
200 unwind protection. For non-interactive shells, we only call
201 this when a trap is defined for EXIT (0). */
203 initialize_terminating_signals ()
206 #if defined (HAVE_POSIX_SIGNALS)
207 struct sigaction act, oact;
210 if (termsigs_initialized)
213 /* The following code is to avoid an expensive call to
214 set_signal_handler () for each terminating_signals. Fortunately,
215 this is possible in Posix. Unfortunately, we have to call signal ()
216 on non-Posix systems for each signal in terminating_signals. */
217 #if defined (HAVE_POSIX_SIGNALS)
218 act.sa_handler = termination_unwind_protect;
220 sigemptyset (&act.sa_mask);
221 sigemptyset (&oact.sa_mask);
222 for (i = 0; i < TERMSIGS_LENGTH; i++)
223 sigaddset (&act.sa_mask, XSIG (i));
224 for (i = 0; i < TERMSIGS_LENGTH; i++)
226 sigaction (XSIG (i), &act, &oact);
227 XHANDLER(i) = oact.sa_handler;
228 /* Don't do anything with signals that are ignored at shell entry
229 if the shell is not interactive. */
230 if (!interactive_shell && XHANDLER (i) == SIG_IGN)
232 sigaction (XSIG (i), &oact, &act);
233 set_signal_ignored (XSIG (i));
235 #if defined (SIGPROF) && !defined (_MINIX)
236 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
237 sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
238 #endif /* SIGPROF && !_MINIX */
241 #else /* !HAVE_POSIX_SIGNALS */
243 for (i = 0; i < TERMSIGS_LENGTH; i++)
245 XHANDLER(i) = signal (XSIG (i), termination_unwind_protect);
246 /* Don't do anything with signals that are ignored at shell entry
247 if the shell is not interactive. */
248 if (!interactive_shell && XHANDLER (i) == SIG_IGN)
250 signal (XSIG (i), SIG_IGN);
251 set_signal_ignored (XSIG (i));
254 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
255 signal (XSIG (i), XHANDLER (i));
259 #endif /* !HAVE_POSIX_SIGNALS */
261 termsigs_initialized = 1;
265 initialize_shell_signals ()
268 initialize_terminating_signals ();
270 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
271 /* All shells use the signal mask they inherit, and pass it along
272 to child processes. Children will never block SIGCHLD, though. */
273 sigemptyset (&top_level_mask);
274 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
275 sigdelset (&top_level_mask, SIGCHLD);
276 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
278 /* And, some signals that are specifically ignored by the shell. */
279 set_signal_handler (SIGQUIT, SIG_IGN);
283 set_signal_handler (SIGINT, sigint_sighandler);
284 set_signal_handler (SIGTERM, SIG_IGN);
289 reset_terminating_signals ()
292 #if defined (HAVE_POSIX_SIGNALS)
293 struct sigaction act;
296 if (termsigs_initialized == 0)
299 #if defined (HAVE_POSIX_SIGNALS)
301 sigemptyset (&act.sa_mask);
302 for (i = 0; i < TERMSIGS_LENGTH; i++)
304 /* Skip a signal if it's trapped or handled specially, because the
305 trap code will restore the correct value. */
306 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
309 act.sa_handler = XHANDLER (i);
310 sigaction (XSIG (i), &act, (struct sigaction *) NULL);
312 #else /* !HAVE_POSIX_SIGNALS */
313 for (i = 0; i < TERMSIGS_LENGTH; i++)
315 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
318 signal (XSIG (i), XHANDLER (i));
320 #endif /* !HAVE_POSIX_SIGNALS */
325 /* What to do when we've been interrupted, and it is safe to handle it. */
327 throw_to_top_level ()
329 int print_newline = 0;
340 last_command_exit_value |= 128;
342 /* Run any traps set on SIGINT. */
343 run_interrupt_trap ();
345 /* Cleanup string parser environment. */
346 while (parse_and_execute_level)
347 parse_and_execute_cleanup ();
349 #if defined (JOB_CONTROL)
350 give_terminal_to (shell_pgrp);
351 #endif /* JOB_CONTROL */
353 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
354 /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
355 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
360 #if defined (READLINE)
362 bashline_reinitialize ();
363 #endif /* READLINE */
365 #if defined (PROCESS_SUBSTITUTION)
367 #endif /* PROCESS_SUBSTITUTION */
369 run_unwind_protects ();
370 loop_level = continuing = breaking = 0;
371 return_catch_flag = 0;
373 if (interactive && print_newline)
376 fprintf (stderr, "\n");
380 /* An interrupted `wait' command in a script does not exit the script. */
381 if (interactive || (interactive_shell && !shell_initialized) ||
382 (print_newline && signal_is_trapped (SIGINT)))
383 jump_to_top_level (DISCARD);
385 jump_to_top_level (EXITPROG);
388 /* This is just here to isolate the longjmp calls. */
390 jump_to_top_level (value)
393 longjmp (top_level, value);
397 termination_unwind_protect (sig)
400 if (sig == SIGINT && signal_is_trapped (SIGINT))
401 run_interrupt_trap ();
403 #if defined (HISTORY)
404 if (interactive_shell && sig != SIGABRT)
405 maybe_save_shell_history ();
408 #if defined (JOB_CONTROL)
409 if (interactive && sig == SIGHUP)
412 #endif /* JOB_CONTROL */
414 #if defined (PROCESS_SUBSTITUTION)
416 #endif /* PROCESS_SUBSTITUTION */
419 set_signal_handler (sig, SIG_DFL);
420 kill (getpid (), sig);
425 /* What we really do when SIGINT occurs. */
427 sigint_sighandler (sig)
430 #if defined (MUST_REINSTALL_SIGHANDLERS)
431 signal (sig, sigint_sighandler);
434 /* interrupt_state needs to be set for the stack of interrupts to work
435 right. Should it be set unconditionally? */
436 if (interrupt_state == 0)
439 if (interrupt_immediately)
441 interrupt_immediately = 0;
442 throw_to_top_level ();
448 /* Signal functions used by the rest of the code. */
449 #if !defined (HAVE_POSIX_SIGNALS)
451 #if defined (JOB_CONTROL)
452 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
453 sigprocmask (operation, newset, oldset)
454 int operation, *newset, *oldset;
466 old = sigblock (new);
474 internal_error ("Bad code in sig.c: sigprocmask");
480 #endif /* JOB_CONTROL */
484 #if !defined (SA_INTERRUPT)
485 # define SA_INTERRUPT 0
488 #if !defined (SA_RESTART)
489 # define SA_RESTART 0
493 set_signal_handler (sig, handler)
497 struct sigaction act, oact;
499 act.sa_handler = handler;
503 act.sa_flags |= SA_INTERRUPT; /* XXX */
505 act.sa_flags |= SA_RESTART; /* XXX */
507 sigemptyset (&act.sa_mask);
508 sigemptyset (&oact.sa_mask);
509 sigaction (sig, &act, &oact);
510 return (oact.sa_handler);
512 #endif /* HAVE_POSIX_SIGNALS */