- 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
/* 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.
/* 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 **);
/* 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);
}
/* 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;
/* 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)
{
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)
}
}
+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
/* 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.
#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 {
.\" 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
.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
[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
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,
.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
@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
/* 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.
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)
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;
/* 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.
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. */
/* 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.
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.
/* 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.
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);
}
/* ``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.
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);
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)
# 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
/* 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.
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;