mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-30 17:09:50 +02:00
change posix-mode implicit redirection from /dev/null for asynchronous commands so that 0<&0 does not count as an explicit redirection for austin-group interp 1913; fix spurious debug message about job notification for -c command; fix error handling for wait builtin if there are no children in a subshell
This commit is contained in:
@@ -12482,3 +12482,33 @@ redir.c
|
||||
- stdin_redirection: now take the entire REDIRECT * as its argument,
|
||||
so we can do additional posix-mandated checking on redirections
|
||||
like 0<&0, to satisfy interp 1913
|
||||
- stdin_redirection: if we are in posix mode, a redirection like
|
||||
0<&0 does not count as an explicit stdin redirection for the purpose
|
||||
of redirecting input from /dev/null, POSIX interp 1913
|
||||
|
||||
doc/bash.1,doc/bashref.texi
|
||||
- update the description of implicit redirection of stdin for async
|
||||
commands from /dev/null with the caveat that an explicit redirection
|
||||
of stdin overrides this
|
||||
- update the posix mode section with info from interp 1913 about how
|
||||
<&0 doesn't count as an explicit redirection of stdin
|
||||
|
||||
1/2/2026
|
||||
--------
|
||||
jobs.c
|
||||
- notify_of_job_status: hold onto the job's exit status without printing
|
||||
a notification if the shell has started to run -c command and the
|
||||
job is in a () subshell or a compound command with pipe input;
|
||||
otherwise we get a spurious catch-all message
|
||||
|
||||
1/5
|
||||
---
|
||||
variables.c
|
||||
- initialize_shell_variables: change string index and length variables
|
||||
to size_t
|
||||
Inspired by report from Marc Aurèle La France <tsi@tuyoix.net>
|
||||
|
||||
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>
|
||||
|
||||
@@ -1492,6 +1492,7 @@ tests/redir10.sub f
|
||||
tests/redir11.sub f
|
||||
tests/redir12.sub f
|
||||
tests/redir13.in f
|
||||
tests/redir14.sub f
|
||||
tests/rhs-exp.tests f
|
||||
tests/rhs-exp.right f
|
||||
tests/rhs-exp1.sub f
|
||||
|
||||
+13
-5
@@ -5,7 +5,7 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet.ramey@case.edu
|
||||
.\"
|
||||
.\" Last Change: Fri Dec 26 18:21:22 EST 2025
|
||||
.\" Last Change: Wed Dec 31 18:30:12 EST 2025
|
||||
.\"
|
||||
.\" 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 26" "GNU Bash 5.3"
|
||||
.TH BASH 1 "2025 December 31" "GNU Bash 5.3"
|
||||
.\"
|
||||
.ie \n(.g \{\
|
||||
.ds ' \(aq
|
||||
@@ -774,11 +774,18 @@ of a semicolon to delimit commands.
|
||||
.PP
|
||||
If a command is terminated by the control operator
|
||||
.BR & ,
|
||||
the shell executes the command in the \fIbackground\fP
|
||||
the shell executes the command asynchronously
|
||||
in a subshell.
|
||||
This is known as executing a command in the \fIbackground\fP,
|
||||
and these are referred to as \fIasynchronous\fP commands.
|
||||
The shell does not wait for the command to
|
||||
finish, and the return status is 0.
|
||||
These are referred to as \fIasynchronous\fP commands.
|
||||
When job control is not active,
|
||||
the standard input for asynchronous commands,
|
||||
in the absence of any explicit redirections involving the standard input,
|
||||
is redirected from
|
||||
.FN /dev/null .
|
||||
.PP
|
||||
Commands separated or terminated by
|
||||
.B ;
|
||||
(or an equivalent
|
||||
@@ -5920,7 +5927,8 @@ for how to control this behavior when not in posix mode.
|
||||
.PP
|
||||
If a command is followed by a \fB&\fP and job control is not active, the
|
||||
default standard input for the command is the empty file
|
||||
.FN /dev/null .
|
||||
.FN /dev/null ,
|
||||
unless the command has an explicit redirection involving the standard input.
|
||||
Otherwise, the invoked command inherits the file descriptors of the calling
|
||||
shell as modified by redirections.
|
||||
.SH ENVIRONMENT
|
||||
|
||||
+17
-4
@@ -914,8 +914,9 @@ and these are referred to as @dfn{asynchronous} commands.
|
||||
The shell does not wait for the command to finish, and the return
|
||||
status is 0 (true).
|
||||
When job control is not active (@pxref{Job Control}),
|
||||
the standard input for asynchronous commands, in the absence of any
|
||||
explicit redirections, is redirected from @code{/dev/null}.
|
||||
the standard input for asynchronous commands,
|
||||
in the absence of any explicit redirections involving the standard input,
|
||||
is redirected from @file{/dev/null}.
|
||||
|
||||
Commands separated or terminated by
|
||||
@samp{;} (or equivalent @code{newline})
|
||||
@@ -3867,7 +3868,8 @@ See the description of the @code{inherit_errexit} shell option
|
||||
in @sc{posix} mode.
|
||||
|
||||
If a command is followed by a @samp{&} and job control is not active, the
|
||||
default standard input for the command is the empty file @file{/dev/null}.
|
||||
default standard input for the command is the empty file @file{/dev/null},
|
||||
unless the command has an explicit redirection involving the standard input.
|
||||
Otherwise, the invoked command inherits the file descriptors of the calling
|
||||
shell as modified by redirections.
|
||||
|
||||
@@ -9240,7 +9242,8 @@ The Bash @dfn{posix mode} changes the Bash
|
||||
behavior in these areas so that it conforms more strictly
|
||||
to the standard.
|
||||
|
||||
Starting Bash with the @option{--posix} command-line option or executing
|
||||
Starting Bash with the @option{--posix} or @option{-o posix}
|
||||
command-line option or executing
|
||||
@samp{set -o posix} while Bash is running will cause Bash to conform more
|
||||
closely to the @sc{posix} standard by changing the behavior to
|
||||
match that specified by @sc{posix} in areas where the Bash default differs.
|
||||
@@ -9364,6 +9367,16 @@ Bash will not insert a command without the execute bit set into the
|
||||
command hash table, even if it returns it as a (last-ditch) result
|
||||
from a @env{$PATH} search.
|
||||
|
||||
@item
|
||||
Normally, when job control is not enabled,
|
||||
the shell implicitly redirects the standard input of
|
||||
asynchronous commands from @file{/dev/null}.
|
||||
A redirection to the standard input in this command inhibits this
|
||||
implicit redirection.
|
||||
In @sc{posix} mode, a redirection that redirects file descriptor 0
|
||||
to itself (e.g., @samp{<&0}) does not count as a redirection that
|
||||
overrides the implicit redirection from @file{/dev/null}.
|
||||
|
||||
@item
|
||||
The message printed by the job control code and builtins when a job
|
||||
exits with a non-zero status is ``Done(status)''.
|
||||
|
||||
+2
-3
@@ -2,11 +2,10 @@
|
||||
Copyright (C) 1988-2025 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Fri Dec 26 18:21:22 EST 2025
|
||||
|
||||
@set LASTCHANGE Wed Dec 31 18:26:37 EST 2025
|
||||
|
||||
@set EDITION 5.3
|
||||
@set VERSION 5.3
|
||||
|
||||
@set UPDATED 26 December 2025
|
||||
@set UPDATED 31 December 2025
|
||||
@set UPDATED-MONTH December 2025
|
||||
|
||||
+10
-11
@@ -847,7 +847,8 @@ execute_command_internal (COMMAND *command, int asynchronous, int pipe_in, int p
|
||||
#endif /* COMMAND_TIMING */
|
||||
|
||||
/* Is this a compound command with a redirection from stdin? POSIX interp
|
||||
1913 makes it matter. */
|
||||
1913 makes it matter. There is an exception for 0<&0 or <&0 or equivalent
|
||||
when in posix mode. */
|
||||
if (shell_control_structure (command->type) && command->redirects)
|
||||
{
|
||||
stdin_redirected = stdin_redirects (command->redirects);
|
||||
@@ -4876,13 +4877,11 @@ run_builtin:
|
||||
{
|
||||
if ((cmdflags & CMD_STDIN_REDIR) &&
|
||||
pipe_in == NO_PIPE &&
|
||||
#if 0 /*TAG:bash-5.4 POSIX interp 1913 */
|
||||
/* POSIX interp 1913 says that the redirection of fd 0
|
||||
from /dev/null is unconditional. */
|
||||
(posixly_correct || stdin_redirects (simple_command->redirects) == 0))
|
||||
#else
|
||||
from /dev/null is performed unless the command has
|
||||
a redirection that's something like 0<&0 or <&0.
|
||||
See redir.c:stdin_redirection() for the details. */
|
||||
(stdin_redirects (simple_command->redirects) == 0))
|
||||
#endif
|
||||
async_redirect_stdin ();
|
||||
setup_async_signals ();
|
||||
}
|
||||
@@ -5917,15 +5916,15 @@ execute_disk_command (WORD_LIST *words, REDIRECT *redirects, char *command_line,
|
||||
in asynchronous children. */
|
||||
if (async)
|
||||
{
|
||||
/*itrace("execute_disk_command: async = 1 cmd_stdin_redir = %d stdin_redirects (redirects) = %d",
|
||||
(cmdflags & CMD_STDIN_REDIR), stdin_redirects (redirects));*/
|
||||
if ((cmdflags & CMD_STDIN_REDIR) &&
|
||||
pipe_in == NO_PIPE &&
|
||||
#if 0 /*TAG:bash-5.4 POSIX interp 1913 */
|
||||
/* POSIX interp 1913 says that the redirection of fd 0
|
||||
from /dev/null is unconditional. */
|
||||
(posixly_correct || stdin_redirects (redirects) == 0))
|
||||
#else
|
||||
from /dev/null is performed unless the command has
|
||||
a redirection that's something like 0<&0 or <&0.
|
||||
See redir.c:stdin_redirection() for the details. */
|
||||
(stdin_redirects (redirects) == 0))
|
||||
#endif
|
||||
async_redirect_stdin ();
|
||||
setup_async_signals ();
|
||||
}
|
||||
|
||||
@@ -2841,7 +2841,7 @@ wait_for_background_pids (int wflags, struct procstat *ps)
|
||||
ps->pid = pid;
|
||||
ps->status = (r < 0 || r > 256) ? 127 : r;
|
||||
}
|
||||
if (r == -1 && errno == ECHILD)
|
||||
if ((r < 0 || r > 256) && errno == ECHILD)
|
||||
{
|
||||
/* If we're mistaken about job state, compensate. */
|
||||
check_async = 0;
|
||||
@@ -4603,6 +4603,14 @@ notify_of_job_status (int wanted)
|
||||
((DEADJOB (job) && IS_FOREGROUND (job) == 0) || STOPPED (job)))
|
||||
continue;
|
||||
|
||||
/* hang onto the status if the shell is running -c command and the
|
||||
command is running in a () subshell or a compound command with
|
||||
pipe input */
|
||||
else if (startup_state == 2 && (subshell_environment & (SUBSHELL_PAREN|SUBSHELL_PIPE)) &&
|
||||
WIFSIGNALED (s) == 0 &&
|
||||
((DEADJOB (job) && IS_FOREGROUND (job) == 0) || STOPPED (job)))
|
||||
continue;
|
||||
|
||||
/* If job control is disabled, don't print the status messages.
|
||||
Mark dead jobs as notified so that they get cleaned up. If
|
||||
startup_state == 2 and subshell_environment has the
|
||||
@@ -4684,7 +4692,7 @@ notify_of_job_status (int wanted)
|
||||
/* XXX - this is a catch-all in case we missed a state */
|
||||
else
|
||||
{
|
||||
internal_debug("notify_of_job_status: catch-all setting J_NOTIFIED on job %d (%d), startup state = %d", job, jobs[job]->flags, startup_state);
|
||||
internal_debug("notify_of_job_status: catch-all setting J_NOTIFIED on job %d (%d), startup state = %d subshell_environment = %d", job, jobs[job]->flags, startup_state, subshell_environment);
|
||||
jobs[job]->flags |= J_NOTIFIED;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1400,8 +1400,15 @@ stdin_redirection (REDIRECT *rp)
|
||||
case r_reading_string:
|
||||
return (1);
|
||||
case r_duplicating_input:
|
||||
case r_duplicating_input_word:
|
||||
case r_close_this:
|
||||
return (rp->redirector.dest == 0
|
||||
#if 1 /*TAG: bash-5.4 POSIX interp 1913 */
|
||||
&& (posixly_correct == 0 || rp->redirectee.dest != 0)
|
||||
#endif
|
||||
);
|
||||
case r_duplicating_input_word:
|
||||
/* we defer evaluation of this until later, so just return based on the
|
||||
destination for now. */
|
||||
return (rp->redirector.dest == 0);
|
||||
case r_output_direction:
|
||||
case r_appending_to:
|
||||
|
||||
@@ -195,3 +195,34 @@ after ERR trap: 1
|
||||
got error ERR
|
||||
./redir12.sub: line 56: unreadable-file: Permission denied
|
||||
/tmp
|
||||
redir14.sub
|
||||
standard 1 - <&0
|
||||
line 1
|
||||
line 2
|
||||
posix 1 - <&0
|
||||
standard 2 - 0<&0
|
||||
line 1
|
||||
line 2
|
||||
posix 2 - 0<&0
|
||||
standard 3 - subshell containing AND-OR list <&0
|
||||
line 1
|
||||
line 2
|
||||
posix 3 - subshell containing AND-OR list <&0
|
||||
standard - subshell with explicit redirection
|
||||
line 1
|
||||
line 2
|
||||
posix - subshell with explicit redirection
|
||||
line 1
|
||||
line 2
|
||||
standard 1 - compound command with AND-OR list with pipe input
|
||||
hello inpipe
|
||||
posix 1 - compound command with AND-OR list with pipe input
|
||||
hello inpipe
|
||||
standard 2 - simple command with AND-OR list with pipe input
|
||||
jello inpipe
|
||||
posix 2 - simple command with AND-OR list with pipe input
|
||||
jello inpipe
|
||||
standard 3 - subshell command with AND-OR list with pipe input
|
||||
hello inpipe
|
||||
posix 3 - subshell command with AND-OR list with pipe input
|
||||
hello inpipe
|
||||
|
||||
@@ -224,3 +224,5 @@ test_runsub ./redir11.sub
|
||||
test_runsub ./redir12.sub
|
||||
|
||||
${THIS_SH} < ./redir13.in
|
||||
|
||||
test_runsub ./redir14.sub
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
: ${TMPDIR:=/tmp} ${THIS_SH:=./bash}
|
||||
TMPFILE=$TMPDIR/redir-in-$$
|
||||
|
||||
trap 'rm -f $TMPFILE' 0
|
||||
|
||||
cat >$TMPFILE <<EOF
|
||||
line 1
|
||||
line 2
|
||||
EOF
|
||||
|
||||
export TMPFILE
|
||||
echo standard 1 - '<&0'
|
||||
${THIS_SH} -c 'exec < $TMPFILE ; cat <&0 & wait'
|
||||
echo posix 1 - '<&0'
|
||||
${THIS_SH} -o posix -c 'exec < $TMPFILE ; cat <&0 & wait'
|
||||
|
||||
echo standard 2 - '0<&0'
|
||||
${THIS_SH} -c 'exec < $TMPFILE ; cat 0<&0 & wait'
|
||||
echo posix 2 - '0<&0'
|
||||
${THIS_SH} -o posix -c 'exec < $TMPFILE ; cat 0<&0 & wait'
|
||||
|
||||
echo standard 3 - subshell containing AND-OR list '<&0'
|
||||
${THIS_SH} -c 'exec < $TMPFILE ; ( cat <&0 & wait )'
|
||||
echo posix 3 - subshell containing AND-OR list '<&0'
|
||||
${THIS_SH} -o posix -c 'exec < $TMPFILE ; ( cat <&0 & wait )'
|
||||
|
||||
echo standard - subshell with explicit redirection
|
||||
${THIS_SH} -c '( cat <&0 & wait ) <$TMPFILE'
|
||||
echo posix - subshell with explicit redirection
|
||||
${THIS_SH} -o posix -c '( cat <&0 & wait ) <$TMPFILE'
|
||||
|
||||
# pipeline input inhibits the implicit redirection from /dev/null; posix mode
|
||||
# does not make a difference -- POSIX interp 1913
|
||||
echo standard 1 - compound command with AND-OR list with pipe input
|
||||
${THIS_SH} -c 'echo "hello inpipe" | { cat 0<&0 & wait; }'
|
||||
echo posix 1 - compound command with AND-OR list with pipe input
|
||||
${THIS_SH} -o posix -c 'echo "hello inpipe" | { cat 0<&0 & wait; }'
|
||||
|
||||
echo standard 2 - simple command with AND-OR list with pipe input
|
||||
${THIS_SH} -c 'echo "jello inpipe" | cat 0<&0 & wait'
|
||||
echo posix 2 - simple command with AND-OR list with pipe input
|
||||
${THIS_SH} -o posix -c 'echo "jello inpipe" | cat 0<&0 & wait'
|
||||
|
||||
echo standard 3 - subshell command with AND-OR list with pipe input
|
||||
${THIS_SH} -c 'echo "hello inpipe" | ( cat <&0 & wait )'
|
||||
echo posix 3 - subshell command with AND-OR list with pipe input
|
||||
${THIS_SH} -o posix -c 'echo "hello inpipe" | ( cat <&0 & wait )'
|
||||
+3
-2
@@ -369,7 +369,8 @@ void
|
||||
initialize_shell_variables (char **env, int privmode)
|
||||
{
|
||||
char *name, *string, *temp_string;
|
||||
int c, char_index, string_index, string_length, ro;
|
||||
int c, ro;
|
||||
size_t char_index, string_index, string_length;
|
||||
SHELL_VAR *temp_var;
|
||||
|
||||
create_variable_tables ();
|
||||
@@ -454,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;
|
||||
size_t namelen, slen;
|
||||
char *tname; /* desired imported array variable name */
|
||||
|
||||
namelen = char_index - BASHARRAY_PREFLEN - BASHARRAY_SUFFLEN;
|
||||
|
||||
Reference in New Issue
Block a user