Subject: bug#70801: Weird behaviour when standard input is closed

From: Bernard Burette <[email-masked]>
Date: Mon, 06 May 2024 09:38:53 +0200

Hi,

If I try:

$ cat <&-

cat: -: Bad file descriptor

cat: closing standard input: Bad file descriptor

$

The error on stdin beign closed is displayed twice plus "-" is for a FILE argument to replace standard input, It would make more sense to me to have someting like:

$ cat <&-

cat: standard input: Bad file descriptor

$

This is the "git diff" of my proposed change:

diff --git a/src/cat.c b/src/cat.c

index b33faeb35..4be189d85 100644

--- a/src/cat.c

+++ b/src/cat.c

@@ -50,6 +50,14 @@

/* Name of input file.  May be "-".  */

static char const *infile;

+/* Pretty name of input file */

+static char const *

+quotef_infile (void)

+{

+  if (STREQ (infile, "-")) return _("standard input");

+  return quotef (infile);

+}

+

/* Descriptor on which input file is open.  */

static int input_desc;

@@ -164,7 +172,7 @@ simple_cat (char *buf, idx_t bufsize)

       size_t n_read = safe_read (input_desc, buf, bufsize);

       if (n_read == SAFE_READ_ERROR)

         {

-          error (0, errno, "%s", quotef (infile));

+          error (0, errno, "%s", quotef_infile());

           return false;

         }

@@ -313,7 +321,7 @@ cat (char *inbuf, idx_t insize, char *outbuf, idx_t outsize,

               size_t n_read = safe_read (input_desc, inbuf, insize);

               if (n_read == SAFE_READ_ERROR)

                 {

-                  error (0, errno, "%s", quotef (infile));

+                  error (0, errno, "%s", quotef_infile());

                   write_pending (outbuf, &bpout);

                   newlines2 = newlines;

                   return false;

@@ -526,7 +534,7 @@ copy_cat (void)

             || errno == EBADF || errno == EXDEV || errno == ETXTBSY

             || errno == EPERM)

           return 0;

-        error (0, errno, "%s", quotef (infile));

+        error (0, errno, "%s", quotef_infile());

         return -1;

       }

}

@@ -684,7 +692,7 @@ main (int argc, char **argv)

           input_desc = open (infile, file_open_mode);

           if (input_desc < 0)

             {

-              error (0, errno, "%s", quotef (infile));

+              error (0, errno, "%s", quotef_infile());

               ok = false;

               continue;

             }

@@ -692,7 +700,7 @@ main (int argc, char **argv)

       if (fstat (input_desc, &stat_buf) < 0)

         {

-          error (0, errno, "%s", quotef (infile));

+          error (0, errno, "%s", quotef_infile());

           ok = false;

           goto contin;

         }

@@ -719,7 +727,7 @@ main (int argc, char **argv)

             }

           if (exhausting)

             {

-              error (0, 0, _("%s: input file is output file"), quotef (infile));

+              error (0, 0, _("%s: input file is output file"), quotef_infile());

               ok = false;

               goto contin;

             }

@@ -794,7 +802,7 @@ main (int argc, char **argv)

     contin:

       if (!reading_stdin && close (input_desc) < 0)

         {

-          error (0, errno, "%s", quotef (infile));

+          error (0, errno, "%s", quotef_infile());

           ok = false;

         }

     }

@@ -807,7 +815,8 @@ main (int argc, char **argv)

     }

   if (have_read_stdin && close (STDIN_FILENO) < 0)

-    error (EXIT_FAILURE, errno, _("closing standard input"));

+    if (ok)

+      error (EXIT_FAILURE, errno, _("closing standard input"));

   return ok ? EXIT_SUCCESS : EXIT_FAILURE;

}

There are a lot more of coreutil utilities that (could) behave weird on a closed standard input, here is my first list:

b2sum base32 base64 cat cksum comm csplit cut expand factor fmt fold head join md5sum nl nohup numfmt od paste pr ptx sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf sort split stdbuf stty sum tac tail tee tr tsort unexpand uniq wc

I would like to work on those as well but it would help to have:

1) some kind of consensus on "this is a better way of displaying the error", for example other tools also go wild like:

     grep: (standard input): Bad file descriptor

     - why parentheses?

     sed: read error on stdin: Bad file descriptor

     - stdin is the C name for standard input, documented?

2) a better way of offering changes than sending a diff patch in a e-mail.

Thanks,

Regards,