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_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
79 initialize_siglist ();
80 #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
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 defined (SIGPROF)
233 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
234 sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
238 #else /* !HAVE_POSIX_SIGNALS */
240 for (i = 0; i < TERMSIGS_LENGTH; i++)
242 XHANDLER(i) = signal (XSIG (i), termination_unwind_protect);
243 /* Don't do anything with signals that are ignored at shell entry
244 if the shell is not interactive. */
245 if (!interactive_shell && XHANDLER (i) == SIG_IGN)
247 signal (XSIG (i), SIG_IGN);
248 set_signal_ignored (XSIG (i));
250 if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
251 signal (XSIG (i), XHANDLER (i));
254 #endif /* !HAVE_POSIX_SIGNALS */
256 termsigs_initialized = 1;
260 initialize_shell_signals ()
263 initialize_terminating_signals ();
265 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
266 /* All shells use the signal mask they inherit, and pass it along
267 to child processes. Children will never block SIGCHLD, though. */
268 sigemptyset (&top_level_mask);
269 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
270 sigdelset (&top_level_mask, SIGCHLD);
271 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
273 /* And, some signals that are specifically ignored by the shell. */
274 set_signal_handler (SIGQUIT, SIG_IGN);
278 set_signal_handler (SIGINT, sigint_sighandler);
279 set_signal_handler (SIGTERM, SIG_IGN);
284 reset_terminating_signals ()
287 #if defined (HAVE_POSIX_SIGNALS)
288 struct sigaction act;
291 if (termsigs_initialized == 0)
294 #if defined (HAVE_POSIX_SIGNALS)
296 sigemptyset (&act.sa_mask);
297 for (i = 0; i < TERMSIGS_LENGTH; i++)
299 /* Skip a signal if it's trapped or handled specially, because the
300 trap code will restore the correct value. */
301 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
304 act.sa_handler = XHANDLER (i);
305 sigaction (XSIG (i), &act, (struct sigaction *) NULL);
307 #else /* !HAVE_POSIX_SIGNALS */
308 for (i = 0; i < TERMSIGS_LENGTH; i++)
310 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
313 signal (XSIG (i), XHANDLER (i));
315 #endif /* !HAVE_POSIX_SIGNALS */
320 /* What to do when we've been interrupted, and it is safe to handle it. */
322 throw_to_top_level ()
324 int print_newline = 0;
335 last_command_exit_value |= 128;
337 /* Run any traps set on SIGINT. */
338 run_interrupt_trap ();
340 /* Cleanup string parser environment. */
341 while (parse_and_execute_level)
342 parse_and_execute_cleanup ();
344 #if defined (JOB_CONTROL)
345 give_terminal_to (shell_pgrp);
346 #endif /* JOB_CONTROL */
348 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
349 /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
350 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
355 #if defined (READLINE)
357 bashline_reinitialize ();
358 #endif /* READLINE */
360 #if defined (PROCESS_SUBSTITUTION)
362 #endif /* PROCESS_SUBSTITUTION */
364 run_unwind_protects ();
365 loop_level = continuing = breaking = 0;
366 return_catch_flag = 0;
368 if (interactive && print_newline)
371 fprintf (stderr, "\n");
375 /* An interrupted `wait' command in a script does not exit the script. */
376 if (interactive || (interactive_shell && !shell_initialized) ||
377 (print_newline && signal_is_trapped (SIGINT)))
378 jump_to_top_level (DISCARD);
380 jump_to_top_level (EXITPROG);
383 /* This is just here to isolate the longjmp calls. */
385 jump_to_top_level (value)
388 longjmp (top_level, value);
392 termination_unwind_protect (sig)
395 if (sig == SIGINT && signal_is_trapped (SIGINT))
396 run_interrupt_trap ();
398 #if defined (HISTORY)
399 if (interactive_shell && sig != SIGABRT)
400 maybe_save_shell_history ();
403 #if defined (JOB_CONTROL)
404 if (interactive && sig == SIGHUP)
407 #endif /* JOB_CONTROL */
409 #if defined (PROCESS_SUBSTITUTION)
411 #endif /* PROCESS_SUBSTITUTION */
414 set_signal_handler (sig, SIG_DFL);
415 kill (getpid (), sig);
420 /* What we really do when SIGINT occurs. */
422 sigint_sighandler (sig)
425 #if defined (MUST_REINSTALL_SIGHANDLERS)
426 signal (sig, sigint_sighandler);
429 /* interrupt_state needs to be set for the stack of interrupts to work
430 right. Should it be set unconditionally? */
431 if (interrupt_state == 0)
434 if (interrupt_immediately)
436 interrupt_immediately = 0;
437 throw_to_top_level ();
443 /* Signal functions used by the rest of the code. */
444 #if !defined (HAVE_POSIX_SIGNALS)
446 #if defined (JOB_CONTROL)
447 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
448 sigprocmask (operation, newset, oldset)
449 int operation, *newset, *oldset;
461 old = sigblock (new);
469 internal_error ("Bad code in sig.c: sigprocmask");
475 #endif /* JOB_CONTROL */
479 #if !defined (SA_INTERRUPT)
480 # define SA_INTERRUPT 0
483 #if !defined (SA_RESTART)
484 # define SA_RESTART 0
488 set_signal_handler (sig, handler)
492 struct sigaction act, oact;
494 act.sa_handler = handler;
498 act.sa_flags |= SA_INTERRUPT; /* XXX */
500 act.sa_flags |= SA_RESTART; /* XXX */
502 sigemptyset (&act.sa_mask);
503 sigemptyset (&oact.sa_mask);
504 sigaction (sig, &act, &oact);
505 return (oact.sa_handler);
507 #endif /* HAVE_POSIX_SIGNALS */