autoconf: File Descriptors

1 
1 11.4 File Descriptors
1 =====================
1 
1 Most shells, if not all (including Bash, Zsh, Ash), output traces on
1 stderr, even for subshells.  This might result in undesirable content
1 if you meant to capture the standard-error output of the inner command:
1 
1      $ ash -x -c '(eval "echo foo >&2") 2>stderr'
1      $ cat stderr
1      + eval echo foo >&2
1      + echo foo
1      foo
1      $ bash -x -c '(eval "echo foo >&2") 2>stderr'
1      $ cat stderr
1      + eval 'echo foo >&2'
1      ++ echo foo
1      foo
1      $ zsh -x -c '(eval "echo foo >&2") 2>stderr'
1      # Traces on startup files deleted here.
1      $ cat stderr
1      +zsh:1> eval echo foo >&2
1      +zsh:1> echo foo
1      foo
1 
1 One workaround is to grep out uninteresting lines, hoping not to remove
1 good ones.
1 
1    If you intend to redirect both standard error and standard output,
1 redirect standard output first.  This works better with HP-UX, since
1 its shell mishandles tracing if standard error is redirected first:
1 
1      $ sh -x -c ': 2>err >out'
1      + :
1      + 2> err $ cat err
1      1> out
1 
1    Don't try to redirect the standard error of a command substitution.
1 It must be done _inside_ the command substitution.  When running `: `cd
1 /zorglub` 2>/dev/null' expect the error message to escape, while `: `cd
1 /zorglub 2>/dev/null`' works properly.
1 
1    On the other hand, some shells, such as Solaris or FreeBSD
1 `/bin/sh', warn about missing programs before performing redirections.
1 Therefore, to silently check whether a program exists, it is necessary
1 to perform redirections on a subshell or brace group:
1      $ /bin/sh -c 'nosuch 2>/dev/null'
1      nosuch: not found
1      $ /bin/sh -c '(nosuch) 2>/dev/null'
1      $ /bin/sh -c '{ nosuch; } 2>/dev/null'
1      $ bash -c 'nosuch 2>/dev/null'
1 
1    FreeBSD 6.2 sh may mix the trace output lines from the statements in
1 a shell pipeline.
1 
1    It is worth noting that Zsh (but not Ash nor Bash) makes it possible
1 in assignments though: `foo=`cd /zorglub` 2>/dev/null'.
1 
1    Some shells, like `ash', don't recognize bi-directional redirection
1 (`<>').  And even on shells that recognize it, it is not portable to
1 use on fifos: Posix does not require read-write support for named
1 pipes, and Cygwin does not support it:
1 
1      $ mkfifo fifo
1      $ exec 5<>fifo
1      $ echo hi >&5
1      bash: echo: write error: Communication error on send
1 
1 Furthermore, versions of `dash' before 0.5.6 mistakenly truncate
1 regular files when using `<>':
1 
1      $ echo a > file
1      $ bash -c ': 1<>file'; cat file
1      a
1      $ dash -c ': 1<>file'; cat file
1      $ rm a
1 
1    When catering to old systems, don't redirect the same file descriptor
1 several times, as you are doomed to failure under Ultrix.
1 
1      ULTRIX V4.4 (Rev. 69) System #31: Thu Aug 10 19:42:23 GMT 1995
1      UWS V4.4 (Rev. 11)
1      $ eval 'echo matter >fullness' >void
1      illegal io
1      $ eval '(echo matter >fullness)' >void
1      illegal io
1      $ (eval '(echo matter >fullness)') >void
1      Ambiguous output redirect.
1 
1 In each case the expected result is of course `fullness' containing
1 `matter' and `void' being empty.  However, this bug is probably not of
1 practical concern to modern platforms.
1 
1    Solaris 10 `sh' will try to optimize away a `:' command (even if it
1 is redirected) in a loop after the first iteration, or in a shell
1 function after the first call:
1 
1      $ for i in 1 2 3 ; do : >x$i; done
1      $ ls x*
1      x1
1      $ f () { : >$1; }; f y1; f y2; f y3;
1      $ ls y*
1      y1
1 
1 As a workaround, `echo' or `eval' can be used.
1 
1    Don't rely on file descriptors 0, 1, and 2 remaining closed in a
1 subsidiary program.  If any of these descriptors is closed, the
1 operating system may open an unspecified file for the descriptor in the
1 new process image.  Posix 2008 says this may be done only if the
1 subsidiary program is set-user-ID or set-group-ID, but HP-UX 11.23 does
1 it even for ordinary programs, and the next version of Posix will allow
1 HP-UX behavior.
1 
1    If you want a file descriptor above 2 to be inherited into a child
1 process, then you must use redirections specific to that command or a
1 containing subshell or command group, rather than relying on `exec' in
1 the shell. In `ksh' as well as HP-UX `sh', file descriptors above 2
1 which are opened using `exec N>file' are closed by a subsequent `exec'
1 (such as that involved in the fork-and-exec which runs a program or
1 script):
1 
1      $ echo 'echo hello >&5' >k
1      $ /bin/sh -c 'exec 5>t; ksh ./k; exec 5>&-; cat t
1      hello
1      $ bash -c 'exec 5>t; ksh ./k; exec 5>&-; cat t
1      hello
1      $ ksh -c 'exec 5>t; ksh ./k; exec 5>&-; cat t
1      ./k[1]: 5: cannot open [Bad file number]
1      $ ksh -c '(ksh ./k) 5>t; cat t'
1      hello
1      $ ksh -c '{ ksh ./k; } 5>t; cat t'
1      hello
1      $ ksh -c '5>t ksh ./k; cat t
1      hello
1 
1    Don't rely on duplicating a closed file descriptor to cause an
1 error.  With Solaris `/bin/sh', failed duplication is silently ignored,
1 which can cause unintended leaks to the original file descriptor.  In
1 this example, observe the leak to standard output:
1 
1      $ bash -c 'echo hi >&3' 3>&-; echo $?
1      bash: 3: Bad file descriptor
1      1
1      $ /bin/sh -c 'echo hi >&3' 3>&-; echo $?
1      hi
1      0
1 
1    Fortunately, an attempt to close an already closed file descriptor
1 will portably succeed.  Likewise, it is safe to use either style of
1 `N<&-' or `N>&-' for closing a file descriptor, even if it doesn't
1 match the read/write mode that the file descriptor was opened with.
1 
1    DOS variants cannot rename or remove open files, such as in `mv foo
1 bar >foo' or `rm foo >foo', even though this is perfectly portable
1 among Posix hosts.
1 
1    A few ancient systems reserved some file descriptors.  By convention,
1 file descriptor 3 was opened to `/dev/tty' when you logged into Eighth
1 Edition (1985) through Tenth Edition Unix (1989).  File descriptor 4
1 had a special use on the Stardent/Kubota Titan (circa 1990), though we
1 don't now remember what it was.  Both these systems are obsolete, so
1 it's now safe to treat file descriptors 3 and 4 like any other file
1 descriptors.
1 
1    On the other hand, you can't portably use multi-digit file
1 descriptors.  Solaris `ksh' doesn't understand any file descriptor
1 larger than `9':
1 
1      $ bash -c 'exec 10>&-'; echo $?
1      0
1      $ ksh -c 'exec 9>&-'; echo $?
1      0
1      $ ksh -c 'exec 10>&-'; echo $?
1      ksh[1]: exec: 10: not found
1      127
1