Hi Serge, ltns,
In Debian bug #726735, you wrote:
Therefore, the shell cannot, in the general case, know about this
redirection when it forks the child process. For some reason, bash still
overrides the implicit </dev/null if the outer command has a redirection
of stdin, and therefore your example works with bash.
The following version works in various shells:
{ sleep 100 & } </dev/stdin
(A <&0 is treated as a no-op by Almquist derivatives such as FreeBSD and
NetBSD /bin/sh, even for the purpose of suppressing the </dev/null
implicit in background commands; I consider this a bug and have fixed it
in FreeBSD 11-current.)
The code to suppress the implicit </dev/null in ash is very old. It is
in the first version of bin/sh/redir.c in the FreeBSD repository, and
the NetBSD commit that added it is from May 2, 1993 by 'sef', message
'Jim "wilson@moria.cygnus.com" Wilson's patches to make C News (and
other things) work.'. It looks like this code was deliberately removed
from dash years ago. No version in the dash git repository has it.
In particular, the modified example works in both ksh93 and the original
Bourne shell (Heirloom). Together with the fact that this override is
explicitly mentioned in POSIX (that the redirection in
sleep 100 </dev/tty &
overrides the implicit /dev/null is obvious and would not warrant
explicit notice), I think the removal from dash was wrong.
Note that mksh does not implement this feature either, so relying on it
in scripts seems unwise at this time. Instead, duplicate stdin in the
parent and put it back in the child:
{ foo <&3 3<&- & } 3<&0