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>
38 #if defined (JOB_CONTROL)
40 #endif /* JOB_CONTROL */
45 #include "builtins/common.h"
47 #if defined (READLINE)
48 # include "bashline.h"
52 # include "bashhist.h"
55 extern int last_command_exit_value
;
56 extern int last_command_exit_signal
;
57 extern int return_catch_flag
;
58 extern int loop_level
, continuing
, breaking
;
59 extern int parse_and_execute_level
, shell_initialized
;
61 /* Non-zero after SIGINT. */
64 /* The environment at the top-level R-E loop. We use this in
65 the case of error return. */
68 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
69 /* The signal masks that this shell runs with. */
70 sigset_t top_level_mask
;
71 #endif /* JOB_CONTROL */
73 /* When non-zero, we throw_to_top_level (). */
74 int interrupt_immediately
= 0;
76 static void initialize_shell_signals
__P((void));
79 initialize_signals (reinit
)
82 initialize_shell_signals ();
83 initialize_job_signals ();
84 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
86 initialize_siglist ();
87 #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
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
},
174 { SIGPROF
, NULL_HANDLER
},
179 { SIGLOST
, NULL_HANDLER
},
183 { SIGUSR1
, NULL_HANDLER
},
187 { SIGUSR2
, NULL_HANDLER
},
191 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
193 #define XSIG(x) (terminating_signals[x].signum)
194 #define XHANDLER(x) (terminating_signals[x].orig_handler)
196 static int termsigs_initialized
= 0;
198 /* Initialize signals that will terminate the shell to do some
199 unwind protection. For non-interactive shells, we only call
200 this when a trap is defined for EXIT (0). */
202 initialize_terminating_signals ()
205 #if defined (HAVE_POSIX_SIGNALS)
206 struct sigaction act
, oact
;
209 if (termsigs_initialized
)
212 /* The following code is to avoid an expensive call to
213 set_signal_handler () for each terminating_signals. Fortunately,
214 this is possible in Posix. Unfortunately, we have to call signal ()
215 on non-Posix systems for each signal in terminating_signals. */
216 #if defined (HAVE_POSIX_SIGNALS)
217 act
.sa_handler
= termination_unwind_protect
;
219 sigemptyset (&act
.sa_mask
);
220 sigemptyset (&oact
.sa_mask
);
221 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
222 sigaddset (&act
.sa_mask
, XSIG (i
));
223 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
225 /* If we've already trapped it, don't do anything. */
226 if (signal_is_trapped (XSIG (i
)))
229 sigaction (XSIG (i
), &act
, &oact
);
230 XHANDLER(i
) = oact
.sa_handler
;
231 /* Don't do anything with signals that are ignored at shell entry
232 if the shell is not interactive. */
233 if (!interactive_shell
&& XHANDLER (i
) == SIG_IGN
)
235 sigaction (XSIG (i
), &oact
, &act
);
236 set_signal_ignored (XSIG (i
));
238 #if defined (SIGPROF) && !defined (_MINIX)
239 if (XSIG (i
) == SIGPROF
&& XHANDLER (i
) != SIG_DFL
&& XHANDLER (i
) != SIG_IGN
)
240 sigaction (XSIG (i
), &oact
, (struct sigaction
*)NULL
);
241 #endif /* SIGPROF && !_MINIX */
244 #else /* !HAVE_POSIX_SIGNALS */
246 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
248 /* If we've already trapped it, don't do anything. */
249 if (signal_is_trapped (XSIG (i
)))
252 XHANDLER(i
) = signal (XSIG (i
), termination_unwind_protect
);
253 /* Don't do anything with signals that are ignored at shell entry
254 if the shell is not interactive. */
255 if (!interactive_shell
&& XHANDLER (i
) == SIG_IGN
)
257 signal (XSIG (i
), SIG_IGN
);
258 set_signal_ignored (XSIG (i
));
261 if (XSIG (i
) == SIGPROF
&& XHANDLER (i
) != SIG_DFL
&& XHANDLER (i
) != SIG_IGN
)
262 signal (XSIG (i
), XHANDLER (i
));
266 #endif /* !HAVE_POSIX_SIGNALS */
268 termsigs_initialized
= 1;
272 initialize_shell_signals ()
275 initialize_terminating_signals ();
277 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
278 /* All shells use the signal mask they inherit, and pass it along
279 to child processes. Children will never block SIGCHLD, though. */
280 sigemptyset (&top_level_mask
);
281 sigprocmask (SIG_BLOCK
, (sigset_t
*)NULL
, &top_level_mask
);
282 # if defined (SIGCHLD)
283 sigdelset (&top_level_mask
, SIGCHLD
);
285 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
287 /* And, some signals that are specifically ignored by the shell. */
288 set_signal_handler (SIGQUIT
, SIG_IGN
);
292 set_signal_handler (SIGINT
, sigint_sighandler
);
293 set_signal_handler (SIGTERM
, SIG_IGN
);
298 reset_terminating_signals ()
301 #if defined (HAVE_POSIX_SIGNALS)
302 struct sigaction act
;
305 if (termsigs_initialized
== 0)
308 #if defined (HAVE_POSIX_SIGNALS)
310 sigemptyset (&act
.sa_mask
);
311 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
313 /* Skip a signal if it's trapped or handled specially, because the
314 trap code will restore the correct value. */
315 if (signal_is_trapped (XSIG (i
)) || signal_is_special (XSIG (i
)))
318 act
.sa_handler
= XHANDLER (i
);
319 sigaction (XSIG (i
), &act
, (struct sigaction
*) NULL
);
321 #else /* !HAVE_POSIX_SIGNALS */
322 for (i
= 0; i
< TERMSIGS_LENGTH
; i
++)
324 if (signal_is_trapped (XSIG (i
)) || signal_is_special (XSIG (i
)))
327 signal (XSIG (i
), XHANDLER (i
));
329 #endif /* !HAVE_POSIX_SIGNALS */
334 /* What to do when we've been interrupted, and it is safe to handle it. */
336 throw_to_top_level ()
338 int print_newline
= 0;
349 last_command_exit_signal
= (last_command_exit_value
> 128) ?
350 (last_command_exit_value
- 128) : 0;
351 last_command_exit_value
|= 128;
353 /* Run any traps set on SIGINT. */
354 run_interrupt_trap ();
356 /* Cleanup string parser environment. */
357 while (parse_and_execute_level
)
358 parse_and_execute_cleanup ();
360 #if defined (JOB_CONTROL)
361 give_terminal_to (shell_pgrp
, 0);
362 #endif /* JOB_CONTROL */
364 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
365 /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
366 sigprocmask (SIG_SETMASK
, &top_level_mask
, (sigset_t
*)NULL
);
371 #if defined (READLINE)
373 bashline_reinitialize ();
374 #endif /* READLINE */
376 #if defined (PROCESS_SUBSTITUTION)
378 #endif /* PROCESS_SUBSTITUTION */
380 run_unwind_protects ();
381 loop_level
= continuing
= breaking
= 0;
382 return_catch_flag
= 0;
384 if (interactive
&& print_newline
)
387 fprintf (stderr
, "\n");
391 /* An interrupted `wait' command in a script does not exit the script. */
392 if (interactive
|| (interactive_shell
&& !shell_initialized
) ||
393 (print_newline
&& signal_is_trapped (SIGINT
)))
394 jump_to_top_level (DISCARD
);
396 jump_to_top_level (EXITPROG
);
399 /* This is just here to isolate the longjmp calls. */
401 jump_to_top_level (value
)
404 longjmp (top_level
, value
);
408 termination_unwind_protect (sig
)
411 if (sig
== SIGINT
&& signal_is_trapped (SIGINT
))
412 run_interrupt_trap ();
414 #if defined (HISTORY)
415 if (interactive_shell
&& sig
!= SIGABRT
)
416 maybe_save_shell_history ();
419 #if defined (JOB_CONTROL)
420 if (interactive
&& sig
== SIGHUP
)
423 #endif /* JOB_CONTROL */
425 #if defined (PROCESS_SUBSTITUTION)
427 #endif /* PROCESS_SUBSTITUTION */
430 set_signal_handler (sig
, SIG_DFL
);
431 kill (getpid (), sig
);
436 /* What we really do when SIGINT occurs. */
438 sigint_sighandler (sig
)
441 #if defined (MUST_REINSTALL_SIGHANDLERS)
442 signal (sig
, sigint_sighandler
);
445 /* interrupt_state needs to be set for the stack of interrupts to work
446 right. Should it be set unconditionally? */
447 if (interrupt_state
== 0)
450 if (interrupt_immediately
)
452 interrupt_immediately
= 0;
453 throw_to_top_level ();
459 /* Signal functions used by the rest of the code. */
460 #if !defined (HAVE_POSIX_SIGNALS)
462 #if defined (JOB_CONTROL)
463 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
464 sigprocmask (operation
, newset
, oldset
)
465 int operation
, *newset
, *oldset
;
477 old
= sigblock (new);
485 internal_error (_("sigprocmask: %d: invalid operation"), operation
);
491 #endif /* JOB_CONTROL */
495 #if !defined (SA_INTERRUPT)
496 # define SA_INTERRUPT 0
499 #if !defined (SA_RESTART)
500 # define SA_RESTART 0
504 set_signal_handler (sig
, handler
)
508 struct sigaction act
, oact
;
510 act
.sa_handler
= handler
;
514 act
.sa_flags
|= SA_INTERRUPT
; /* XXX */
516 act
.sa_flags
|= SA_RESTART
; /* XXX */
518 sigemptyset (&act
.sa_mask
);
519 sigemptyset (&oact
.sa_mask
);
520 sigaction (sig
, &act
, &oact
);
521 return (oact
.sa_handler
);
523 #endif /* HAVE_POSIX_SIGNALS */