"trap" output from "if" statement redirected wrongly

2022-04-13 Thread Frank Heckenbach
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -g -O2 -fstack-protector-strong -Wformat 
-Werror=format-security -Wall 
uname output: Linux mars 5.10.0-12-amd64 #1 SMP Debian 5.10.103-1 (2022-03-07) 
x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 5.1
Patch Level: 16
Release Status: release

Description:

This script writes "foo" to bar rather than stdout as I'd expect.

It's triggered by the "if" statement (which doesn't even cause
running in a subshell, so it's not that).

#!/bin/bash
set -e
trap 'echo foo' 0
#false > bar  # "foo" written to stdout correctly
if true; then false; else false; fi > bar  # "foo" written to bar



Re: "trap" output from "if" statement redirected wrongly

2022-04-13 Thread Jesse Hathaway
On Wed, Apr 13, 2022 at 7:59 AM Frank Heckenbach
 wrote:
> This script writes "foo" to bar rather than stdout as I'd expect.
>
> It's triggered by the "if" statement (which doesn't even cause
> running in a subshell, so it's not that).
>
> #!/bin/bash
> set -e
> trap 'echo foo' 0
> #false > bar  # "foo" written to stdout correctly
> if true; then false; else false; fi > bar  # "foo" written to bar

I don't believe this is a bug, though Chet is welcome to chime in
with an authoritative answer. The script exits after the else clause
because false returns 1 and errexit is set. At this point in the program
stdout has been redirect to the file bar, so when the trap echos to
stdout its content goes to bar as well. I don't see anything in the
docs about traps resetting their output file descriptors before they
are ran. To work around this you need to save the original stdout file
descriptor. Something like this:

#!/bin/bash
exec {STDOUT}>&1
exec {STDERR}>&2
set -e
trap 'echo foo >&${STDOUT}' EXIT
if true; then false; else false; fi >bar



Re: "trap" output from "if" statement redirected wrongly

2022-04-13 Thread Frank Heckenbach
> On Wed, Apr 13, 2022 at 7:59 AM Frank Heckenbach
>  wrote:
> > This script writes "foo" to bar rather than stdout as I'd expect.
> >
> > It's triggered by the "if" statement (which doesn't even cause
> > running in a subshell, so it's not that).
> >
> > #!/bin/bash
> > set -e
> > trap 'echo foo' 0
> > #false > bar  # "foo" written to stdout correctly
> > if true; then false; else false; fi > bar  # "foo" written to bar
> 
> I don't believe this is a bug, though Chet is welcome to chime in
> with an authoritative answer. The script exits after the else clause
> because false returns 1 and errexit is set. At this point in the program
> stdout has been redirect to the file bar, so when the trap echos to
> stdout its content goes to bar as well. I don't see anything in the
> docs about traps resetting their output file descriptors before they
> are ran.

I don't see anything to the contrary either. Syntactically, the
redirection applies to the main statement, not the trap. When and
how redirections are set up and reset is an implementation detail.

Moreover, I don't see anything that would make a difference between
the "if" statement and the plain one, so if the behaviour you
describe is correct, the bug is that the non-"if" statement actually
writes to stdout. :P

> To work around this you need to save the original stdout file
> descriptor.

I know how to work around. But that makes me wonder. What is
actually required to use a trap-statement safely (meaning, in a
non-surprising way)? I know (for an EXIT trap) to save "$?" and
"rethrow" it, now it seems one needs to save all FDs it might use
(STDOUT, STDERR, maybe STDIN or other FDs one might redirect
somewhere). What else is required? Is this documented anywhere?



Bash-5.2-beta available

2022-04-13 Thread Chet Ramey
The first beta release of bash-5.2 is now available with the URLs

ftp://ftp.cwru.edu/pub/bash/bash-5.2-beta.tar.gz
https://ftp.gnu.org/pub/gnu/bash/bash-5.2-beta.tar.gz

