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_terminating_signals ();
76 initialize_terminating_signals ();
77 initialize_job_signals ();
78 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
79 initialize_siglist ();
84 reinitialize_signals ()
86 initialize_terminating_signals ();
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 /* Initialize signals that will terminate the shell to do some
195 unwind protection. */
197 initialize_terminating_signals ()
201 /* The following code is to avoid an expensive call to
202 set_signal_handler () for each terminating_signals. Fortunately,
203 this is possible in Posix. Unfortunately, we have to call signal ()
204 on non-Posix systems for each signal in terminating_signals. */
205 #if defined (HAVE_POSIX_SIGNALS)
206 struct sigaction act, oact;
208 act.sa_handler = termination_unwind_protect;
210 sigemptyset (&act.sa_mask);
211 sigemptyset (&oact.sa_mask);
212 for (i = 0; i < TERMSIGS_LENGTH; i++)
213 sigaddset (&act.sa_mask, XSIG (i));
214 for (i = 0; i < TERMSIGS_LENGTH; i++)
216 sigaction (XSIG (i), &act, &oact);
217 terminating_signals[i].orig_handler = oact.sa_handler;
218 /* Don't do anything with signals that are ignored at shell entry
219 if the shell is not interactive. */
220 if (!interactive_shell && oact.sa_handler == SIG_IGN)
222 sigaction (XSIG (i), &oact, &act);
223 set_signal_ignored (XSIG (i));
227 #else /* !HAVE_POSIX_SIGNALS */
229 for (i = 0; i < TERMSIGS_LENGTH; i++)
231 terminating_signals[i].orig_handler =
232 signal (XSIG (i), termination_unwind_protect);
233 /* Don't do anything with signals that are ignored at shell entry
234 if the shell is not interactive. */
235 if (!interactive_shell && terminating_signals[i].orig_handler == SIG_IGN)
237 signal (XSIG (i), SIG_IGN);
238 set_signal_ignored (XSIG (i));
242 #endif /* !HAVE_POSIX_SIGNALS */
244 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
245 /* All shells use the signal mask they inherit, and pass it along
246 to child processes. Children will never block SIGCHLD, though. */
247 sigemptyset (&top_level_mask);
248 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
249 sigdelset (&top_level_mask, SIGCHLD);
250 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
252 /* And, some signals that are specifically ignored by the shell. */
253 set_signal_handler (SIGQUIT, SIG_IGN);
257 set_signal_handler (SIGINT, sigint_sighandler);
258 set_signal_handler (SIGTERM, SIG_IGN);
263 reset_terminating_signals ()
267 #if defined (HAVE_POSIX_SIGNALS)
268 struct sigaction act;
271 sigemptyset (&act.sa_mask);
272 for (i = 0; i < TERMSIGS_LENGTH; i++)
274 /* Skip a signal if it's trapped or handled specially, because the
275 trap code will restore the correct value. */
276 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
279 act.sa_handler = XHANDLER (i);
280 sigaction (XSIG (i), &act, (struct sigaction *) NULL);
282 #else /* !HAVE_POSIX_SIGNALS */
283 for (i = 0; i < TERMSIGS_LENGTH; i++)
285 if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
288 signal (XSIG (i), XHANDLER (i));
290 #endif /* !HAVE_POSIX_SIGNALS */
295 /* What to do when we've been interrupted, and it is safe to handle it. */
297 throw_to_top_level ()
299 int print_newline = 0;
310 last_command_exit_value |= 128;
312 /* Run any traps set on SIGINT. */
313 run_interrupt_trap ();
315 /* Cleanup string parser environment. */
316 while (parse_and_execute_level)
317 parse_and_execute_cleanup ();
319 #if defined (JOB_CONTROL)
320 give_terminal_to (shell_pgrp);
321 #endif /* JOB_CONTROL */
323 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
324 /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
325 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
330 #if defined (READLINE)
332 bashline_reinitialize ();
333 #endif /* READLINE */
335 #if defined (PROCESS_SUBSTITUTION)
337 #endif /* PROCESS_SUBSTITUTION */
339 run_unwind_protects ();
340 loop_level = continuing = breaking = 0;
341 return_catch_flag = 0;
343 if (interactive && print_newline)
346 fprintf (stderr, "\n");
350 /* An interrupted `wait' command in a script does not exit the script. */
351 if (interactive || (interactive_shell && !shell_initialized) ||
352 (print_newline && signal_is_trapped (SIGINT)))
353 jump_to_top_level (DISCARD);
355 jump_to_top_level (EXITPROG);
358 /* This is just here to isolate the longjmp calls. */
360 jump_to_top_level (value)
363 longjmp (top_level, value);
367 termination_unwind_protect (sig)
370 if (sig == SIGINT && signal_is_trapped (SIGINT))
371 run_interrupt_trap ();
373 #if defined (HISTORY)
374 if (interactive_shell && sig != SIGABRT)
375 maybe_save_shell_history ();
378 #if defined (JOB_CONTROL)
379 if (interactive && sig == SIGHUP)
382 #endif /* JOB_CONTROL */
384 #if defined (PROCESS_SUBSTITUTION)
386 #endif /* PROCESS_SUBSTITUTION */
389 set_signal_handler (sig, SIG_DFL);
390 kill (getpid (), sig);
395 /* What we really do when SIGINT occurs. */
397 sigint_sighandler (sig)
400 #if defined (MUST_REINSTALL_SIGHANDLERS)
401 signal (sig, sigint_sighandler);
404 /* interrupt_state needs to be set for the stack of interrupts to work
405 right. Should it be set unconditionally? */
406 if (interrupt_state == 0)
409 if (interrupt_immediately)
411 interrupt_immediately = 0;
412 throw_to_top_level ();
418 /* Signal functions used by the rest of the code. */
419 #if !defined (HAVE_POSIX_SIGNALS)
421 #if defined (JOB_CONTROL)
422 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
423 sigprocmask (operation, newset, oldset)
424 int operation, *newset, *oldset;
436 old = sigblock (new);
444 internal_error ("Bad code in sig.c: sigprocmask");
450 #endif /* JOB_CONTROL */
454 #if !defined (SA_INTERRUPT)
455 # define SA_INTERRUPT 0
458 #if !defined (SA_RESTART)
459 # define SA_RESTART 0
463 set_signal_handler (sig, handler)
467 struct sigaction act, oact;
469 act.sa_handler = handler;
473 act.sa_flags |= SA_INTERRUPT; /* XXX */
475 act.sa_flags |= SA_RESTART; /* XXX */
477 sigemptyset (&act.sa_mask);
478 sigemptyset (&oact.sa_mask);
479 sigaction (sig, &act, &oact);
480 return (oact.sa_handler);
482 #endif /* HAVE_POSIX_SIGNALS */