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)
33 #if defined (JOB_CONTROL)
35 #endif /* JOB_CONTROL */
40 #include "builtins/common.h"
42 #if defined (READLINE)
43 # include "bashline.h"
47 # include "bashhist.h"
50 extern int last_command_exit_value;
51 extern int return_catch_flag;
52 extern int loop_level, continuing, breaking;
53 extern int parse_and_execute_level, shell_initialized;
54 extern int interactive, interactive_shell, login_shell, startup_state;
56 /* Non-zero after SIGINT. */
59 /* The environment at the top-level R-E loop. We use this in
60 the case of error return. */
63 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
64 /* The signal masks that this shell runs with. */
65 sigset_t top_level_mask;
66 #endif /* JOB_CONTROL */
68 /* When non-zero, we throw_to_top_level (). */
69 int interrupt_immediately = 0;
71 static void initialize_shell_signals ();
76 initialize_shell_signals ();
77 initialize_job_signals ();
78 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
79 initialize_siglist ();
84 reinitialize_signals ()
86 initialize_shell_signals (1);
87 initialize_job_signals ();
90 /* A structure describing a signal that terminates the shell if not
91 caught. The orig_handler member is present so children can reset
92 these signals back to their original handlers. */
95 SigHandler *orig_handler;
98 #define NULL_HANDLER (SigHandler *)SIG_DFL
100 /* The list of signals that would terminate the shell if not caught.
101 We catch them, but just so that we can write the history file,
103 static struct termsig terminating_signals[] = {
105 SIGHUP, NULL_HANDLER,
109 SIGINT, NULL_HANDLER,
113 SIGILL, NULL_HANDLER,
117 SIGTRAP, NULL_HANDLER,
121 SIGIOT, NULL_HANDLER,
125 SIGDANGER, NULL_HANDLER,
129 SIGEMT, NULL_HANDLER,
133 SIGFPE, NULL_HANDLER,
137 SIGBUS, NULL_HANDLER,
141 SIGSEGV, NULL_HANDLER,
145 SIGSYS, NULL_HANDLER,
149 SIGPIPE, NULL_HANDLER,
153 SIGALRM, NULL_HANDLER,
157 SIGTERM, NULL_HANDLER,
161 SIGXCPU, NULL_HANDLER,
165 SIGXFSZ, NULL_HANDLER,
169 SIGVTALRM, NULL_HANDLER,
173 SIGPROF, NULL_HANDLER,
177 SIGLOST, NULL_HANDLER,
181 SIGUSR1, NULL_HANDLER,
185 SIGUSR2, NULL_HANDLER,
189 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
191 #define XSIG(x) (terminating_signals[x].signum)
192 #define XHANDLER(x) (terminating_signals[x].orig_handler)
194 static int termsigs_initialized = 0;
196 /* Initialize signals that will terminate the shell to do some
197 unwind protection. For non-interactive shells, we only call
198 this when a trap is defined for EXIT (0). */
200 initialize_terminating_signals ()
203 #if defined (HAVE_POSIX_SIGNALS)
204 struct sigaction act, oact;
207 if (termsigs_initialized)
210 /* The following code is to avoid an expensive call to
211 set_signal_handler () for each terminating_signals. Fortunately,
212 this is possible in Posix. Unfortunately, we have to call signal ()
213 on non-Posix systems for each signal in terminating_signals. */
214 #if defined (HAVE_POSIX_SIGNALS)
215 act.sa_handler = termination_unwind_protect;
217 sigemptyset (&act.sa_mask);
218 sigemptyset (&oact.sa_mask);
219 for (i = 0; i < TERMSIGS_LENGTH; i++)
220 sigaddset (&act.sa_mask, XSIG (i));
221 for (i = 0; i < TERMSIGS_LENGTH; i++)
223 sigaction (XSIG (i), &act, &oact);
224 XHANDLER(i) = oact.sa_handler;
225 /* Don't do anything with signals that are ignored at shell entry
226 if the shell is not interactive. */
227 if (!interactive_shell && XHANDLER (i) == SIG_IGN)
229 sigaction (XSIG (i), &oact, &act);
230 set_signal_ignored (XSIG (i));
232 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
233 sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
236 #else /* !HAVE_POSIX_SIGNALS */
238 for (i = 0; i < TERMSIGS_LENGTH; i++)
240 XHANDLER(i) = signal (XSIG (i), termination_unwind_protect);
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 signal (XSIG (i), SIG_IGN);
246 set_signal_ignored (XSIG (i));
248 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
249 signal (XSIG (i), XHANDLER (i));
252 #endif /* !HAVE_POSIX_SIGNALS */
254 termsigs_initialized = 1;
258 initialize_shell_signals ()
261 initialize_terminating_signals ();
263 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
264 /* All shells use the signal mask they inherit, and pass it along
265 to child processes. Children will never block SIGCHLD, though. */
266 sigemptyset (&top_level_mask);
267 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
268 sigdelset (&top_level_mask, SIGCHLD);
269 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
271 /* And, some signals that are specifically ignored by the shell. */
272 set_signal_handler (SIGQUIT, SIG_IGN);
276 set_signal_handler (SIGINT, sigint_sighandler);
277 set_signal_handler (SIGTERM, SIG_IGN);
282 reset_terminating_signals ()
285 #if defined (HAVE_POSIX_SIGNALS)
286 struct sigaction act;
289 if (termsigs_initialized == 0)
292 #if defined (HAVE_POSIX_SIGNALS)
294 sigemptyset (&act.sa_mask);
295 for (i = 0; i < TERMSIGS_LENGTH; i++)
297 /* Skip a signal if it's trapped or handled specially, because the
298 trap code will restore the correct value. */
299 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
302 act.sa_handler = XHANDLER (i);
303 sigaction (XSIG (i), &act, (struct sigaction *) NULL);
305 #else /* !HAVE_POSIX_SIGNALS */
306 for (i = 0; i < TERMSIGS_LENGTH; i++)
308 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
311 signal (XSIG (i), XHANDLER (i));
313 #endif /* !HAVE_POSIX_SIGNALS */
318 /* What to do when we've been interrupted, and it is safe to handle it. */
320 throw_to_top_level ()
322 int print_newline = 0;
333 last_command_exit_value |= 128;
335 /* Run any traps set on SIGINT. */
336 run_interrupt_trap ();
338 /* Cleanup string parser environment. */
339 while (parse_and_execute_level)
340 parse_and_execute_cleanup ();
342 #if defined (JOB_CONTROL)
343 give_terminal_to (shell_pgrp);
344 #endif /* JOB_CONTROL */
346 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
347 /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
348 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
353 #if defined (READLINE)
355 bashline_reinitialize ();
356 #endif /* READLINE */
358 #if defined (PROCESS_SUBSTITUTION)
360 #endif /* PROCESS_SUBSTITUTION */
362 run_unwind_protects ();
363 loop_level = continuing = breaking = 0;
364 return_catch_flag = 0;
366 if (interactive && print_newline)
369 fprintf (stderr, "\n");
373 /* An interrupted `wait' command in a script does not exit the script. */
374 if (interactive || (interactive_shell && !shell_initialized) ||
375 (print_newline && signal_is_trapped (SIGINT)))
376 jump_to_top_level (DISCARD);
378 jump_to_top_level (EXITPROG);
381 /* This is just here to isolate the longjmp calls. */
383 jump_to_top_level (value)
386 longjmp (top_level, value);
390 termination_unwind_protect (sig)
393 if (sig == SIGINT && signal_is_trapped (SIGINT))
394 run_interrupt_trap ();
396 #if defined (HISTORY)
397 if (interactive_shell && sig != SIGABRT)
398 maybe_save_shell_history ();
401 #if defined (JOB_CONTROL)
402 if (interactive && sig == SIGHUP)
405 #endif /* JOB_CONTROL */
407 #if defined (PROCESS_SUBSTITUTION)
409 #endif /* PROCESS_SUBSTITUTION */
412 set_signal_handler (sig, SIG_DFL);
413 kill (getpid (), sig);
418 /* What we really do when SIGINT occurs. */
420 sigint_sighandler (sig)
423 #if defined (MUST_REINSTALL_SIGHANDLERS)
424 signal (sig, sigint_sighandler);
427 /* interrupt_state needs to be set for the stack of interrupts to work
428 right. Should it be set unconditionally? */
429 if (interrupt_state == 0)
432 if (interrupt_immediately)
434 interrupt_immediately = 0;
435 throw_to_top_level ();
441 /* Signal functions used by the rest of the code. */
442 #if !defined (HAVE_POSIX_SIGNALS)
444 #if defined (JOB_CONTROL)
445 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
446 sigprocmask (operation, newset, oldset)
447 int operation, *newset, *oldset;
459 old = sigblock (new);
467 internal_error ("Bad code in sig.c: sigprocmask");
473 #endif /* JOB_CONTROL */
477 #if !defined (SA_INTERRUPT)
478 # define SA_INTERRUPT 0
481 #if !defined (SA_RESTART)
482 # define SA_RESTART 0
486 set_signal_handler (sig, handler)
490 struct sigaction act, oact;
492 act.sa_handler = handler;
496 act.sa_flags |= SA_INTERRUPT; /* XXX */
498 act.sa_flags |= SA_RESTART; /* XXX */
500 sigemptyset (&act.sa_mask);
501 sigemptyset (&oact.sa_mask);
502 sigaction (sig, &act, &oact);
503 return (oact.sa_handler);
505 #endif /* HAVE_POSIX_SIGNALS */