mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 23:53:18 +02:00
change to readline callback signal handling; fix message when popping shell function context; handle new terminating signals inside terminating signal handler; fix to pattern substitution with null replacement and null string; fix to alias expansion when we get a SIGINT while entering a command substitution in an interactive shell
This commit is contained in:
@@ -4078,3 +4078,69 @@ execute_cmd.c
|
||||
- shell_execve: rearrange code so that we check for a bad interpreter
|
||||
before printing a generic ENOENT error message. Report from
|
||||
Kirill Elagin <kirelagin@gmail.com>
|
||||
|
||||
10/12
|
||||
-----
|
||||
lib/readline/callback.c
|
||||
- CALLBACK_READ_RETURN: add an inlined call to RL_CHECK_SIGNALS so we
|
||||
can handle any signals that arrived before we restored the calling
|
||||
application's signal handlers. From a gdb dicussion with
|
||||
Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
10/12
|
||||
-----
|
||||
variables.c
|
||||
- pop_var_context: flag an internal error for shell_variables not
|
||||
pointing to a function context only if we haven't already flushed
|
||||
all the local contexts and reset variable_context. This can happen
|
||||
if errexit is enabled and we're going to be exiting the shell, but
|
||||
we're running unwind-protects on our way out. Report from
|
||||
Xavier Delaruelle <xavier.delaruelle@gmail.com>
|
||||
|
||||
10/13
|
||||
-----
|
||||
sig.c
|
||||
- kill_shell: broke the code that resets the signal disposition to the
|
||||
default and sends a terminating signal to the shell into a separate
|
||||
function
|
||||
- termsig_handler: set handling_termsig to terminating_signal and make
|
||||
it file-scope so other functions know we're handling a terminating
|
||||
signal and are about to exit, and which signal it is (latter not used
|
||||
yet)
|
||||
- termsig_sighandler: if we get a fatal signal while we're handling a
|
||||
fatal signal, kill ourselves with the second fatal signal immediately.
|
||||
Fixes issue reported by Andreas Schwab <schwab@suse.de>
|
||||
|
||||
execute_cmd.c
|
||||
- execute_case_command: call CHECK_TERMSIG after the call to strmatch,
|
||||
since gmatch will return FNM_NOMATCH if there's a pending terminating
|
||||
signal and we don't want incorrect results
|
||||
|
||||
subst.c
|
||||
- pat_subst: make sure REP is non-NULL before calling savestring on it.
|
||||
Report from Justin Wood (Callek) <callek@gmail.com>
|
||||
|
||||
10/14
|
||||
-----
|
||||
builtins/{shopt.def,common.h}
|
||||
- expand_aliases: split into a variable that holds the current state
|
||||
of alias expansion (expand_aliases) and a variable that reflects the
|
||||
global option value (expalias_flag), make sure expand_aliases is set
|
||||
appropriately by shopt
|
||||
|
||||
shell.c,execute_cmd.c,general.c
|
||||
- expand_aliases: make sure expand_aliases and expalias_flag always
|
||||
agree
|
||||
|
||||
parser.h
|
||||
- PST_STRING: new parser flag, set when parsing a string to a command
|
||||
or word list
|
||||
|
||||
parse.y
|
||||
- reset_parser: if we're parsing a command substitution or a string,
|
||||
and need to restore expand_aliases, make sure it's set to the value
|
||||
of expalias_flag.
|
||||
Fixes SIGINT during interactive command substitution parsing bug
|
||||
reported by feng xiangjun <fengxj325@gmail.com>
|
||||
- parse_string_to_word_list,parse_string_to_command: make sure to set
|
||||
PST_STRING in parser_flags since we're resetting expand_aliases
|
||||
|
||||
@@ -261,6 +261,8 @@ extern int expand_once_flag;
|
||||
extern int extglob_flag;
|
||||
#endif
|
||||
|
||||
extern int expaliases_flag;
|
||||
|
||||
/* variables from source.def */
|
||||
extern int source_searches_cwd;
|
||||
extern int source_uses_path;
|
||||
|
||||
@@ -590,6 +590,7 @@ parse_string (string, from_file, flags, cmdp, endp)
|
||||
char *ostring;
|
||||
volatile sigset_t ps_sigmask;
|
||||
|
||||
/* unwind-protects common to this and parse_and_execute */
|
||||
parse_prologue (string, flags, PS_TAG);
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
|
||||
+14
-4
@@ -154,6 +154,9 @@ int extglob_flag = EXTGLOB_DEFAULT;
|
||||
static int shopt_set_extglob PARAMS((char *, int));
|
||||
#endif
|
||||
|
||||
int expaliases_flag = 0;
|
||||
static int shopt_set_expaliases PARAMS((char *, int));
|
||||
|
||||
static int shopt_set_debug_mode PARAMS((char *, int));
|
||||
|
||||
static int shopt_login_shell;
|
||||
@@ -203,7 +206,7 @@ static struct {
|
||||
#endif
|
||||
{ "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL },
|
||||
{ "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL },
|
||||
{ "expand_aliases", &expand_aliases, (shopt_set_func_t *)NULL },
|
||||
{ "expand_aliases", &expaliases_flag, shopt_set_expaliases },
|
||||
#if defined (DEBUGGER)
|
||||
{ "extdebug", &debugging_mode, shopt_set_debug_mode },
|
||||
#endif
|
||||
@@ -355,7 +358,7 @@ reset_shopt_options ()
|
||||
check_window_size = CHECKWINSIZE_DEFAULT;
|
||||
allow_null_glob_expansion = glob_dot_filenames = 0;
|
||||
no_exit_on_failed_exec = 0;
|
||||
expand_aliases = 0;
|
||||
expand_aliases = expaliases_flag = 0;
|
||||
extended_quote = 1;
|
||||
fail_glob_expansion = 0;
|
||||
glob_asciirange = GLOBASCII_DEFAULT;
|
||||
@@ -636,6 +639,15 @@ shopt_set_debug_mode (option_name, mode)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
shopt_set_expaliases (option_name, mode)
|
||||
char *option_name;
|
||||
int mode;
|
||||
{
|
||||
expand_aliases = expaliases_flag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
static int
|
||||
shopt_set_extglob (option_name, mode)
|
||||
@@ -652,8 +664,6 @@ static int
|
||||
shopt_enable_hostname_completion (option_name, mode)
|
||||
char *option_name;
|
||||
int mode;
|
||||
|
||||
|
||||
{
|
||||
return (enable_hostname_completion (mode));
|
||||
}
|
||||
|
||||
+2
-1
@@ -1539,7 +1539,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
expansion with `shopt -s expand_alias' to continue to expand
|
||||
aliases. */
|
||||
if (ois != interactive_shell)
|
||||
expand_aliases = 0;
|
||||
expand_aliases = expaliases_flag = 0;
|
||||
}
|
||||
|
||||
/* Subshells are neither login nor interactive. */
|
||||
@@ -3627,6 +3627,7 @@ execute_case_command (case_command)
|
||||
free (pattern);
|
||||
|
||||
dispose_words (es);
|
||||
CHECK_TERMSIG;
|
||||
|
||||
if (match)
|
||||
{
|
||||
|
||||
@@ -91,7 +91,7 @@ static struct {
|
||||
{
|
||||
&interactive_comments,
|
||||
&source_uses_path,
|
||||
&expand_aliases,
|
||||
&expaliases_flag,
|
||||
&inherit_errexit,
|
||||
&print_shift_error,
|
||||
0
|
||||
@@ -106,7 +106,8 @@ posix_initialize (on)
|
||||
/* Things that should be turned on when posix mode is enabled. */
|
||||
if (on != 0)
|
||||
{
|
||||
interactive_comments = source_uses_path = expand_aliases = 1;
|
||||
interactive_comments = source_uses_path = 1;
|
||||
expand_aliases = expaliases_flag = 1;
|
||||
inherit_errexit = 1;
|
||||
source_searches_cwd = 0;
|
||||
print_shift_error = 1;
|
||||
@@ -116,13 +117,14 @@ posix_initialize (on)
|
||||
else if (saved_posix_vars) /* on == 0, restore saved settings */
|
||||
{
|
||||
set_posix_options (saved_posix_vars);
|
||||
expand_aliases = expaliases_flag;
|
||||
free (saved_posix_vars);
|
||||
saved_posix_vars = 0;
|
||||
}
|
||||
else /* on == 0, restore a default set of settings */
|
||||
{
|
||||
source_searches_cwd = 1;
|
||||
expand_aliases = interactive_shell;
|
||||
expand_aliases = expaliases_flag = interactive_shell; /* XXX */
|
||||
print_shift_error = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,10 @@ rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *linefunc)
|
||||
#define CALLBACK_READ_RETURN() \
|
||||
do { \
|
||||
if (rl_persistent_signal_handlers == 0) \
|
||||
rl_clear_signals (); \
|
||||
{ \
|
||||
rl_clear_signals (); \
|
||||
if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \
|
||||
} \
|
||||
return; \
|
||||
} while (0)
|
||||
#else
|
||||
|
||||
@@ -3306,6 +3306,8 @@ reset_parser ()
|
||||
if (parser_state & (PST_EXTPAT|PST_CMDSUBST))
|
||||
extended_glob = extglob_flag;
|
||||
#endif
|
||||
if (parser_state & (PST_CMDSUBST|PST_STRING))
|
||||
expand_aliases = expaliases_flag;
|
||||
|
||||
parser_state = 0;
|
||||
here_doc_first_line = 0;
|
||||
@@ -4392,6 +4394,7 @@ parse_string_to_command (string, flags)
|
||||
if (flags & SX_COMPLETE)
|
||||
parser_state |= PST_NOERROR;
|
||||
|
||||
parser_state |= PST_STRING;
|
||||
expand_aliases = 0;
|
||||
|
||||
cmd = 0;
|
||||
@@ -6409,7 +6412,7 @@ parse_string_to_word_list (s, flags, whom)
|
||||
/* State flags we don't want to persist into compound assignments. */
|
||||
parser_state &= ~PST_NOEXPAND; /* parse_comsub sentinel */
|
||||
/* State flags we want to set for this run through the tokenizer. */
|
||||
parser_state |= PST_COMPASSIGN|PST_REPARSE;
|
||||
parser_state |= PST_COMPASSIGN|PST_REPARSE|PST_STRING;
|
||||
}
|
||||
|
||||
while ((tok = read_token (READ)) != yacc_EOF)
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#define PST_ENDALIAS 0x200000 /* just finished expanding and consuming an alias */
|
||||
#define PST_NOEXPAND 0x400000 /* don't expand anything in read_token_word; for command substitution */
|
||||
#define PST_NOERROR 0x800000 /* don't print error messages in yyerror */
|
||||
#define PST_STRING 0x1000000 /* parsing a string to a command or word list */
|
||||
|
||||
/* Definition of the delimiter stack. Needed by parse.y and bashhist.c. */
|
||||
struct dstack {
|
||||
|
||||
@@ -1844,8 +1844,8 @@ reset_option_defaults ()
|
||||
static void
|
||||
init_interactive ()
|
||||
{
|
||||
expand_aliases = interactive_shell = startup_state = 1;
|
||||
interactive = 1;
|
||||
expand_aliases = expaliases_flag = 1;
|
||||
interactive_shell = startup_state = interactive = 1;
|
||||
#if defined (HISTORY)
|
||||
if (enable_history_list == -1)
|
||||
enable_history_list = 1; /* set default */
|
||||
@@ -1865,7 +1865,7 @@ init_noninteractive ()
|
||||
bash_history_reinit (0);
|
||||
#endif /* HISTORY */
|
||||
interactive_shell = startup_state = interactive = 0;
|
||||
expand_aliases = posixly_correct; /* XXX - was 0 not posixly_correct */
|
||||
expand_aliases = expaliases_flag = posixly_correct; /* XXX - was 0 not posixly_correct */
|
||||
no_line_editing = 1;
|
||||
#if defined (JOB_CONTROL)
|
||||
/* Even if the shell is not interactive, enable job control if the -i or
|
||||
@@ -1882,7 +1882,7 @@ init_interactive_script ()
|
||||
enable_history_list = 1;
|
||||
#endif
|
||||
init_noninteractive ();
|
||||
expand_aliases = interactive_shell = startup_state = 1;
|
||||
expand_aliases = expaliases_flag = interactive_shell = startup_state = 1;
|
||||
#if defined (HISTORY)
|
||||
remember_on_history = enable_history_list; /* XXX */
|
||||
#endif
|
||||
@@ -2025,7 +2025,7 @@ shell_reinitialize ()
|
||||
debugging = do_version = line_number = last_command_exit_value = 0;
|
||||
forced_interactive = interactive_shell = 0;
|
||||
subshell_environment = running_in_background = 0;
|
||||
expand_aliases = 0;
|
||||
expand_aliases = expaliases_flag = 0;
|
||||
bash_argv_initialized = 0;
|
||||
|
||||
/* XXX - should we set jobs_m_flag to 0 here? */
|
||||
|
||||
@@ -94,6 +94,7 @@ static SigHandler *old_winch = (SigHandler *)SIG_DFL;
|
||||
#endif
|
||||
|
||||
static void initialize_shell_signals PARAMS((void));
|
||||
static void kill_shell PARAMS((int));
|
||||
|
||||
void
|
||||
initialize_signals (reinit)
|
||||
@@ -486,6 +487,8 @@ restore_sigmask ()
|
||||
#endif
|
||||
}
|
||||
|
||||
static int handling_termsig = 0;
|
||||
|
||||
sighandler
|
||||
termsig_sighandler (sig)
|
||||
int sig;
|
||||
@@ -532,6 +535,14 @@ termsig_sighandler (sig)
|
||||
sig == terminating_signal)
|
||||
terminate_immediately = 1;
|
||||
|
||||
/* If we are currently handling a terminating signal, we have a couple of
|
||||
choices here. We can ignore this second terminating signal and let the
|
||||
shell exit from the first one, or we can exit immediately by killing
|
||||
the shell with this signal. This code implements the latter; to implement
|
||||
the former, replace the kill_shell(sig) with return. */
|
||||
if (handling_termsig)
|
||||
kill_shell (sig); /* just short-circuit now */
|
||||
|
||||
terminating_signal = sig;
|
||||
|
||||
if (terminate_immediately)
|
||||
@@ -564,16 +575,13 @@ void
|
||||
termsig_handler (sig)
|
||||
int sig;
|
||||
{
|
||||
static int handling_termsig = 0;
|
||||
int i, core;
|
||||
sigset_t mask;
|
||||
|
||||
/* 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;
|
||||
|
||||
handling_termsig = terminating_signal; /* for termsig_sighandler */
|
||||
terminating_signal = 0; /* keep macro from re-testing true. */
|
||||
|
||||
/* I don't believe this condition ever tests true. */
|
||||
@@ -613,6 +621,16 @@ termsig_handler (sig)
|
||||
|
||||
run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
|
||||
|
||||
kill_shell (sig);
|
||||
}
|
||||
|
||||
static void
|
||||
kill_shell (sig)
|
||||
int sig;
|
||||
{
|
||||
int i, core;
|
||||
sigset_t mask;
|
||||
|
||||
/* We don't change the set of blocked signals. If a user starts the shell
|
||||
with a terminating signal blocked, we won't get here (and if by some
|
||||
magic chance we do, we'll exit below). What we do is to restore the
|
||||
@@ -627,7 +645,7 @@ termsig_handler (sig)
|
||||
if (dollar_dollar_pid != 1)
|
||||
exit (128+sig); /* just in case the kill fails? */
|
||||
|
||||
/* We get here only under extraordinary circumstances. */
|
||||
/* We get here only under extraordinarily rare circumstances. */
|
||||
|
||||
/* We are PID 1, and the kill above failed to kill the process. We assume
|
||||
this means that we are running as an init process in a pid namespace
|
||||
|
||||
@@ -4005,7 +4005,7 @@ expand_string_for_patsub (string, quoted)
|
||||
if (value)
|
||||
{
|
||||
t = (value->next) ? string_list (value) : value->word->word;
|
||||
ret = quote_string_for_repl (t, quoted);
|
||||
ret = t ? quote_string_for_repl (t, quoted) : t;
|
||||
if (t != value->word->word)
|
||||
free (t);
|
||||
dispose_words (value);
|
||||
@@ -8970,7 +8970,8 @@ pat_subst (string, pat, rep, mflags)
|
||||
return (ret);
|
||||
}
|
||||
else if (*string == 0 && (match_pattern (string, pat, mtype, &s, &e) != 0))
|
||||
return ((mflags & MATCH_EXPREP) ? strcreplace (rep, '&', "", 2) : savestring (rep));
|
||||
return (mflags & MATCH_EXPREP) ? strcreplace (rep, '&', "", 2)
|
||||
: (rep ? savestring (rep) : savestring (""));
|
||||
|
||||
ret = (char *)xmalloc (rsize = 64);
|
||||
ret[0] = '\0';
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -379,6 +379,11 @@ shopt -u globstar
|
||||
# in the right place
|
||||
builtin cd "$MYDIR"
|
||||
|
||||
# seg fault in bash-5.2
|
||||
foo=
|
||||
foo=${foo/#*([.])}
|
||||
unset foo
|
||||
|
||||
${THIS_SH} ./extglob1.sub
|
||||
${THIS_SH} ./extglob1a.sub
|
||||
${THIS_SH} ./extglob3.sub
|
||||
|
||||
+3
-1
@@ -5413,7 +5413,9 @@ pop_var_context ()
|
||||
vcxt = shell_variables;
|
||||
if (vc_isfuncenv (vcxt) == 0)
|
||||
{
|
||||
internal_error (_("pop_var_context: head of shell_variables not a function context"));
|
||||
/* If we haven't flushed all of the local contexts already, flag an error */
|
||||
if (shell_variables != global_variables || variable_context > 0)
|
||||
internal_error (_("pop_var_context: head of shell_variables not a function context"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user