i-bash/sig.c

755 lines
19 KiB
C
Raw Permalink Normal View History

1996-12-23 17:02:34 +00:00
/* sig.c - interface for shell signal handlers and signal initialization. */
/* Copyright (C) 1994-2015 Free Software Foundation, Inc.
1996-12-23 17:02:34 +00:00
This file is part of GNU Bash, the Bourne Again SHell.
2009-01-12 13:36:28 +00:00
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
1996-12-23 17:02:34 +00:00
2009-01-12 13:36:28 +00:00
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
1996-12-23 17:02:34 +00:00
2009-01-12 13:36:28 +00:00
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
1996-12-23 17:02:34 +00:00
#include "config.h"
#include "bashtypes.h"
#if defined (HAVE_UNISTD_H)
1998-04-17 19:52:44 +00:00
# ifdef _MINIX
# include <sys/types.h>
# endif
1996-12-23 17:02:34 +00:00
# include <unistd.h>
#endif
#include <stdio.h>
#include <signal.h>
2004-07-27 13:29:18 +00:00
#include "bashintl.h"
1996-12-23 17:02:34 +00:00
#include "shell.h"
#if defined (JOB_CONTROL)
#include "jobs.h"
#endif /* JOB_CONTROL */
#include "siglist.h"
#include "sig.h"
#include "trap.h"
#include "builtins/common.h"
#include "builtins/builtext.h"
1996-12-23 17:02:34 +00:00
#if defined (READLINE)
# include "bashline.h"
2011-11-22 20:00:47 -05:00
# include <readline/readline.h>
1996-12-23 17:02:34 +00:00
#endif
#if defined (HISTORY)
# include "bashhist.h"
#endif
extern int last_command_exit_value;
2004-07-27 13:29:18 +00:00
extern int last_command_exit_signal;
1996-12-23 17:02:34 +00:00
extern int return_catch_flag;
extern int running_trap;
extern int loop_level, continuing, breaking, funcnest;
2009-01-12 13:36:28 +00:00
extern int executing_list;
extern int comsub_ignore_return;
1996-12-23 17:02:34 +00:00
extern int parse_and_execute_level, shell_initialized;
#if defined (HISTORY)
extern int history_lines_this_session;
#endif
2011-11-22 20:00:47 -05:00
extern int no_line_editing;
extern int wait_signal_received;
extern int wait_intr_flag;
extern sh_builtin_func_t *this_shell_builtin;
extern void initialize_siglist ();
1996-12-23 17:02:34 +00:00
#if !defined (JOB_CONTROL)
extern void initialize_job_signals __P((void));
#endif
1996-12-23 17:02:34 +00:00
/* Non-zero after SIGINT. */
volatile sig_atomic_t interrupt_state = 0;
1996-12-23 17:02:34 +00:00
2005-12-07 14:08:12 +00:00
/* Non-zero after SIGWINCH */
volatile sig_atomic_t sigwinch_received = 0;
/* Non-zero after SIGTERM */
volatile sig_atomic_t sigterm_received = 0;
2005-12-07 14:08:12 +00:00
2006-10-10 14:15:34 +00:00
/* Set to the value of any terminating signal received. */
volatile sig_atomic_t terminating_signal = 0;
2006-10-10 14:15:34 +00:00
1996-12-23 17:02:34 +00:00
/* The environment at the top-level R-E loop. We use this in
the case of error return. */
procenv_t top_level;
#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
/* The signal masks that this shell runs with. */
sigset_t top_level_mask;
#endif /* JOB_CONTROL */
/* When non-zero, we throw_to_top_level (). */
int interrupt_immediately = 0;
2006-10-10 14:15:34 +00:00
/* When non-zero, we call the terminating signal handler immediately. */
int terminate_immediately = 0;
2005-12-07 14:08:12 +00:00
#if defined (SIGWINCH)
static SigHandler *old_winch = (SigHandler *)SIG_DFL;
#endif
2001-11-13 17:56:06 +00:00
static void initialize_shell_signals __P((void));
1996-12-23 17:02:34 +00:00
void
2002-07-17 14:10:11 +00:00
initialize_signals (reinit)
int reinit;
1996-12-23 17:02:34 +00:00
{
1997-06-05 14:59:13 +00:00
initialize_shell_signals ();
1996-12-23 17:02:34 +00:00
initialize_job_signals ();
1997-09-22 20:22:27 +00:00
#if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
2002-07-17 14:10:11 +00:00
if (reinit == 0)
initialize_siglist ();
1997-09-22 20:22:27 +00:00
#endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
1996-12-23 17:02:34 +00:00
}
/* A structure describing a signal that terminates the shell if not
caught. The orig_handler member is present so children can reset
these signals back to their original handlers. */
struct termsig {
int signum;
SigHandler *orig_handler;
2005-12-07 14:08:12 +00:00
int orig_flags;
1996-12-23 17:02:34 +00:00
};
#define NULL_HANDLER (SigHandler *)SIG_DFL
/* The list of signals that would terminate the shell if not caught.
We catch them, but just so that we can write the history file,
and so forth. */
static struct termsig terminating_signals[] = {
#ifdef SIGHUP
2005-12-07 14:08:12 +00:00
{ SIGHUP, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGINT
2005-12-07 14:08:12 +00:00
{ SIGINT, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGILL
2005-12-07 14:08:12 +00:00
{ SIGILL, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGTRAP
2005-12-07 14:08:12 +00:00
{ SIGTRAP, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGIOT
2005-12-07 14:08:12 +00:00
{ SIGIOT, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGDANGER
2005-12-07 14:08:12 +00:00
{ SIGDANGER, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGEMT
2005-12-07 14:08:12 +00:00
{ SIGEMT, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGFPE
2005-12-07 14:08:12 +00:00
{ SIGFPE, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGBUS
2005-12-07 14:08:12 +00:00
{ SIGBUS, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGSEGV
2005-12-07 14:08:12 +00:00
{ SIGSEGV, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGSYS
2005-12-07 14:08:12 +00:00
{ SIGSYS, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGPIPE
2005-12-07 14:08:12 +00:00
{ SIGPIPE, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGALRM
2005-12-07 14:08:12 +00:00
{ SIGALRM, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGTERM
2005-12-07 14:08:12 +00:00
{ SIGTERM, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGXCPU
2005-12-07 14:08:12 +00:00
{ SIGXCPU, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGXFSZ
2005-12-07 14:08:12 +00:00
{ SIGXFSZ, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGVTALRM
2005-12-07 14:08:12 +00:00
{ SIGVTALRM, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
2000-03-17 21:46:59 +00:00
#if 0
1996-12-23 17:02:34 +00:00
#ifdef SIGPROF
2005-12-07 14:08:12 +00:00
{ SIGPROF, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
2000-03-17 21:46:59 +00:00
#endif
1996-12-23 17:02:34 +00:00
#ifdef SIGLOST
2005-12-07 14:08:12 +00:00
{ SIGLOST, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGUSR1
2005-12-07 14:08:12 +00:00
{ SIGUSR1, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
#ifdef SIGUSR2
2005-12-07 14:08:12 +00:00
{ SIGUSR2, NULL_HANDLER, 0 },
1996-12-23 17:02:34 +00:00
#endif
};
#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
#define XSIG(x) (terminating_signals[x].signum)
#define XHANDLER(x) (terminating_signals[x].orig_handler)
2005-12-07 14:08:12 +00:00
#define XSAFLAGS(x) (terminating_signals[x].orig_flags)
1996-12-23 17:02:34 +00:00
1997-06-05 14:59:13 +00:00
static int termsigs_initialized = 0;
1996-12-23 17:02:34 +00:00
/* Initialize signals that will terminate the shell to do some
1997-06-05 14:59:13 +00:00
unwind protection. For non-interactive shells, we only call
this when a trap is defined for EXIT (0) or when trap is run
to display signal dispositions. */
1997-06-05 14:59:13 +00:00
void
1996-12-23 17:02:34 +00:00
initialize_terminating_signals ()
{
register int i;
1997-06-05 14:59:13 +00:00
#if defined (HAVE_POSIX_SIGNALS)
struct sigaction act, oact;
#endif
if (termsigs_initialized)
return;
1996-12-23 17:02:34 +00:00
/* The following code is to avoid an expensive call to
set_signal_handler () for each terminating_signals. Fortunately,
this is possible in Posix. Unfortunately, we have to call signal ()
on non-Posix systems for each signal in terminating_signals. */
#if defined (HAVE_POSIX_SIGNALS)
2006-10-10 14:15:34 +00:00
act.sa_handler = termsig_sighandler;
1996-12-23 17:02:34 +00:00
act.sa_flags = 0;
sigemptyset (&act.sa_mask);
sigemptyset (&oact.sa_mask);
for (i = 0; i < TERMSIGS_LENGTH; i++)
sigaddset (&act.sa_mask, XSIG (i));
for (i = 0; i < TERMSIGS_LENGTH; i++)
{
2002-07-17 14:10:11 +00:00
/* If we've already trapped it, don't do anything. */
if (signal_is_trapped (XSIG (i)))
continue;
1996-12-23 17:02:34 +00:00
sigaction (XSIG (i), &act, &oact);
1997-06-05 14:59:13 +00:00
XHANDLER(i) = oact.sa_handler;
2005-12-07 14:08:12 +00:00
XSAFLAGS(i) = oact.sa_flags;
1996-12-23 17:02:34 +00:00
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
/* XXX - should we do this for interactive shells, too? */
if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
2001-04-06 19:14:31 +00:00
{
1996-12-23 17:02:34 +00:00
sigaction (XSIG (i), &oact, &act);
set_signal_hard_ignored (XSIG (i));
2001-04-06 19:14:31 +00:00
}
1998-04-17 19:52:44 +00:00
#if defined (SIGPROF) && !defined (_MINIX)
1997-06-05 14:59:13 +00:00
if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
2001-04-06 19:14:31 +00:00
sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
1998-04-17 19:52:44 +00:00
#endif /* SIGPROF && !_MINIX */
1996-12-23 17:02:34 +00:00
}
#else /* !HAVE_POSIX_SIGNALS */
for (i = 0; i < TERMSIGS_LENGTH; i++)
{
2002-07-17 14:10:11 +00:00
/* If we've already trapped it, don't do anything. */
if (signal_is_trapped (XSIG (i)))
continue;
2006-10-10 14:15:34 +00:00
XHANDLER(i) = signal (XSIG (i), termsig_sighandler);
2005-12-07 14:08:12 +00:00
XSAFLAGS(i) = 0;
1996-12-23 17:02:34 +00:00
/* Don't do anything with signals that are ignored at shell entry
if the shell is not interactive. */
/* XXX - should we do this for interactive shells, too? */
if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
1996-12-23 17:02:34 +00:00
{
2001-04-06 19:14:31 +00:00
signal (XSIG (i), SIG_IGN);
set_signal_hard_ignored (XSIG (i));
1996-12-23 17:02:34 +00:00
}
1998-04-17 19:52:44 +00:00
#ifdef SIGPROF
1997-06-05 14:59:13 +00:00
if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
2001-04-06 19:14:31 +00:00
signal (XSIG (i), XHANDLER (i));
1998-04-17 19:52:44 +00:00
#endif
1996-12-23 17:02:34 +00:00
}
#endif /* !HAVE_POSIX_SIGNALS */
1997-06-05 14:59:13 +00:00
termsigs_initialized = 1;
}
static void
initialize_shell_signals ()
{
if (interactive)
initialize_terminating_signals ();
1996-12-23 17:02:34 +00:00
#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
/* All shells use the signal mask they inherit, and pass it along
to child processes. Children will never block SIGCHLD, though. */
sigemptyset (&top_level_mask);
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
2000-03-17 21:46:59 +00:00
# if defined (SIGCHLD)
1996-12-23 17:02:34 +00:00
sigdelset (&top_level_mask, SIGCHLD);
2000-03-17 21:46:59 +00:00
# endif
1996-12-23 17:02:34 +00:00
#endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
/* And, some signals that are specifically ignored by the shell. */
set_signal_handler (SIGQUIT, SIG_IGN);
if (interactive)
{
set_signal_handler (SIGINT, sigint_sighandler);
get_original_signal (SIGTERM);
if (signal_is_hard_ignored (SIGTERM) == 0)
set_signal_handler (SIGTERM, sigterm_sighandler);
2005-12-07 14:08:12 +00:00
set_sigwinch_handler ();
1996-12-23 17:02:34 +00:00
}
}
void
reset_terminating_signals ()
{
register int i;
#if defined (HAVE_POSIX_SIGNALS)
struct sigaction act;
1997-06-05 14:59:13 +00:00
#endif
1996-12-23 17:02:34 +00:00
1997-06-05 14:59:13 +00:00
if (termsigs_initialized == 0)
return;
#if defined (HAVE_POSIX_SIGNALS)
1996-12-23 17:02:34 +00:00
act.sa_flags = 0;
sigemptyset (&act.sa_mask);
for (i = 0; i < TERMSIGS_LENGTH; i++)
{
/* Skip a signal if it's trapped or handled specially, because the
trap code will restore the correct value. */
if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
continue;
act.sa_handler = XHANDLER (i);
2005-12-07 14:08:12 +00:00
act.sa_flags = XSAFLAGS (i);
1996-12-23 17:02:34 +00:00
sigaction (XSIG (i), &act, (struct sigaction *) NULL);
}
#else /* !HAVE_POSIX_SIGNALS */
for (i = 0; i < TERMSIGS_LENGTH; i++)
{
if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
continue;
signal (XSIG (i), XHANDLER (i));
}
#endif /* !HAVE_POSIX_SIGNALS */
termsigs_initialized = 0;
1996-12-23 17:02:34 +00:00
}
#undef XSIG
#undef XHANDLER
2008-11-18 13:15:12 +00:00
/* Run some of the cleanups that should be performed when we run
jump_to_top_level from a builtin command context. XXX - might want to
also call reset_parser here. */
void
top_level_cleanup ()
{
/* Clean up string parser environment. */
while (parse_and_execute_level)
parse_and_execute_cleanup ();
#if defined (PROCESS_SUBSTITUTION)
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
run_unwind_protects ();
loop_level = continuing = breaking = funcnest = 0;
executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
2008-11-18 13:15:12 +00:00
}
1996-12-23 17:02:34 +00:00
/* What to do when we've been interrupted, and it is safe to handle it. */
void
throw_to_top_level ()
{
int print_newline = 0;
if (interrupt_state)
{
if (last_command_exit_value < 128)
last_command_exit_value = 128 + SIGINT;
1996-12-23 17:02:34 +00:00
print_newline = 1;
DELINTERRUPT;
}
if (interrupt_state)
return;
2004-07-27 13:29:18 +00:00
last_command_exit_signal = (last_command_exit_value > 128) ?
(last_command_exit_value - 128) : 0;
1996-12-23 17:02:34 +00:00
last_command_exit_value |= 128;
/* Run any traps set on SIGINT, mostly for interactive shells */
if (signal_is_trapped (SIGINT))
run_interrupt_trap (1);
1996-12-23 17:02:34 +00:00
2009-01-12 13:36:28 +00:00
/* Clean up string parser environment. */
1996-12-23 17:02:34 +00:00
while (parse_and_execute_level)
parse_and_execute_cleanup ();
if (running_trap > 0)
run_trap_cleanup (running_trap - 1);
1996-12-23 17:02:34 +00:00
#if defined (JOB_CONTROL)
2001-04-06 19:14:31 +00:00
give_terminal_to (shell_pgrp, 0);
1996-12-23 17:02:34 +00:00
#endif /* JOB_CONTROL */
#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
/* This needs to stay because jobs.c:make_child() uses it without resetting
the signal mask. */
1996-12-23 17:02:34 +00:00
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
#endif
reset_parser ();
#if defined (READLINE)
if (interactive)
2009-01-12 13:36:28 +00:00
bashline_reset ();
1996-12-23 17:02:34 +00:00
#endif /* READLINE */
#if defined (PROCESS_SUBSTITUTION)
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
run_unwind_protects ();
loop_level = continuing = breaking = funcnest = 0;
executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
1996-12-23 17:02:34 +00:00
if (interactive && print_newline)
{
fflush (stdout);
fprintf (stderr, "\n");
fflush (stderr);
}
/* An interrupted `wait' command in a script does not exit the script. */
if (interactive || (interactive_shell && !shell_initialized) ||
(print_newline && signal_is_trapped (SIGINT)))
jump_to_top_level (DISCARD);
else
jump_to_top_level (EXITPROG);
}
/* This is just here to isolate the longjmp calls. */
void
jump_to_top_level (value)
int value;
{
sh_longjmp (top_level, value);
1996-12-23 17:02:34 +00:00
}
sighandler
2006-10-10 14:15:34 +00:00
termsig_sighandler (sig)
1996-12-23 17:02:34 +00:00
int sig;
{
2011-11-21 20:49:12 -05:00
/* If we get called twice with the same signal before handling it,
terminate right away. */
if (
#ifdef SIGHUP
sig != SIGHUP &&
#endif
#ifdef SIGINT
sig != SIGINT &&
#endif
#ifdef SIGDANGER
sig != SIGDANGER &&
#endif
#ifdef SIGPIPE
sig != SIGPIPE &&
#endif
#ifdef SIGALRM
sig != SIGALRM &&
#endif
#ifdef SIGTERM
sig != SIGTERM &&
#endif
#ifdef SIGXCPU
sig != SIGXCPU &&
#endif
#ifdef SIGXFSZ
sig != SIGXFSZ &&
#endif
#ifdef SIGVTALRM
sig != SIGVTALRM &&
#endif
#ifdef SIGLOST
sig != SIGLOST &&
#endif
#ifdef SIGUSR1
sig != SIGUSR1 &&
#endif
#ifdef SIGUSR2
sig != SIGUSR2 &&
#endif
sig == terminating_signal)
terminate_immediately = 1;
2006-10-10 14:15:34 +00:00
terminating_signal = sig;
2009-01-12 13:36:28 +00:00
/* XXX - should this also trigger when interrupt_immediately is set? */
2006-10-10 14:15:34 +00:00
if (terminate_immediately)
{
#if defined (HISTORY)
/* XXX - will inhibit history file being written */
2011-11-22 20:00:47 -05:00
# if defined (READLINE)
if (interactive_shell == 0 || interactive == 0 || (sig != SIGHUP && sig != SIGTERM) || no_line_editing || (RL_ISSTATE (RL_STATE_READCMD) == 0))
# endif
history_lines_this_session = 0;
#endif
2006-10-10 14:15:34 +00:00
terminate_immediately = 0;
termsig_handler (sig);
}
#if defined (READLINE)
/* Set the event hook so readline will call it after the signal handlers
finish executing, so if this interrupted character input we can get
2015-01-15 10:21:08 -05:00
quick response. If readline is active or has modified the terminal we
need to set this no matter what the signal is, though the check for
RL_STATE_TERMPREPPED is possibly redundant. */
if (RL_ISSTATE (RL_STATE_SIGHANDLER) || RL_ISSTATE (RL_STATE_TERMPREPPED))
bashline_set_event_hook ();
#endif
2006-10-10 14:15:34 +00:00
SIGRETURN (0);
}
void
termsig_handler (sig)
int sig;
{
static int handling_termsig = 0;
/* Simple semaphore to keep this function from being executed multiple
times. Since we no longer are running as a signal handler, we don't
block multiple occurrences of the terminating signals while running. */
if (handling_termsig)
return;
handling_termsig = 1;
terminating_signal = 0; /* keep macro from re-testing true. */
2005-12-07 14:08:12 +00:00
/* I don't believe this condition ever tests true. */
1996-12-23 17:02:34 +00:00
if (sig == SIGINT && signal_is_trapped (SIGINT))
run_interrupt_trap (0);
1996-12-23 17:02:34 +00:00
#if defined (HISTORY)
/* If we don't do something like this, the history will not be saved when
an interactive shell is running in a terminal window that gets closed
with the `close' button. We can't test for RL_STATE_READCMD because
readline no longer handles SIGTERM synchronously. */
if (interactive_shell && interactive && (sig == SIGHUP || sig == SIGTERM) && remember_on_history)
1996-12-23 17:02:34 +00:00
maybe_save_shell_history ();
#endif /* HISTORY */
if (this_shell_builtin == read_builtin)
read_tty_cleanup ();
1996-12-23 17:02:34 +00:00
#if defined (JOB_CONTROL)
2011-11-21 20:51:19 -05:00
if (sig == SIGHUP && (interactive || (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB))))
1996-12-23 17:02:34 +00:00
hangup_all_jobs ();
2017-01-20 15:38:49 -05:00
if ((subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB)) == 0)
end_job_control ();
1996-12-23 17:02:34 +00:00
#endif /* JOB_CONTROL */
#if defined (PROCESS_SUBSTITUTION)
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
2009-01-12 13:36:28 +00:00
/* Reset execution context */
loop_level = continuing = breaking = funcnest = 0;
executing_list = comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
2009-01-12 13:36:28 +00:00
run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
1996-12-23 17:02:34 +00:00
set_signal_handler (sig, SIG_DFL);
kill (getpid (), sig);
}
/* What we really do when SIGINT occurs. */
sighandler
sigint_sighandler (sig)
int sig;
{
#if defined (MUST_REINSTALL_SIGHANDLERS)
signal (sig, sigint_sighandler);
#endif
/* interrupt_state needs to be set for the stack of interrupts to work
right. Should it be set unconditionally? */
if (interrupt_state == 0)
ADDINTERRUPT;
/* We will get here in interactive shells with job control active; allow
an interactive wait to be interrupted. wait_intr_flag is only set during
the execution of the wait builtin and when wait_intr_buf is valid. */
if (wait_intr_flag)
{
last_command_exit_value = 128 + sig;
wait_signal_received = sig;
SIGRETURN (0);
}
1996-12-23 17:02:34 +00:00
if (interrupt_immediately)
{
interrupt_immediately = 0;
2011-11-21 20:51:19 -05:00
last_command_exit_value = 128 + sig;
1996-12-23 17:02:34 +00:00
throw_to_top_level ();
}
#if defined (READLINE)
/* Set the event hook so readline will call it after the signal handlers
finish executing, so if this interrupted character input we can get
quick response. */
else if (RL_ISSTATE (RL_STATE_SIGHANDLER))
bashline_set_event_hook ();
#endif
1996-12-23 17:02:34 +00:00
SIGRETURN (0);
}
2005-12-07 14:08:12 +00:00
#if defined (SIGWINCH)
sighandler
sigwinch_sighandler (sig)
int sig;
{
#if defined (MUST_REINSTALL_SIGHANDLERS)
set_signal_handler (SIGWINCH, sigwinch_sighandler);
#endif /* MUST_REINSTALL_SIGHANDLERS */
sigwinch_received = 1;
SIGRETURN (0);
}
#endif /* SIGWINCH */
void
set_sigwinch_handler ()
{
#if defined (SIGWINCH)
old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
#endif
}
void
unset_sigwinch_handler ()
{
#if defined (SIGWINCH)
set_signal_handler (SIGWINCH, old_winch);
#endif
}
sighandler
sigterm_sighandler (sig)
int sig;
{
sigterm_received = 1; /* XXX - counter? */
SIGRETURN (0);
}
1996-12-23 17:02:34 +00:00
/* Signal functions used by the rest of the code. */
#if !defined (HAVE_POSIX_SIGNALS)
/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
sigprocmask (operation, newset, oldset)
int operation, *newset, *oldset;
{
int old, new;
if (newset)
new = *newset;
else
new = 0;
switch (operation)
{
case SIG_BLOCK:
old = sigblock (new);
break;
case SIG_SETMASK:
old = sigsetmask (new);
1996-12-23 17:02:34 +00:00
break;
default:
2004-07-27 13:29:18 +00:00
internal_error (_("sigprocmask: %d: invalid operation"), operation);
1996-12-23 17:02:34 +00:00
}
if (oldset)
*oldset = old;
}
#else
#if !defined (SA_INTERRUPT)
# define SA_INTERRUPT 0
#endif
#if !defined (SA_RESTART)
# define SA_RESTART 0
#endif
SigHandler *
set_signal_handler (sig, handler)
int sig;
SigHandler *handler;
{
struct sigaction act, oact;
act.sa_handler = handler;
act.sa_flags = 0;
/* XXX - bash-4.2 */
/* We don't want a child death to interrupt interruptible system calls, even
if we take the time to reap children */
#if defined (SIGCHLD)
2011-11-21 20:57:16 -05:00
if (sig == SIGCHLD)
act.sa_flags |= SA_RESTART; /* XXX */
#endif
/* If we're installing a SIGTERM handler for interactive shells, we want
it to be as close to SIG_IGN as possible. */
if (sig == SIGTERM && handler == sigterm_sighandler)
act.sa_flags |= SA_RESTART; /* XXX */
1996-12-23 17:02:34 +00:00
sigemptyset (&act.sa_mask);
sigemptyset (&oact.sa_mask);
if (sigaction (sig, &act, &oact) == 0)
return (oact.sa_handler);
else
return (SIG_DFL);
1996-12-23 17:02:34 +00:00
}
#endif /* HAVE_POSIX_SIGNALS */