From 937388c3059d321797ac327452d71494fcebc655 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 5 Apr 2017 11:34:42 -0700 Subject: [PATCH] tty: handle misconfigured namespaces MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit On some platforms, isatty succeeds but ttyname fails. POSIX does not seem to allow this, but there it is. Problem reported by Christian Brauner (Bug#26371). While we’re at it, check for errors more carefully and return a new exit status 4 if stdin is closed or a similar error occurs. * doc/coreutils.texi (tty invocation): Document new behavior. * init.cfg (stderr_fileno_): Don't assume have_input_tty is not in the environment. * src/tty.c (TTY_STDIN_ERROR): New constant. (main): Exit with nonzero status if there is a usage error, like other coreutils programs. Check for error in getting stdin type. * tests/misc/tty.sh: New file. * tests/local.mk (all_tests): Add it. --- doc/coreutils.texi | 3 ++- init.cfg | 1 + src/tty.c | 33 +++++++++++++++++++++++---------- tests/local.mk | 1 + tests/misc/tty.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 11 deletions(-) create mode 100755 tests/misc/tty.sh diff --git a/doc/coreutils.texi b/doc/coreutils.texi index c22e076157..284e7e36b0 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -15041,9 +15041,10 @@ Exit status: @display 0 if standard input is a terminal -1 if standard input is not a terminal +1 if standard input is a non-terminal file 2 if given incorrect arguments 3 if a write error occurs +4 if standard input is closed or its type cannot be determined @end display diff --git a/init.cfg b/init.cfg index 2f747a3490..af6b581755 100644 --- a/init.cfg +++ b/init.cfg @@ -293,6 +293,7 @@ require_setfacl_() # Require a controlling input 'terminal'. require_controlling_input_terminal_() { + have_input_tty=yes tty -s || have_input_tty=no test -t 0 || have_input_tty=no if test "$have_input_tty" = no; then diff --git a/src/tty.c b/src/tty.c index c3fdabc85e..e908e7ec11 100644 --- a/src/tty.c +++ b/src/tty.c @@ -34,7 +34,8 @@ enum { TTY_FAILURE = 2, - TTY_WRITE_ERROR = 3 + TTY_WRITE_ERROR = 3, + TTY_STDIN_ERROR = 4 }; /* The official name of this program (e.g., no 'g' prefix). */ @@ -77,7 +78,6 @@ Print the file name of the terminal connected to standard input.\n\ int main (int argc, char **argv) { - char *tty; int optc; initialize_main (&argc, &argv); @@ -109,16 +109,29 @@ main (int argc, char **argv) } if (optind < argc) - error (0, 0, _("extra operand %s"), quote (argv[optind])); + { + error (0, 0, _("extra operand %s"), quote (argv[optind])); + usage (TTY_FAILURE); + } + + errno = ENOENT; + + if (silent) + return (isatty (STDIN_FILENO) ? EXIT_SUCCESS + : errno == ENOTTY ? EXIT_FAILURE + : TTY_STDIN_ERROR); + + int status = EXIT_SUCCESS; + char const *tty = ttyname (STDIN_FILENO); - tty = ttyname (STDIN_FILENO); - if (!silent) + if (! tty) { - if (tty) - puts (tty); - else - puts (_("not a tty")); + if (errno != ENOTTY) + error (TTY_STDIN_ERROR, errno, _("standard input")); + tty = _("not a tty"); + status = EXIT_FAILURE; } - return isatty (STDIN_FILENO) ? EXIT_SUCCESS : EXIT_FAILURE; + puts (tty); + return status; } diff --git a/tests/local.mk b/tests/local.mk index 9f1a853a85..3fe9ba8476 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -415,6 +415,7 @@ all_tests = \ tests/misc/truncate-parameters.sh \ tests/misc/truncate-relative.sh \ tests/misc/tsort.pl \ + tests/misc/tty.sh \ tests/misc/unexpand.pl \ tests/misc/uniq.pl \ tests/misc/uniq-perf.sh \ diff --git a/tests/misc/tty.sh b/tests/misc/tty.sh new file mode 100755 index 0000000000..5931350ef3 --- /dev/null +++ b/tests/misc/tty.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# Test 'tty'. + +# Copyright 2017 Free Software Foundation, Inc. + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Make sure there's a tty on stdin. +. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src +print_ver_ tty + +if test -t 0; then + tty || fail=1 + tty -s || fail=1 +fi + +returns_ 1 tty /dev/full || fail=1 + returns_ 3 tty /dev/full || fail=1 +fi + +returns_ 4 tty <&- 2>/dev/null || fail=1 +returns_ 4 tty -s <&- || fail=1 + +Exit $fail -- 2.47.2