mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-30 08:59:56 +02:00
modify way bash avoids running traps in subshells that haven't reset the trap strings yet; new readline bindable command 'shell-expand-and-requote-line'
This commit is contained in:
@@ -12512,3 +12512,32 @@ jobs.c
|
||||
- wait_for_background_pids: treat wait_for_single_pid returning > 256
|
||||
as an error, same as returning < 0, and check errno appropriately
|
||||
Report from Aleksey Covacevice <aleksey.covacevice@gmail.com>
|
||||
|
||||
sig.c
|
||||
- termsig_handler: don't try to run the exit trap if we're supposed
|
||||
to be ignoring traps (until they're reset) in a subshell
|
||||
environment
|
||||
|
||||
1/7
|
||||
---
|
||||
execute_cmd.c
|
||||
- execute_in_subshell: set SUBSHELL_IGNTRAP before checking for any
|
||||
fatal signal instead of calling clear_exit_trap(); this modifies
|
||||
the change from 12/1
|
||||
|
||||
1/9
|
||||
---
|
||||
bashline.c
|
||||
- shell_expand_line_internal: rename shell_expand_line(), takes an
|
||||
additional argument saying whether or not to quote the individual
|
||||
words in the expanded line (which changes how the line is split
|
||||
initially, since shell-expand-line treats the line as a single
|
||||
potentially-quoted word)
|
||||
- shell_expand_line: call shell_expand_line_internal
|
||||
- shell-expand-and-requote-line: new bindable command, splits the
|
||||
line into individual words like with programmable completion,
|
||||
expands each one, including word splitting, then quotes the
|
||||
resultant words if necessary to prevent subsequent expansion
|
||||
- shell_expand_and_requote_line: calls shell_expand_line_internal
|
||||
with a third argument of 1 to force quoting
|
||||
From a proposal by Koichi Murase <myoga.murase@gmail.com> in 2/2024
|
||||
|
||||
+79
-19
@@ -1,6 +1,6 @@
|
||||
/* bashline.c -- Bash's interface to the readline library. */
|
||||
|
||||
/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -117,7 +117,9 @@ extern int tputs (const char *string, int nlines, int (*outx)(int));
|
||||
/* Forward declarations */
|
||||
|
||||
/* Functions bound to keys in Readline for Bash users. */
|
||||
static int shell_expand_line_internal (int, int, int);
|
||||
static int shell_expand_line (int, int);
|
||||
static int shell_expand_and_requote_line (int, int);
|
||||
static int display_shell_version (int, int);
|
||||
|
||||
static int bash_ignore_filenames (char **);
|
||||
@@ -466,6 +468,7 @@ initialize_readline (void)
|
||||
/* Add bindable names before calling rl_initialize so they may be
|
||||
referenced in the various inputrc files. */
|
||||
rl_add_defun ("shell-expand-line", shell_expand_line, -1);
|
||||
rl_add_defun ("shell-expand-and-requote-line", shell_expand_and_requote_line, -1);
|
||||
#ifdef BANG_HISTORY
|
||||
rl_add_defun ("history-expand-line", history_expand_line, -1);
|
||||
rl_add_defun ("magic-space", tcsh_magic_space, -1);
|
||||
@@ -3005,11 +3008,12 @@ history_and_alias_expand_line (int count, int ignore)
|
||||
}
|
||||
|
||||
/* History and alias expand the line, then perform the shell word
|
||||
expansions by calling expand_string. This can't use set_up_new_line()
|
||||
because we want the variable expansions as a separate undo'able
|
||||
set of operations. */
|
||||
expansions by calling expand_word(). If QUOTE_WORDS is non-zero,
|
||||
we single-quote the expanded words if they contain any shell
|
||||
metacharacters. This can't use set_up_new_line() because we want
|
||||
the variable expansions as a separate undoable set of operations. */
|
||||
static int
|
||||
shell_expand_line (int count, int ignore)
|
||||
shell_expand_line_internal (int count, int ignore, int quote_words)
|
||||
{
|
||||
char *new_line, *t;
|
||||
WORD_LIST *expanded_string;
|
||||
@@ -3048,17 +3052,25 @@ shell_expand_line (int count, int ignore)
|
||||
/* If there is variable expansion to perform, do that as a separate
|
||||
operation to be undone. */
|
||||
|
||||
#if 1
|
||||
w = alloc_word_desc ();
|
||||
w->word = savestring (rl_line_buffer);
|
||||
w->flags = rl_explicit_arg ? (W_NOPROCSUB|W_NOCOMSUB) : 0;
|
||||
expanded_string = expand_word (w, rl_explicit_arg ? Q_HERE_DOCUMENT : 0);
|
||||
dispose_word (w);
|
||||
#else
|
||||
new_line = savestring (rl_line_buffer);
|
||||
expanded_string = expand_string (new_line, 0);
|
||||
FREE (new_line);
|
||||
#endif
|
||||
if (quote_words)
|
||||
{
|
||||
WORD_LIST *wl;
|
||||
|
||||
wl = split_at_delims (rl_line_buffer, strlen (rl_line_buffer), (char *)NULL, -1, 0, (int *)NULL, (int *)NULL);
|
||||
if (rl_explicit_arg)
|
||||
for (expanded_string = wl; expanded_string; expanded_string = expanded_string->next)
|
||||
expanded_string->word->flags |= (W_NOPROCSUB|W_NOCOMSUB);
|
||||
expanded_string = expand_words_shellexp (wl);
|
||||
dispose_words (wl);
|
||||
}
|
||||
else
|
||||
{
|
||||
w = alloc_word_desc ();
|
||||
w->word = savestring (rl_line_buffer);
|
||||
w->flags = rl_explicit_arg ? (W_NOPROCSUB|W_NOCOMSUB) : 0;
|
||||
expanded_string = expand_word (w, rl_explicit_arg ? Q_HERE_DOCUMENT : 0);
|
||||
dispose_word (w);
|
||||
}
|
||||
|
||||
if (expanded_string == 0)
|
||||
{
|
||||
@@ -3066,13 +3078,48 @@ shell_expand_line (int count, int ignore)
|
||||
new_line[0] = '\0';
|
||||
}
|
||||
else
|
||||
new_line = string_list (expanded_string);
|
||||
|
||||
/* We do it this way so we can make the expansion and (optional)
|
||||
quoting separate undoable operations. */
|
||||
maybe_make_readline_line (new_line);
|
||||
free (new_line);
|
||||
|
||||
/* If requested, we quote the expanded words if they need it. This uses
|
||||
split_at_delims in the same way that programmable completion does. */
|
||||
if (quote_words)
|
||||
{
|
||||
char *nword;
|
||||
WORD_LIST *wl;
|
||||
|
||||
for (wl = expanded_string; wl; wl = wl->next)
|
||||
{
|
||||
t = wl->word->word;
|
||||
if (t == 0)
|
||||
continue; /* XXX skip empty words */
|
||||
nword = NULL;
|
||||
if (*t == 0)
|
||||
nword = sh_single_quote (t);
|
||||
else if (ansic_shouldquote (t))
|
||||
nword = ansic_quote (t, 0, (int *)0);
|
||||
else if (rl_explicit_arg || sh_contains_shell_metas (t))
|
||||
nword = sh_single_quote (t);
|
||||
|
||||
if (nword)
|
||||
{
|
||||
free (t);
|
||||
wl->word->word = nword;
|
||||
}
|
||||
}
|
||||
|
||||
new_line = string_list (expanded_string);
|
||||
dispose_words (expanded_string);
|
||||
|
||||
maybe_make_readline_line (new_line);
|
||||
free (new_line);
|
||||
}
|
||||
|
||||
maybe_make_readline_line (new_line);
|
||||
free (new_line);
|
||||
if (expanded_string)
|
||||
dispose_words (expanded_string);
|
||||
|
||||
/* Place rl_point where we think it should go. */
|
||||
if (at_end)
|
||||
@@ -3092,6 +3139,19 @@ shell_expand_line (int count, int ignore)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
shell_expand_line (int count, int ignore)
|
||||
{
|
||||
return (shell_expand_line_internal (count, ignore, 0));
|
||||
}
|
||||
|
||||
static int
|
||||
shell_expand_and_requote_line (int count, int ignore)
|
||||
{
|
||||
return (shell_expand_line_internal (count, ignore, 1));
|
||||
}
|
||||
|
||||
|
||||
/* If FIGNORE is set, then don't match files with the given suffixes when
|
||||
completing filenames. If only one of the possibilities has an acceptable
|
||||
suffix, delete the others, else just return and let the completer
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* command.h -- The structures used internally to represent commands, and
|
||||
the extern declarations of the functions used to create them. */
|
||||
|
||||
/* Copyright (C) 1993-2022 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1993-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -126,6 +126,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
#define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
|
||||
#define SUBSHELL_RESETTRAP 0x80 /* subshell needs to reset trap strings on first call to trap */
|
||||
#define SUBSHELL_IGNTRAP 0x100 /* subshell should reset trapped signals from trap_handler */
|
||||
#define SUBSHELL_RESETJOBS 0x200 /* subshell should clear the jobs list */
|
||||
|
||||
/* A structure which represents a word. */
|
||||
typedef struct word_desc {
|
||||
|
||||
+24
-5
@@ -5,7 +5,7 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet.ramey@case.edu
|
||||
.\"
|
||||
.\" Last Change: Wed Dec 31 18:30:12 EST 2025
|
||||
.\" Last Change: Fri Jan 9 10:17:30 EST 2026
|
||||
.\"
|
||||
.\" For bash_builtins, strip all but "SHELL BUILTIN COMMANDS" section
|
||||
.\" For rbash, strip all but "RESTRICTED SHELL" section
|
||||
@@ -22,7 +22,7 @@
|
||||
.ds zX \" empty
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2025 December 31" "GNU Bash 5.3"
|
||||
.TH BASH 1 "2026 January 9" "GNU Bash 5.3"
|
||||
.\"
|
||||
.ie \n(.g \{\
|
||||
.ds ' \(aq
|
||||
@@ -110,8 +110,8 @@ bash \- GNU Bourne-Again SHell
|
||||
[options]
|
||||
[command_string | file]
|
||||
.SH COPYRIGHT
|
||||
.if n Bash is Copyright (C) 1989-2025 by the Free Software Foundation, Inc.
|
||||
.if t Bash is Copyright \(co 1989-2025 by the Free Software Foundation, Inc.
|
||||
.if n Bash is Copyright (C) 1989-2026 by the Free Software Foundation, Inc.
|
||||
.if t Bash is Copyright \(co 1989-2026 by the Free Software Foundation, Inc.
|
||||
.SH DESCRIPTION
|
||||
.B Bash
|
||||
is a command language interpreter that
|
||||
@@ -7761,7 +7761,8 @@ last word, as if the
|
||||
history expansion had been specified.
|
||||
.TP
|
||||
.B shell\-expand\-line (M\-C\-e)
|
||||
Expand the line by performing shell word expansions.
|
||||
Expand the line by performing shell word expansions,
|
||||
treating the line as a single shell word.
|
||||
This performs alias and history expansion,
|
||||
\fB$\fP\*'\fIstring\fP\*' and \fB$\fP\*"\fIstring\fP\*" quoting,
|
||||
tilde expansion, parameter and variable expansion, arithmetic expansion,
|
||||
@@ -7773,6 +7774,24 @@ See
|
||||
.B "HISTORY EXPANSION"
|
||||
below for a description of history expansion.
|
||||
.TP
|
||||
.B shell\-expand\-and\-requote\-line ()
|
||||
Expand the line by performing shell word expansions,
|
||||
splitting the line into shell words in the same way as for
|
||||
programmable completion.
|
||||
This performs alias and history expansion,
|
||||
\fB$\fP\*'\fIstring\fP\*' and \fB$\fP\*"\fIstring\fP\*" quoting,
|
||||
tilde expansion, parameter and variable expansion, arithmetic expansion,
|
||||
command and process substitution,
|
||||
word splitting, and quote removal
|
||||
on each word, then quotes the resulting words if necessary to
|
||||
prevent further expansion.
|
||||
An explicit argument suppresses command and process substitution
|
||||
and quotes each resultant word.
|
||||
As usual, double-quoting a word will suppress word splitting.
|
||||
This can be useful when combined with suppressing command substitution,
|
||||
for instance, so the words in the command substitution aren't
|
||||
quoted individually.
|
||||
.TP
|
||||
.B history\-expand\-line (M\-\*^)
|
||||
Perform history expansion on the current line.
|
||||
See
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2025 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2026 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Wed Dec 31 18:26:37 EST 2025
|
||||
@set LASTCHANGE Fri Jan 9 10:17:58 EST 2026
|
||||
|
||||
@set EDITION 5.3
|
||||
@set VERSION 5.3
|
||||
|
||||
@set UPDATED 31 December 2025
|
||||
@set UPDATED-MONTH December 2025
|
||||
@set UPDATED 9 January 2026
|
||||
@set UPDATED-MONTH January 2026
|
||||
|
||||
+3
-7
@@ -1,6 +1,6 @@
|
||||
/* execute_cmd.c -- Execute a COMMAND structure. */
|
||||
|
||||
/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -1680,13 +1680,13 @@ execute_in_subshell (COMMAND *command, int asynchronous, int pipe_in, int pipe_o
|
||||
|
||||
if (user_subshell)
|
||||
{
|
||||
subshell_environment = SUBSHELL_PAREN; /* XXX */
|
||||
subshell_environment = SUBSHELL_PAREN|SUBSHELL_IGNTRAP; /* XXX */
|
||||
if (asynchronous)
|
||||
subshell_environment |= SUBSHELL_ASYNC;
|
||||
}
|
||||
else
|
||||
{
|
||||
subshell_environment = 0; /* XXX */
|
||||
subshell_environment = SUBSHELL_IGNTRAP; /* XXX */
|
||||
if (asynchronous)
|
||||
subshell_environment |= SUBSHELL_ASYNC;
|
||||
if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
|
||||
@@ -1695,10 +1695,6 @@ execute_in_subshell (COMMAND *command, int asynchronous, int pipe_in, int pipe_o
|
||||
subshell_environment |= SUBSHELL_COPROC;
|
||||
}
|
||||
|
||||
/* clear the exit trap before checking for fatal signals, but don't free
|
||||
the trap command (see below). */
|
||||
clear_exit_trap (0);
|
||||
|
||||
QUIT;
|
||||
CHECK_TERMSIG;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* general.c -- Stuff that is used by all files. */
|
||||
|
||||
/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -456,6 +456,24 @@ valid_function_word (WORD_DESC *word, int flags)
|
||||
err_invalidid (name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if 0 /*TAG: bash-5.4 kre@munnari.oz.au 6/11/2025 */
|
||||
if (word->flags & W_QUOTED)
|
||||
{
|
||||
char *newname;
|
||||
|
||||
newname = string_quote_removal (name, 0);
|
||||
if (newname == 0)
|
||||
{
|
||||
err_invalidid (name);
|
||||
return (0);
|
||||
}
|
||||
free (word->word);
|
||||
word->word = name = newname;
|
||||
word->flags &= ~W_QUOTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* POSIX interpretation 383 -- this is an application requirement, but the
|
||||
shell should enforce it rather than allow a script to define a function
|
||||
that will never be called. */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/* This file works with both POSIX and BSD systems. It implements job
|
||||
control. */
|
||||
|
||||
/* Copyright (C) 1989-2025 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1989-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
@@ -2065,13 +2065,33 @@ If a numeric argument is supplied, append a @samp{*} before
|
||||
pathname expansion.
|
||||
|
||||
@item shell-expand-line (M-C-e)
|
||||
Expand the line by performing shell word expansions.
|
||||
Expand the line by performing shell word expansions,
|
||||
treating the line as a single shell word.
|
||||
This performs alias and history expansion,
|
||||
$'@var{string}' and $"@var{string}" quoting,
|
||||
tilde expansion, parameter and variable expansion, arithmetic expansion,
|
||||
command and process substitution,
|
||||
word splitting, and quote removal.
|
||||
An explicit argument suppresses command and process substitution.
|
||||
word splitting, and quote removal.
|
||||
An explicit argument suppresses command and process substitution and
|
||||
treats the line as if it were quoted as part of a here-document.
|
||||
|
||||
@item shell-expand-and-requote-line ()
|
||||
Expand the line by performing shell word expansions,
|
||||
splitting the line into shell words in the same way as for
|
||||
programmable completion.
|
||||
This performs alias and history expansion,
|
||||
$'@var{string}' and $"@var{string}" quoting,
|
||||
tilde expansion, parameter and variable expansion, arithmetic expansion,
|
||||
command and process substitution,
|
||||
word splitting, and quote removal
|
||||
on each word, then quotes the resulting words if necessary to
|
||||
prevent further expansion.
|
||||
An explicit argument suppresses command and process substitution
|
||||
and quotes each resultant word.
|
||||
As usual, double-quoting a word will suppress word splitting.
|
||||
This can be useful when combined with suppressing command substitution,
|
||||
for instance, so the words in the command substitution aren't
|
||||
quoted individually.
|
||||
|
||||
@item history-expand-line (M-^)
|
||||
Perform history expansion on the current line.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* sig.c - interface for shell signal handlers and signal initialization. */
|
||||
|
||||
/* Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1994-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -644,7 +644,10 @@ termsig_handler (int sig)
|
||||
interrupt_execution = retain_fifos = executing_funsub = 0;
|
||||
comsub_ignore_return = return_catch_flag = wait_intr_flag = 0;
|
||||
|
||||
run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
|
||||
/* Don't run the exit trap if we're supposed to be ignoring traps in a
|
||||
subshell environment. */
|
||||
if ((subshell_environment & SUBSHELL_IGNTRAP) == 0)
|
||||
run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
|
||||
|
||||
kill_shell (sig);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -7143,10 +7143,8 @@ function_substitute (char *string, int quoted, int flags)
|
||||
add_unwind_protect (uw_unbind_localvar, "REPLY");
|
||||
}
|
||||
|
||||
#if 1 /* TAG:bash-5.3 myoga.murase@gmail.com 04/30/2024 */
|
||||
old_frozen = freeze_jobs_list (-1);
|
||||
add_unwind_protect (uw_lastpipe_cleanup, (void *) (intptr_t) old_frozen);
|
||||
#endif
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
unwind_protect_var (pipeline_pgrp);
|
||||
@@ -8768,7 +8766,7 @@ string_var_assignment (SHELL_VAR *v, char *s)
|
||||
sprintf (ret, "declare -%s %s", flags, v->name); /* just attributes, unset */
|
||||
else if (i > 0)
|
||||
sprintf (ret, "declare -%s %s=%s", flags, v->name, val); /* attributes, set */
|
||||
#if 1 /*TAG: bash-5.3 tentative */
|
||||
#if 1 /*TAG: bash-5.4 tentative */
|
||||
else if (i == 0 && val && local_p (v) && variable_context == v->context)
|
||||
sprintf (ret, "declare %s=%s", v->name, val); /* set local variable at current scope */
|
||||
else if (i == 0 && val == 0 && local_p (v) && variable_context == v->context)
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
# this locale causes problems all over the place
|
||||
if [ -z "$ZH_LOCALE" ]; then
|
||||
echo "${CSTART}glob2.sub: warning${CEND}: you do not have the zh_TW.big5 locale installed;" >&2
|
||||
echo "${TAB}glob2.sub: that may cause some of these tests to fail." >&2
|
||||
echo "${TAB}that may cause some of these tests to fail." >&2
|
||||
ZH_LOCALE=$ZH_DEFAULT
|
||||
fi
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
/* variables.c -- Functions for hacking shell variables. */
|
||||
|
||||
/* Copyright (C) 1987-2025 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2026 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -455,7 +455,7 @@ initialize_shell_variables (char **env, int privmode)
|
||||
STREQN (BASHARRAY_SUFFIX, name + char_index - BASHARRAY_SUFFLEN, BASHARRAY_SUFFLEN) &&
|
||||
*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
|
||||
{
|
||||
size_t namelen, slen;
|
||||
size_t namelen;
|
||||
char *tname; /* desired imported array variable name */
|
||||
|
||||
namelen = char_index - BASHARRAY_PREFLEN - BASHARRAY_SUFFLEN;
|
||||
|
||||
Reference in New Issue
Block a user