Enhance/fix isatty using command test.

Presently, `isatty` only works on a handful of keywords. Here it
  is rewritten to be able to take any path, device or fd number as
  an argument, and eliminates errors printed to stdout.
  Per discussion in #1228, using `builtin test -c` within a pipe to
  test special file descriptors is not viable, so this implementation
  specifcially uses `command test`. Additionally, a note has been
  added to the documentation of `test` regarding this potential
  aberration from the expected output of the test utility under the
  'Standards' section.
This commit is contained in:
Geoff Nixon 2014-01-07 19:57:49 -08:00 committed by pca
parent d5cb16aa1f
commit 60808a4820
3 changed files with 47 additions and 26 deletions

View file

@ -1,14 +1,29 @@
\section isatty isatty - test if the specified file descriptor is a tty \section isatty isatty - test if a file or file descriptor is a tty.
\subsection isatty-synopsis Synopsis \subsection isatty-synopsis Synopsis
<tt>isatty [FILE DESCRIPTOR]</tt> <tt>isatty [FILE | DEVICE | FILE DESCRIPTOR NUMBER]</tt>
\subsection isatty-description Description \subsection isatty-description Description
<tt>isatty</tt> tests if a file descriptor is a tty. <tt>isatty</tt> tests if a file or file descriptor is a tty.
The argument may be in the form of a file path, device, or file descriptor
number. Without an argument, <tt>standard input</tt> is implied.
<tt>FILE DESCRIPTOR</tt> may be either the number of a file descriptor, or one of the If the resolved file descriptor is a tty, the command returns zero. Otherwise, the command exits one. No messages are printed to standard error.
strings <tt>stdin</tt>, \c stdout and <tt>stderr</tt>.
If the specified file descriptor is a tty, the exit status of the command is \subsection isatty-examples Examples
zero. Otherwise, it is non-zero.
From an interactive shell, the commands below exit with a return value of zero:
<pre>
isatty
isatty stdout
isatty 2
echo | isatty /dev/fd/1
</pre>
And these will exit non-zero:
<pre>
echo | isatty
isatty /dev/fd/9
isatty stdout > file
isatty 2 2> file
</pre>

View file

@ -97,4 +97,11 @@ end.
<a href="http://www.unix.com/man-page/POSIX/1/test/">IEEE Std 1003.1-2008 <a href="http://www.unix.com/man-page/POSIX/1/test/">IEEE Std 1003.1-2008
(POSIX.1) standard</a>. The following exceptions apply: (POSIX.1) standard</a>. The following exceptions apply:
- The \c < and \c > operators for comparing strings are not implemented. - The \c < and \c > operators for comparing strings are not implemented.
- Because this test is a shell builtin and not a standalone utility, using
the -c flag on a special file descriptors like standard input and output
may not return the same result when invoked from within a pipe as one
would expect when invoking the \c test utility in another shell.
In cases such as this, one can use \c command \c test to explicitly
use the system's standalone \c test rather than this \c builtin \c test.

View file

@ -1,28 +1,27 @@
function isatty -d "Test if a file or file descriptor is a tty."
function isatty -d "Tests if a file descriptor is a tty" # Use `command test` because `builtin test` doesn't open the regular fd's.
set -l fd 0
if count $argv >/dev/null
switch $argv[1]
case -h --h --he --hel --help switch "$argv"
case '-h*' '--h*'
__fish_print_help isatty __fish_print_help isatty
return 0
case stdin case ''
set fd 0 command test -c /dev/stdin
case stdout
set fd 1
case stderr
set fd 2
case '*' case '*'
set fd $argv[1] if test -e "$argv" # The eval here is needed for symlinks. Unsure why.
command test -c "$argv"; and eval tty 0>"$argv" >/dev/null
else if test -e /dev/"$argv"
command test -c /dev/"$argv"; and tty 0>/dev/"$argv" >/dev/null
else if test -e /dev/fd/"$argv"
command test -c /dev/fd/"$argv"; and tty 0>/dev/fd/"$argv" >/dev/null
else
return 1
end end
end end
eval "tty 0>&$fd >/dev/null"
end end