and from the bash-5.2-testing branch in the bash git repository
(http://git.savannah.gnu.org/cgit/bash.git/log/?h=bash-5.2-testing).
You can use

git clone --branch bash-5.2-testing git://git.savannah.gnu.org/bash.git

to clone the testing branch.

The CWRU FTP site works best if your client supports Extended Passive
(EPSV) mode.

This tar file includes the formatted documentation (you should be able to
generate updated versions yourself).

This release fixes several outstanding bugs in bash-5.1 and introduces
a number of new features. There are significant new features of note:

* The parser now calls itself recursively to parse command substitutions,
  and reconstitutes the text from the parsed command. This allows better
  syntax checking and catches errors much earlier;

* Bash-5.2 improves associative array subscript parsing with the goal of
  eliminating double evaluation for shell constructs such as arithmetic
  expansion and conditional commands, the `unset' builtin, and arguments
  to other builtin commands as long as assoc_expand_once is set;

* Associative arrays now allow assignment to and unsetting `@' and `*' keys,
  and the `unset' builtin treats `@' and `*' keys differently to allow this;

* There is an alternate array implementation, selectable at configuration
  time, that optimizes access speed over memory use (but can use considerably
  more memory for large sparse arrays);

* There is a configuration option to compile $"..." string translation out of
  the shell, and a runtime shell option to inhibit any additional expansion
  of translated strings;

* The new `varredir_close' shell option causes bash to automatically close
  file descriptors opened with {var} 128 in the current encoding.

hh. Fixed a problem that could cause the shell to attempt to free unallocated
memory if an expansion error occurred.

ii. Fixed a bug in the bash malloc implementation of malloc_usable_size. Bash
did not use it, but it could cause problems with library functions that
did.

jj. If the `exec' builtin fails, and the shell does not exit, it restores
trapped signals to their trapped state.

kk. Fixed a bug that could cause variable assignment arguments to `declare' to
expand variables using attributes that the call to declare was turning off.

ll. Fixed a bug with LINENO and arithmetic for commands.

mm. Fixed a posix-mode bug that caused tildes not to be expanded after an
unquoted colon on the right side of an assignment statement.

nn. Fixed a problem with `caller' and line numbers when executing an ERR trap.

oo. Fixed a problem that could make the value returned by ${a:=b} not be the
final value assigned to a (e.g., if `a' has an attribute that modifies
the value on assignment).

pp. Fixed a problem with saving multi-line here-documents to the history list
where the here-document delimiter does not appear on the first line.

qq. Fixed a bug with using += to assign to dynamic variables like RANDOM.

rr. Fixed a bug that caused `set -n' to modify $? if set after execution had
started.

ss. Builtins like printf/read/wait now behave more consistently when assigning
arbitrary keys to associative arrays (like `]'. when appropriately quoted).

tt. Fixed a problem with here-document collection printing the wrong prompt
when parsing a compound list in an interactive shell.

uu. Fixed a problem with quoting shell expansion characters (like `$') when
they appear in a tab-completed word along with characters that do need
quoting (e.g.. $HOME/VirtualBox VMs).

2. Changes to Readline

a. Fixed a problem with cleaning up active marks when using callback mode.

b. Fixed a problem with arithmetic comparison operators checking the version.

c. Fixed a problem that could cause readline not to build on systems without
   POSIX signal functions.

d. Fixed a bug that could cause readline to crash if the application removed
   the callback line handler before readline read all typeahead.

e. Added additional checks for read errors in the middle of readline commands.

f. Fixed a redisplay problem that occurred when switching from the digit-
   argument prompt `(arg: N)' back to the regular prompt and the regular
   prompt contained invisible characters.

g. Fixed a problem with restoring the prompt when aborting an incremental
   search.

h. Fix a problem with characters > 128 not being displayed correctly in certain
   single-byte encodings.

i. Fixed a problem with unix-filename-rubout that caused it to delete too much
   when applied to a pathname consisting only of one or more slashes.

j. Fixed a display problem that caused the prompt to be wrapped incorrectly if
   the screen changed dimensions during a call to readline() and the prompt
   became longer than the screen width.

k. Fixed a problem