Hey there.
For some backstory, please see the already accepted: https://www.austingroupbugs.net/view.php?id=1879 and its changes. The motivation there was to find out whether POSIX actually mandates that: command exec some-redirections is expected to *not* cause the shell to exit/abort in case of redirection errors (but still have the redirections, if successful, effective in the current shell execution environment). The answer to that was apparently yes. The motivation for that in turn was, finding a portable way to differentiate in a command like: utility some-redirections whether a non-zero exit status came form the utility itself or from an error in redirections (for which, AFAIK, POSIX leaves the actual exit status open, other than it has to be non-zero). The idea was that instead of: utility </does-not-exist/file a construct like: ( command exec </does-not-exist/file || exit 100; utility ) would portably allow to differentiate (while the utility would still get the redirections), assuming of course that the special exit status (here 100) is know to be not used by utility. 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. The exec 3>&1 and exec 3>&- are done separately, because when no command name results (as with above assignment), POSIX leaves it open whether any redirections would be performed before or after the assignment (and shells actually differ in behaviour, e.g. dash/bash). The overall goal of the above example would be to capture stderr of the utility, let stdout of it through (to stdout), not "leak" the helper FD 3 to the utility and capture the exit status of it. However, with exec not being guaranteed to work portably for FDs greater than 2, I cannot see any other way to get that done. bash/dash seem to pass on the redirected FDs, but I found at least on shell wich doesn’t namely, mksh, which explicitly documents[0] the behaviour. $ dash -c "exec 8</dev/null; ls /proc/self/fd/8" /proc/self/fd/8 $ bash -c "exec 8</dev/null; ls /proc/self/fd/8" /proc/self/fd/8 $ mksh -c "exec 8</dev/null; ls /proc/self/fd/8" ls: cannot access '/proc/self/fd/8': No such file or directory $ Not sure what’s the intention of not passing on FDs > 2, because one could always just close such FDs via redirection specifically for the utility. Any other means to get the desired goal (in a portable way)? Or could the behaviour/standard be changed? Cheers, Chris. [0] https://manpages.debian.org/bookworm/mksh/mksh.1.en.html#exec
