On Fri, Jan 10, 2025, at 7:50 PM, Christoph Anton Mitterer via austin-group-l
at The Open Group wrote:
> Now even with #1879 solved, another problem with that is however the
> following part of POSIX' definition for the `exec` special built-in:
>
>> If exec is specified with no operands, any redirections associated
>> with the exec command shall be made in the current shell execution
>> environment. If any file descriptors with numbers greater than 2 are
>> opened by those redirections, it is unspecified whether those file
>> descriptors remain open when the shell invokes another utility.
>
> IOW, for any FDs greater than 2, it’s *not* guaranteed that a shell
> passes the redirected FDs on to the utilities.
>
> Which means that the above redirection (</does-not-exist/file) should
> actually be guaranteed to work portably,
> but doing something more complex like:
> command exec 3>&1 || return 125
> captured_stderr="$( command exec 2>&1 >&3 3>&- || exit 125; utility
> )" || exit_status="$?"
> command exec 3>&- || return 125
>
> is not guaranteed to work.
Not in general, but for this specific example I don't see why not.
It's portable to use FD 3 inside the command substitution because
subshells aren't utilities, and the actual "utility" clearly doesn't
try to use FD 3, given that you close it first.
And behold, it works with the four FD-closing shells yet mentioned:
% cat /tmp/exec_tricks.sh
date >/tmp/date
command exec 3>&1 || exit 125
stderr=$(
command exec 2>&1 >&3 3>&- || exit 125
cat /tmp/date nosuchfile
)
rc=$?
command exec 3>&- || exit 125
echo ===
printf '%s\n' "$stderr" "$rc"
echo
% /bin/ksh /tmp/exec_tricks.sh
Sun Jan 12 17:57:22 EST 2025
===
cat: nosuchfile: No such file or directory
1
% /opt/local/bin/ksh /tmp/exec_tricks.sh
Sun Jan 12 17:57:32 EST 2025
===
cat: nosuchfile: No such file or directory
1
% mksh /tmp/exec_tricks.sh
Sun Jan 12 17:57:36 EST 2025
===
/tmp/exec_tricks.sh[7]: cat: nosuchfile: No such file or directory
1
% oksh /tmp/exec_tricks.sh
Sun Jan 12 17:57:37 EST 2025
===
cat: nosuchfile: No such file or directory
1
%
--
vq