bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: more gcc warnings


From: Paul Eggert
Subject: Re: more gcc warnings
Date: Mon, 11 Jul 2005 11:39:31 -0700
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

address@hidden (Eric Blake) writes:

> cygwin's headers are poorly documented; I often resort to grepping
> /usr/include.  setmode() is in <io.h>, along with get_osfhandle and
> a redundant declaration of access().

I've been putting off cleaning up this mess, but I found the time this
weekend to give it a start.  I installed the following patch.  It
avoids the use of setmode and <io.h> entirely, and it cleans up some
of the inconsistencies in the code (in some cases, they were bugs that
even infected the GNU/Linux version -- ouch!).

Since I don't use DOS, someone with some expertise in that area will
have to double-check it.

I dislike all that isatty stuff -- is there some way that we could
easily remove it from the mainline sources, and put it in config.h or
somewhere we we don't have to see it?  For example, can we replace this:

  if (O_BINARY && ! isatty (STDIN_FILENO))
    freopen (NULL, "rb", stdin);

with this:

  if (O_BINARY)
    freopen (NULL, "rb", stdin);

and have a wrapper on MS-DOS that defines freopen to not do anything
if the first argument is NULL, the second ends in "b", and the third a
standard tty?


2005-07-11  Paul Eggert  <address@hidden>

        * NEWS: Binary input and output are now implemented more consistently.
        These changes affect only platforms like MS-DOS that distinguish
        between binary and text files.
        * doc/coreutils.texi (cat invocation): Remove -B or --binary option
        (available on MS-DOS-like platforms only).  Explain when text and
        binary mode are used now.
        (md5sum invocation): -b actually does have an effect on Unix: it
        causes "*" to be output.  Explain when text and binary mode are
        used now.
        * src/cat.c (usage, main, long_options) [O_BINARY]:
        Remove support for -B.  Use same rules as other programs to decide
        whether to use binary I/O, except that the -bensAE options always
        select text mode.
        * src/cat.c (main): Avoid setmode; use POSIX-specified routines instead.
        * src/cksum.c (cksum): Likewise.
        * src/head.c (head_lines, head_file): Likewise.
        * src/od.c (open_next_file): Likewise.
        * src/split.c (main): Likewise.
        * src/sum.c (bsd_sum_file, sysv_sym_file): Likewise.
        * src/tac.c (copy_to_temp, tac_file, main): Likewise.
        * src/tail.c (tail_bytes, tail_lines, tail_file, main): Likewise.
        * src/tee.c (tee): Likewise.
        * src/tr.c (main): Likewise.
        * src/wc.c (wc): Likewise.
        * src/copy.c (copy_reg): Always copy in binary mode.
        * src/expand.c (expand): Always copy in text mode.  POSIX says
        the input and output must be text.
        * src/unexpand.c (unexpand): Likewise.
        * src/head.c (elide_tail_bytes_file, elide_tail_lines_file, head_bytes):
        (head_lines, head_file): Always use binary mode except for std tty.
        * src/md5sum.c (usage): Clarify whether text or binary is the default.
        (split_3, main): BINARY is now a 3-way value.  All uses changed.
        (digest_file): Likewise.  Clear *BINARY if we determine the file
        to be text.  All uses changed.
        (main): Don't report a file to be binary if we actually read it
        as text in MS-DOS, because it was a terminal.
        * src/shred.c (wipefile): Always use binary mode.  Clearly this
        never worked right on DOS!
        * src/system.h (setmode, fileno): Remove; no longer needed, we think.
        (SET_MODE, SET_BINARY, SET_BINARY2): Remove.
        [defined __DJGPP__]: Don't include <io.h> or <sys/exceptn.h>.
        * src/wc.c (wc_file): FILE might be null now.
        (main): Simplify code a bit, so that fewer places need the
        setmode fixes.

Index: NEWS
===================================================================
RCS file: /fetish/cu/NEWS,v
retrieving revision 1.300
diff -p -u -r1.300 NEWS
--- NEWS        3 Jul 2005 16:52:09 -0000       1.300
+++ NEWS        11 Jul 2005 18:08:34 -0000
@@ -48,6 +48,31 @@ GNU coreutils NEWS                      
   "Utility Syntax Guidelines" in the Minutes of the January 2005
   Meeting <http://www.opengroup.org/austin/docs/austin_239.html>.
 
+** Binary input and output are now implemented more consistently.
+  These changes affect only platforms like MS-DOS that distinguish
+  between binary and text files.
+
+  The following programs now always use text input/output:
+
+    expand unexpand
+
+  The following programs now always use binary input/output to copy data:
+
+    cp install mv shred
+
+  The following programs now always use binary input/output to copy
+  data, except for stdin and stdout when it is a terminal.
+
+    head tac tail tee tr
+    (cat behaves similarly, unless one of the options -bensAE is used.)
+
+  cat's --binary or -B option has been removed.  It existed only on
+  MS-DOS-like platforms, and didn't work as documented there.
+
+  md5sum and sha1sum now obey the -b or --binary option, even if
+  standard input is a terminal, and they no longer report files to be
+  binary if they actually read them in text mode.
+
 ** Changes for better conformance to POSIX
 
   cp, ln, mv, rm changes:
Index: doc/coreutils.texi
===================================================================
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.270
diff -p -u -r1.270 coreutils.texi
--- doc/coreutils.texi  3 Jul 2005 16:48:19 -0000       1.270
+++ doc/coreutils.texi  11 Jul 2005 18:08:43 -0000
@@ -1209,32 +1209,11 @@ The program accepts the following option
 @opindex --show-all
 Equivalent to @option{-vET}.
 
address@hidden -B
address@hidden --binary
address@hidden -B
address@hidden --binary
address@hidden binary and text I/O in cat
-On MS-DOS and MS-Windows only, read and write the files in binary mode.
-By default, @command{cat} on MS-DOS/MS-Windows uses binary mode only when
-standard output is redirected to a file or a pipe; this option overrides
-that.  Binary file I/O is used so that the files retain their format
-(Unix text as opposed to DOS text and binary), because @command{cat} is
-frequently used as a file-copying program.  Some options (see below)
-cause @command{cat} to read and write files in text mode because in those
-cases the original file contents aren't important (e.g., when lines are
-numbered by @command{cat}, or when line endings should be marked).  This is
-so these options work as DOS/Windows users would expect; for example,
-DOS-style text files have their lines end with the CR-LF pair of
-characters, which won't be processed as an empty line by @option{-b} unless
-the file is read in text mode.
-
 @item -b
 @itemx --number-nonblank
 @opindex -b
 @opindex --number-nonblank
-Number all nonblank output lines, starting with 1.  On MS-DOS and
-MS-Windows, this option causes @command{cat} to read and write files in
-text mode.
+Number all nonblank output lines, starting with 1.
 
 @item -e
 @opindex -e
@@ -1244,25 +1223,20 @@ Equivalent to @option{-vE}.
 @itemx --show-ends
 @opindex -E
 @opindex --show-ends
-Display a @samp{$} after the end of each line.  On MS-DOS and
-MS-Windows, this option causes @command{cat} to read and write files in
-text mode.
+Display a @samp{$} after the end of each line.
 
 @item -n
 @itemx --number
 @opindex -n
 @opindex --number
-Number all output lines, starting with 1.  On MS-DOS and MS-Windows,
-this option causes @command{cat} to read and write files in text mode.
+Number all output lines, starting with 1.
 
 @item -s
 @itemx --squeeze-blank
 @opindex -s
 @opindex --squeeze-blank
 @cindex squeezing blank lines
-Replace multiple adjacent blank lines with a single blank line.  On
-MS-DOS and MS-Windows, this option causes @command{cat} to read and write
-files in text mode.
+Replace multiple adjacent blank lines with a single blank line.
 
 @item -t
 @opindex -t
@@ -1276,7 +1250,7 @@ Display TAB characters as @samp{^I}.
 
 @item -u
 @opindex -u
-Ignored; for Unix compatibility.
+Ignored; for @acronym{POSIX} compatibility.
 
 @item -v
 @itemx --show-nonprinting
@@ -1284,12 +1258,18 @@ Ignored; for Unix compatibility.
 @opindex --show-nonprinting
 Display control characters except for LFD and TAB using
 @samp{^} notation and precede characters that have the high bit set with
address@hidden  On MS-DOS and MS-Windows, this option causes @command{cat} to
-read files and standard input in DOS binary mode, so the CR
-characters at the end of each line are also visible.
address@hidden
 
 @end table
 
+On systems like MS-DOS that distinguish between text and binary files,
address@hidden normally reads and writes in binary mode.  However,
address@hidden reads in text mode if one of the options
address@hidden is used or if @command{cat} is reading from standard
+input and standard input is a terminal.  Similarly, @command{cat}
+writes in text mode if one of the options @option{-bensAE} is used or
+if standard output is a terminal.
+
 @exitstatus
 
 Examples:
@@ -3023,11 +3003,13 @@ The program accepts the following option
 @opindex -b
 @opindex --binary
 @cindex binary input files
-Treat all input files as binary.  This option has no effect on Unix
-systems, since they don't distinguish between binary and text files.
-This option is useful on systems that have different internal and
-external character representations.  On MS-DOS and MS-Windows, this is
-the default.
+Treat each input file as binary, by reading it in binary mode and
+outputting a @samp{*} flag.  This is the inverse of @option{--text}.
+On systems like @acronym{GNU} that do not distinguish between binary
+and text files, this option merely flags each input file as binary:
+the MD5 checksum is unaffected.  This option is the default on systems
+like MS-DOS that distinguish between binary and text files, except
+for reading standard input when standard input is a terminal.
 
 @item -c
 @itemx --check
@@ -3070,8 +3052,12 @@ indicating there was a failure.
 @opindex -t
 @opindex --text
 @cindex text input files
-Treat all input files as text files.  This is the reverse of
address@hidden
+Treat each input file as text, by reading it in text mode and
+outputting a @samp{ } flag.  This is the inverse of @option{--binary}.
+This option is the default on systems like @acronym{GNU} that do not
+distinguish between binary and text files.  On other systems, it is
+the default for reading standard input when standard input is a
+terminal.
 
 @item -w
 @itemx --warn
Index: src/cat.c
===================================================================
RCS file: /fetish/cu/src/cat.c,v
retrieving revision 1.104
diff -p -u -r1.104 cat.c
--- src/cat.c   9 Jul 2005 07:37:58 -0000       1.104
+++ src/cat.c   11 Jul 2005 18:08:43 -0000
@@ -118,12 +118,6 @@ Concatenate FILE(s), or standard input, 
 \n\
 With no FILE, or when FILE is -, read standard input.\n\
 "), stdout);
-#if O_BINARY
-      fputs (_("\
-\n\
-  -B, --binary             use binary writes to the console device.\n\n\
-"), stdout);
-#endif
       printf (_("\
 \n\
 Examples:\n\
@@ -538,10 +532,6 @@ main (int argc, char **argv)
   bool show_ends = false;
   bool show_nonprinting = false;
   bool show_tabs = false;
-#if O_BINARY
-  bool binary = false;
-  bool binary_output = false;
-#endif
   int file_open_mode = O_RDONLY;
 
   static struct option const long_options[] =
@@ -553,9 +543,6 @@ main (int argc, char **argv)
     {"show-ends", no_argument, NULL, 'E'},
     {"show-tabs", no_argument, NULL, 'T'},
     {"show-all", no_argument, NULL, 'A'},
-#if O_BINARY
-    {"binary", no_argument, NULL, 'B'},
-#endif
     {GETOPT_HELP_OPTION_DECL},
     {GETOPT_VERSION_OPTION_DECL},
     {NULL, 0, NULL, 0}
@@ -573,13 +560,8 @@ main (int argc, char **argv)
 
   /* Parse command line options.  */
 
-  while ((c = getopt_long (argc, argv,
-#if O_BINARY
-                          "benstuvABET"
-#else
-                          "benstuvAET"
-#endif
-                          , long_options, NULL)) != -1)
+  while ((c = getopt_long (argc, argv, "benstuvAET", long_options, NULL))
+        != -1)
     {
       switch (c)
        {
@@ -620,12 +602,6 @@ main (int argc, char **argv)
          show_tabs = true;
          break;
 
-#if O_BINARY
-       case 'B':
-         binary = true;
-         break;
-#endif
-
        case 'E':
          show_ends = true;
          break;
@@ -669,41 +645,12 @@ main (int argc, char **argv)
 #endif
     }
 
-#if O_BINARY
-  /* We always read and write in BINARY mode, since this is the
-     best way to copy the files verbatim.  Exceptions are when
-     they request line numbering, squeezing of empty lines or
-     marking lines' ends: then we use text I/O, because otherwise
-     -b, -s and -E would surprise users on DOS/Windows where a line
-     with only CR-LF is an empty line.  (Besides, if they ask for
-     one of these options, they don't care much about the original
-     file contents anyway).  */
-  if (binary
-      || ! ((number | squeeze_blank | show_ends)
-           || isatty (STDOUT_FILENO)))
+  if (! (number | show_ends | squeeze_blank))
     {
-      /* Switch stdout to BINARY mode.  */
-      binary_output = true;
-      SET_BINARY (STDOUT_FILENO);
-      /* When stdout is in binary mode, make sure all input files are
-        also read in binary mode.  */
       file_open_mode |= O_BINARY;
+      if (O_BINARY && ! isatty (STDOUT_FILENO))
+       freopen (NULL, "wb", stdout);
     }
-  else if (show_nonprinting)
-    {
-      /* If they want to see the non-printables, let's show them
-        those CR characters as well, so make the input binary.
-        But keep console output in text mode, so that LF causes
-        both CR and LF on output, and the output is readable.  */
-      file_open_mode |= O_BINARY;
-      SET_BINARY (0);
-
-      /* Setting stdin to binary switches the console device to
-        raw I/O, which also affects stdout to console.  Undo that.  */
-      if (isatty (STDOUT_FILENO))
-       setmode (STDOUT_FILENO, O_TEXT);
-    }
-#endif
 
   /* Check if any of the input files are the same as the output file.  */
 
@@ -717,37 +664,12 @@ main (int argc, char **argv)
       if (argind < argc)
        infile = argv[argind];
 
-      if (infile[0] == '-' && infile[1] == 0)
+      if (STREQ (infile, "-"))
        {
          have_read_stdin = true;
-         input_desc = 0;
-
-#if O_BINARY
-         /* Switch stdin to BINARY mode if needed.  */
-         if (binary_output)
-           {
-             bool tty_in = isatty (input_desc);
-
-             /* If stdin is a terminal device, and it is the ONLY
-                input file (i.e. we didn't write anything to the
-                output yet), switch the output back to TEXT mode.
-                This is so "cat > xyzzy" creates a DOS-style text
-                file, like people expect.  */
-             if (tty_in && optind <= argc)
-               setmode (STDOUT_FILENO, O_TEXT);
-             else
-               {
-                 SET_BINARY (input_desc);
-# ifdef __DJGPP__
-                 /* This is DJGPP-specific.  By default, switching console
-                    to binary mode disables SIGINT.  But we want terminal
-                    reads to be interruptible.  */
-                 if (tty_in)
-                   __djgpp_set_ctrl_c (1);
-# endif
-               }
-           }
-#endif
+         input_desc = STDIN_FILENO;
+         if ((file_open_mode & O_BINARY) && ! isatty (STDIN_FILENO))
+           freopen (NULL, "rb", stdin);
        }
       else
        {
Index: src/cksum.c
===================================================================
RCS file: /fetish/cu/src/cksum.c,v
retrieving revision 1.76
diff -p -u -r1.76 cksum.c
--- src/cksum.c 14 May 2005 07:58:36 -0000      1.76
+++ src/cksum.c 11 Jul 2005 18:08:43 -0000
@@ -199,10 +199,12 @@ cksum (const char *file, bool print_name
     {
       fp = stdin;
       have_read_stdin = true;
+      if (O_BINARY && ! isatty (STDIN_FILENO))
+       freopen (NULL, "rb", stdin);
     }
   else
     {
-      fp = fopen (file, "r");
+      fp = fopen (file, (O_BINARY ? "rb" : "r"));
       if (fp == NULL)
        {
          error (0, errno, "%s", file);
@@ -210,9 +212,6 @@ cksum (const char *file, bool print_name
        }
     }
 
-  /* Read input in BINARY mode, unless it is a console device.  */
-  SET_BINARY (fileno (fp));
-
   while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0)
     {
       unsigned char *cp = buf;
Index: src/copy.c
===================================================================
RCS file: /fetish/cu/src/copy.c,v
retrieving revision 1.186
diff -p -u -r1.186 copy.c
--- src/copy.c  3 Jul 2005 07:16:43 -0000       1.186
+++ src/copy.c  11 Jul 2005 18:08:43 -0000
@@ -212,7 +212,7 @@ copy_reg (char const *src_name, char con
   bool last_write_made_hole = false;
   bool make_holes = false;
 
-  source_desc = open (src_name, O_RDONLY);
+  source_desc = open (src_name, O_RDONLY | O_BINARY);
   if (source_desc < 0)
     {
       error (0, errno, _("cannot open %s for reading"), quote (src_name));
@@ -241,11 +241,11 @@ copy_reg (char const *src_name, char con
      The if-block will be taken in move_mode.  */
   if (*new_dst)
     {
-      dest_desc = open (dst_name, O_WRONLY | O_CREAT, dst_mode);
+      dest_desc = open (dst_name, O_WRONLY | O_CREAT | O_BINARY, dst_mode);
     }
   else
     {
-      dest_desc = open (dst_name, O_WRONLY | O_TRUNC, dst_mode);
+      dest_desc = open (dst_name, O_WRONLY | O_TRUNC | O_BINARY, dst_mode);
 
       if (dest_desc < 0 && x->unlink_dest_after_failed_open)
        {
@@ -260,7 +260,7 @@ copy_reg (char const *src_name, char con
          *new_dst = true;
 
          /* Try the open again, but this time with different flags.  */
-         dest_desc = open (dst_name, O_WRONLY | O_CREAT, dst_mode);
+         dest_desc = open (dst_name, O_WRONLY | O_CREAT | O_BINARY, dst_mode);
        }
     }
 
@@ -270,7 +270,6 @@ copy_reg (char const *src_name, char con
       return_val = false;
       goto close_src_desc;
     }
-  SET_BINARY2 (source_desc, dest_desc);
 
   /* Determine the optimal buffer size.  */
 
Index: src/expand.c
===================================================================
RCS file: /fetish/cu/src/expand.c,v
retrieving revision 1.86
diff -p -u -r1.86 expand.c
--- src/expand.c        5 Jul 2005 06:32:54 -0000       1.86
+++ src/expand.c        11 Jul 2005 18:08:43 -0000
@@ -276,9 +276,6 @@ expand (void)
   if (!fp)
     return;
 
-  /* Binary I/O will preserve the original EOL style (DOS/Unix) of files.  */
-  SET_BINARY2 (fileno (fp), STDOUT_FILENO);
-
   for (;;)
     {
       /* Input character, or EOF.  */
@@ -303,7 +300,7 @@ expand (void)
       do
        {
          while ((c = getc (fp)) < 0 && (fp = next_file (fp)))
-           SET_BINARY2 (fileno (fp), STDOUT_FILENO);
+           continue;
 
          if (convert)
            {
Index: src/head.c
===================================================================
RCS file: /fetish/cu/src/head.c,v
retrieving revision 1.102
diff -p -u -r1.102 head.c
--- src/head.c  14 May 2005 07:58:37 -0000      1.102
+++ src/head.c  11 Jul 2005 18:08:44 -0000
@@ -411,10 +411,6 @@ elide_tail_bytes_file (const char *filen
 {
   struct stat stats;
 
-  /* We need binary input, since `head' relies on `lseek' and byte counts,
-     while binary output will preserve the style (Unix/DOS) of text file.  */
-  SET_BINARY2 (fd, STDOUT_FILENO);
-
   if (presume_input_pipe || fstat (fd, &stats) || ! S_ISREG (stats.st_mode))
     {
       return elide_tail_bytes_pipe (filename, fd, n_elide);
@@ -713,10 +709,6 @@ elide_tail_lines_seekable (const char *p
 static bool
 elide_tail_lines_file (const char *filename, int fd, uintmax_t n_elide)
 {
-  /* We need binary input, since `head' relies on `lseek' and byte counts,
-     while binary output will preserve the style (Unix/DOS) of text file.  */
-  SET_BINARY2 (fd, STDOUT_FILENO);
-
   if (!presume_input_pipe)
     {
       /* Find the offset, OFF, of the Nth newline from the end,
@@ -749,9 +741,6 @@ head_bytes (const char *filename, int fd
   char buffer[BUFSIZ];
   size_t bytes_to_read = BUFSIZ;
 
-  /* Need BINARY I/O for the byte counts to be accurate.  */
-  SET_BINARY2 (fd, fileno (stdout));
-
   while (bytes_to_write)
     {
       size_t bytes_read;
@@ -777,10 +766,6 @@ head_lines (const char *filename, int fd
 {
   char buffer[BUFSIZ];
 
-  /* Need BINARY I/O for the byte counts to be accurate.  */
-  /* FIXME: do we really need this when counting *lines*?  */
-  SET_BINARY2 (fd, fileno (stdout));
-
   while (lines_to_write)
     {
       size_t bytes_read = safe_read (fd, buffer, BUFSIZ);
@@ -853,10 +838,12 @@ head_file (const char *filename, uintmax
       have_read_stdin = true;
       fd = STDIN_FILENO;
       filename = _("standard input");
+      if (O_BINARY && ! isatty (STDIN_FILENO))
+       freopen (NULL, "rb", stdin);
     }
   else
     {
-      fd = open (filename, O_RDONLY);
+      fd = open (filename, O_RDONLY | O_BINARY);
       if (fd < 0)
        {
          error (0, errno, _("cannot open %s for reading"), quote (filename));
@@ -1061,6 +1048,9 @@ main (int argc, char **argv)
               ? (char const *const *) &argv[optind]
               : default_file_list);
 
+  if (O_BINARY && ! isatty (STDOUT_FILENO))
+    freopen (NULL, "wb", stdout);
+
   for (i = 0; file_list[i]; ++i)
     ok &= head_file (file_list[i], n_units, count_lines, elide_from_end);
 
Index: src/md5sum.c
===================================================================
RCS file: /fetish/cu/src/md5sum.c,v
retrieving revision 1.137
diff -p -u -r1.137 md5sum.c
--- src/md5sum.c        9 Jul 2005 22:10:39 -0000       1.137
+++ src/md5sum.c        11 Jul 2005 18:08:44 -0000
@@ -110,19 +110,32 @@ Usage: %s [OPTION] [FILE]...\n\
   or:  %s [OPTION] --check [FILE]\n\
 Print or check %s (%d-bit) checksums.\n\
 With no FILE, or when FILE is -, read standard input.\n\
+\n\
 "),
              program_name, program_name,
              DIGEST_TYPE_STRING (algorithm),
              DIGEST_BITS (algorithm));
+      if (O_BINARY)
+       fputs (_("\
+  -b, --binary            read in binary mode (default unless reading tty 
stdin)\n\
+"), stdout);
+      else
+       fputs (_("\
+  -b, --binary            read in binary mode\n\
+"), stdout);
       printf (_("\
-\n\
-  -b, --binary            read files in binary mode (default on DOS/Windows)\n\
-  -c, --check             check %s sums against given list\n\
-  -t, --text              read files in text mode (default)\n\
-\n\
-"),
+  -c, --check             check %s sums against given list\n"),
              DIGEST_TYPE_STRING (algorithm));
+      if (O_BINARY)
+       fputs (_("\
+  -t, --text              read in text mode (default if reading tty stdin)\n\
+"), stdout);
+      else
+       fputs (_("\
+  -t, --text              read in text mode (default)\n\
+"), stdout);
       fputs (_("\
+\n\
 The following two options are useful only when verifying checksums:\n\
       --status            don't output anything, status code shows success\n\
   -w, --warn              warn about improperly formated checksum lines\n\
@@ -188,7 +201,7 @@ bsd_split_3 (char *s, size_t s_len, unsi
 
 static bool
 split_3 (char *s, size_t s_len,
-        unsigned char **hex_digest, bool *binary, char **file_name)
+        unsigned char **hex_digest, int *binary, char **file_name)
 {
   size_t i;
   bool escaped_filename = false;
@@ -204,7 +217,7 @@ split_3 (char *s, size_t s_len,
     {
       if (strncmp (s + i + algo_name_len, " (", 2) == 0)
        {
-         *binary = false;
+         *binary = 0;
          return bsd_split_3 (s +      i + algo_name_len + 2,
                              s_len - (i + algo_name_len + 2),
                              hex_digest, file_name);
@@ -303,11 +316,18 @@ hex_digits (unsigned char const *s)
 
 /* An interface to the function, DIGEST_STREAM,
    (either md5_stream or sha1_stream).
-   Operate on FILENAME (it may be "-") and put the result in *BIN_RESULT.
+   Operate on FILENAME (it may be "-").
+
+   *BINARY indicates whether the file is binary.  BINARY < 0 means it
+   depends on whether binary mode makes any difference and the file is
+   a terminal; in that case, clear *BINARY if the file was treated as
+   text because it was a terminal.
+
+   Put the checksum in *BIN_RESULT.
    Return true if successful.  */
 
 static bool
-digest_file (const char *filename, bool binary, unsigned char *bin_result,
+digest_file (const char *filename, int *binary, unsigned char *bin_result,
             int (*digest_stream) (FILE *, void *))
 {
   FILE *fp;
@@ -318,20 +338,17 @@ digest_file (const char *filename, bool 
     {
       have_read_stdin = true;
       fp = stdin;
-#if O_BINARY
-      /* If we need binary reads from a pipe or redirected stdin, we need
-        to switch it to BINARY mode here, since stdin is already open.  */
-      if (binary)
-       SET_BINARY (fileno (stdin));
-#endif
+      if (O_BINARY && *binary)
+       {
+         if (*binary < 0)
+           *binary = ! isatty (STDIN_FILENO);
+         if (*binary)
+           freopen (NULL, "rb", stdin);
+       }
     }
   else
     {
-      /* OPENOPTS is a macro.  It varies with the system.
-        Some systems distinguish between internal and
-        external text representations.  */
-
-      fp = fopen (filename, (O_BINARY && binary ? "rb" : "r"));
+      fp = fopen (filename, (O_BINARY && *binary ? "rb" : "r"));
       if (fp == NULL)
        {
          error (0, errno, "%s", filename);
@@ -386,14 +403,13 @@ digest_check (const char *checkfile_name
        }
     }
 
-  SET_MODE (fileno (checkfile_stream), O_TEXT);
   line_number = 0;
   line = NULL;
   line_chars_allocated = 0;
   do
     {
       char *filename;
-      bool binary;
+      int binary;
       unsigned char *hex_digest IF_LINT (= NULL);
       ssize_t line_length;
 
@@ -437,7 +453,7 @@ digest_check (const char *checkfile_name
 
          ++n_properly_formatted_lines;
 
-         ok = digest_file (filename, binary, bin_buffer, digest_stream);
+         ok = digest_file (filename, &binary, bin_buffer, digest_stream);
 
          if (!ok)
            {
@@ -536,16 +552,7 @@ main (int argc, char **argv)
   bool do_check = false;
   int opt;
   bool ok = true;
-  bool file_type_specified = false;
-
-#if O_BINARY
-  /* Binary is default on MSDOS, so the actual file contents
-     are used in computation.  */
-  bool binary = true;
-#else
-  /* Text is default of the Plumb/Lankester format.  */
-  bool binary = false;
-#endif
+  int binary = -1;
 
   /* Setting values of global variables.  */
   initialize_main (&argc, &argv);
@@ -560,8 +567,7 @@ main (int argc, char **argv)
     switch (opt)
       {
       case 'b':
-       file_type_specified = true;
-       binary = true;
+       binary = 1;
        break;
       case 'c':
        do_check = true;
@@ -571,8 +577,7 @@ main (int argc, char **argv)
        warn = false;
        break;
       case 't':
-       file_type_specified = true;
-       binary = false;
+       binary = 0;
        break;
       case 'w':
        status_only = false;
@@ -587,7 +592,7 @@ main (int argc, char **argv)
   min_digest_line_length = MIN_DIGEST_LINE_LENGTH (algorithm);
   digest_hex_bytes = DIGEST_HEX_BYTES (algorithm);
 
-  if (file_type_specified & do_check)
+  if (0 <= binary && do_check)
     {
       error (0, 0, _("the --binary and --text options are meaningless when "
                     "verifying checksums"));
@@ -629,8 +634,9 @@ main (int argc, char **argv)
       for (; optind < argc; ++optind)
        {
          char *file = argv[optind];
+         int file_is_binary = binary;
 
-         if (! digest_file (file, binary, bin_buffer,
+         if (! digest_file (file, &file_is_binary, bin_buffer,
                             DIGEST_STREAM (algorithm)))
            ok = false;
          else
@@ -646,7 +652,7 @@ main (int argc, char **argv)
                printf ("%02x", bin_buffer[i]);
 
              putchar (' ');
-             if (binary)
+             if (file_is_binary)
                putchar ('*');
              else
                putchar (' ');
Index: src/od.c
===================================================================
RCS file: /fetish/cu/src/od.c,v
retrieving revision 1.163
diff -p -u -r1.163 od.c
--- src/od.c    5 Jul 2005 05:17:10 -0000       1.163
+++ src/od.c    11 Jul 2005 18:08:44 -0000
@@ -899,10 +899,12 @@ open_next_file (void)
          input_filename = _("standard input");
          in_stream = stdin;
          have_read_stdin = true;
+         if (O_BINARY && ! isatty (STDIN_FILENO))
+           freopen (NULL, "rb", stdin);
        }
       else
        {
-         in_stream = fopen (input_filename, "r");
+         in_stream = fopen (input_filename, (O_BINARY ? "rb" : "r"));
          if (in_stream == NULL)
            {
              error (0, errno, "%s", input_filename);
@@ -914,7 +916,6 @@ open_next_file (void)
 
   if (limit_bytes_to_format & !flag_dump_strings)
     SETVBUF (in_stream, NULL, _IONBF, 0);
-  SET_BINARY (fileno (in_stream));
 
   return ok;
 }
Index: src/shred.c
===================================================================
RCS file: /fetish/cu/src/shred.c,v
retrieving revision 1.115
diff -p -u -r1.115 shred.c
--- src/shred.c 3 Jul 2005 07:19:29 -0000       1.115
+++ src/shred.c 11 Jul 2005 18:08:44 -0000
@@ -1442,11 +1442,11 @@ wipefile (char *name, char const *qname,
   bool ok;
   int fd;
 
-  fd = open (name, O_WRONLY | O_NOCTTY);
+  fd = open (name, O_WRONLY | O_NOCTTY | O_BINARY);
   if (fd < 0
       && (errno == EACCES && flags->force)
       && chmod (name, S_IWUSR) == 0)
-    fd = open (name, O_WRONLY | O_NOCTTY);
+    fd = open (name, O_WRONLY | O_NOCTTY | O_BINARY);
   if (fd < 0)
     {
       error (0, errno, _("%s: failed to open for writing"), qname);
Index: src/split.c
===================================================================
RCS file: /fetish/cu/src/split.c,v
retrieving revision 1.111
diff -p -u -r1.111 split.c
--- src/split.c 5 Jul 2005 06:32:54 -0000       1.111
+++ src/split.c 11 Jul 2005 18:08:44 -0000
@@ -541,7 +541,8 @@ main (int argc, char **argv)
           quote (infile));
 
   /* Binary I/O is safer when bytecounts are used.  */
-  SET_BINARY (STDIN_FILENO);
+  if (O_BINARY && ! isatty (STDIN_FILENO))
+    freopen (NULL, "rb", stdin);
 
   /* No output file is open now.  */
   output_desc = -1;
Index: src/sum.c
===================================================================
RCS file: /fetish/cu/src/sum.c,v
retrieving revision 1.79
diff -p -u -r1.79 sum.c
--- src/sum.c   14 May 2005 07:58:37 -0000      1.79
+++ src/sum.c   11 Jul 2005 18:08:44 -0000
@@ -97,18 +97,18 @@ bsd_sum_file (const char *file, int prin
     {
       fp = stdin;
       have_read_stdin = true;
+      if (O_BINARY && ! isatty (STDIN_FILENO))
+       freopen (NULL, "rb", stdin);
     }
   else
     {
-      fp = fopen (file, "r");
+      fp = fopen (file, (O_BINARY ? "rb" : "r"));
       if (fp == NULL)
        {
          error (0, errno, "%s", file);
          return false;
        }
     }
-  /* Need binary I/O, or else byte counts and checksums are incorrect.  */
-  SET_BINARY (fileno(fp));
 
   while ((ch = getc (fp)) != EOF)
     {
@@ -165,18 +165,18 @@ sysv_sum_file (const char *file, int pri
     {
       fd = STDIN_FILENO;
       have_read_stdin = true;
+      if (O_BINARY && ! isatty (STDIN_FILENO))
+       freopen (NULL, "rb", stdin);
     }
   else
     {
-      fd = open (file, O_RDONLY);
+      fd = open (file, O_RDONLY | O_BINARY);
       if (fd == -1)
        {
          error (0, errno, "%s", file);
          return false;
        }
     }
-  /* Need binary I/O, or else byte counts and checksums are incorrect.  */
-  SET_BINARY (fd);
 
   while (1)
     {
Index: src/system.h
===================================================================
RCS file: /fetish/cu/src/system.h,v
retrieving revision 1.132
diff -p -u -r1.132 system.h
--- src/system.h        6 Jul 2005 09:34:09 -0000       1.132
+++ src/system.h        11 Jul 2005 18:08:44 -0000
@@ -170,14 +170,6 @@ initialize_exit_failure (int status)
 # define R_OK 4
 #endif
 
-/* For systems that distinguish between text and binary I/O.
-   O_BINARY is usually declared in fcntl.h  */
-#if !defined O_BINARY && defined _O_BINARY
-  /* For MSC-compatible compilers.  */
-# define O_BINARY _O_BINARY
-# define O_TEXT _O_TEXT
-#endif
-
 #if !defined O_DIRECT
 # define O_DIRECT 0
 #endif
@@ -210,37 +202,24 @@ initialize_exit_failure (int status)
 # define O_SYNC 0
 #endif
 
+/* For systems that distinguish between text and binary I/O.
+   O_BINARY is usually declared in fcntl.h  */
+#if !defined O_BINARY && defined _O_BINARY
+  /* For MSC-compatible compilers.  */
+# define O_BINARY _O_BINARY
+# define O_TEXT _O_TEXT
+#endif
+
 #ifdef __BEOS__
   /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect.  */
 # undef O_BINARY
 # undef O_TEXT
 #endif
 
-#if O_BINARY
-# ifndef __DJGPP__
-#  define setmode _setmode
-#  define fileno(_fp) _fileno (_fp)
-# endif /* not DJGPP */
-# define SET_MODE(_f, _m) setmode (_f, _m)
-# define SET_BINARY(_f) do {if (!isatty(_f)) setmode (_f, O_BINARY);} while (0)
-# define SET_BINARY2(_f1, _f2)         \
-  do {                                 \
-    if (!isatty (_f1))                 \
-      {                                        \
-        setmode (_f1, O_BINARY);       \
-       if (!isatty (_f2))              \
-         setmode (_f2, O_BINARY);      \
-      }                                        \
-  } while(0)
-#else
-# define SET_MODE(_f, _m) (void)0
-# define SET_BINARY(f) (void)0
-# define SET_BINARY2(f1,f2) (void)0
-# ifndef O_BINARY
-#  define O_BINARY 0
-# endif
+#ifndef O_BINARY
+# define O_BINARY 0
 # define O_TEXT 0
-#endif /* O_BINARY */
+#endif
 
 #if HAVE_DIRENT_H
 # include <dirent.h>
@@ -344,13 +323,6 @@ initialize_exit_failure (int status)
 
 #include "timespec.h"
 
-#ifdef __DJGPP__
-  /* We need the declaration of setmode.  */
-# include <io.h>
-  /* We need the declaration of __djgpp_set_ctrl_c.  */
-# include <sys/exceptn.h>
-#endif
-
 #if HAVE_INTTYPES_H
 # include <inttypes.h>
 #endif
Index: src/tac.c
===================================================================
RCS file: /fetish/cu/src/tac.c,v
retrieving revision 1.123
diff -p -u -r1.123 tac.c
--- src/tac.c   3 Jul 2005 07:21:31 -0000       1.123
+++ src/tac.c   11 Jul 2005 18:08:44 -0000
@@ -455,7 +455,7 @@ copy_to_temp (FILE **g_tmp, char **g_tem
       return false;
     }
 
-  tmp = fdopen (fd, "w+");
+  tmp = fdopen (fd, (O_BINARY ? "w+b" : "w+"));
   if (! tmp)
     {
       error (0, errno, _("cannot open %s for writing"), quote (tempfile));
@@ -490,7 +490,6 @@ copy_to_temp (FILE **g_tmp, char **g_tem
       goto Fail;
     }
 
-  SET_BINARY (fileno (tmp));
   *g_tmp = tmp;
   *g_tempfile = tempfile;
   return true;
@@ -529,10 +528,12 @@ tac_file (const char *filename)
       have_read_stdin = true;
       fd = STDIN_FILENO;
       filename = _("standard input");
+      if (O_BINARY && ! isatty (STDIN_FILENO))
+       freopen (NULL, "rb", stdin);
     }
   else
     {
-      fd = open (filename, O_RDONLY);
+      fd = open (filename, O_RDONLY | O_BINARY);
       if (fd < 0)
        {
          error (0, errno, _("cannot open %s for reading"), quote (filename));
@@ -540,16 +541,6 @@ tac_file (const char *filename)
        }
     }
 
-  /* We need binary I/O, since `tac' relies
-     on `lseek' and byte counts.
-
-     Binary output will leave the lines' ends (NL or
-     CR/LF) intact when the output is a disk file.
-     Writing a file with CR/LF pairs at end of lines in
-     text mode has no visible effect on console output,
-     since two CRs in a row are just like one CR.  */
-  SET_BINARY2 (fd, STDOUT_FILENO);
-
   file_size = lseek (fd, (off_t) 0, SEEK_END);
 
   ok = (0 <= file_size
@@ -651,6 +642,9 @@ main (int argc, char **argv)
          ? (char const *const *) &argv[optind]
          : default_file_list);
 
+  if (O_BINARY && ! isatty (STDOUT_FILENO))
+    freopen (NULL, "wb", stdout);
+
   {
     size_t i;
     ok = true;
Index: src/tail.c
===================================================================
RCS file: /fetish/cu/src/tail.c,v
retrieving revision 1.239
diff -p -u -r1.239 tail.c
--- src/tail.c  3 Jul 2005 07:21:49 -0000       1.239
+++ src/tail.c  11 Jul 2005 18:08:44 -0000
@@ -1127,10 +1127,6 @@ tail_bytes (const char *pretty_filename,
 {
   struct stat stats;
 
-  /* We need binary input, since `tail' relies on `lseek' and byte counts,
-     while binary output will preserve the style (Unix/DOS) of text file.  */
-  SET_BINARY2 (fd, STDOUT_FILENO);
-
   if (fstat (fd, &stats))
     {
       error (0, errno, _("cannot fstat %s"), quote (pretty_filename));
@@ -1197,10 +1193,6 @@ tail_lines (const char *pretty_filename,
 {
   struct stat stats;
 
-  /* We need binary input, since `tail' relies on `lseek' and byte counts,
-     while binary output will preserve the style (Unix/DOS) of text file.  */
-  SET_BINARY2 (fd, STDOUT_FILENO);
-
   if (fstat (fd, &stats))
     {
       error (0, errno, _("cannot fstat %s"), quote (pretty_filename));
@@ -1283,9 +1275,11 @@ tail_file (struct File_spec *f, uintmax_
     {
       have_read_stdin = true;
       fd = STDIN_FILENO;
+      if (O_BINARY && ! isatty (STDIN_FILENO))
+       freopen (NULL, "rb", stdin);
     }
   else
-    fd = open (f->name, O_RDONLY);
+    fd = open (f->name, O_RDONLY | O_BINARY);
 
   f->tailable = !(reopen_inaccessible_files && fd == -1);
 
@@ -1675,6 +1669,9 @@ main (int argc, char **argv)
       || (header_mode == multiple_files && n_files > 1))
     print_headers = true;
 
+  if (O_BINARY && ! isatty (STDOUT_FILENO))
+    freopen (NULL, "wb", stdout);
+
   for (i = 0; i < n_files; i++)
     ok &= tail_file (&F[i], n_units);
 
Index: src/tee.c
===================================================================
RCS file: /fetish/cu/src/tee.c,v
retrieving revision 1.82
diff -p -u -r1.82 tee.c
--- src/tee.c   9 Jul 2005 22:10:39 -0000       1.82
+++ src/tee.c   11 Jul 2005 18:08:44 -0000
@@ -140,7 +140,10 @@ tee (int nfiles, const char **files)
   ssize_t bytes_read;
   int i;
   bool ok = true;
-  const char *mode_string = (append ? "a" : "w");
+  char const *mode_string =
+    (O_BINARY
+     ? (append ? "ab" : "wb")
+     : (append ? "a" : "w"));
 
   descriptors = xnmalloc (nfiles + 1, sizeof *descriptors);
 
@@ -149,7 +152,10 @@ tee (int nfiles, const char **files)
   for (i = nfiles; i >= 1; i--)
     files[i] = files[i - 1];
 
-  SET_BINARY2 (0, 1);
+  if (O_BINARY && ! isatty (STDIN_FILENO))
+    freopen (NULL, "rb", stdin);
+  if (O_BINARY && ! isatty (STDOUT_FILENO))
+    freopen (NULL, "wb", stdout);
 
   /* In the array of NFILES + 1 descriptors, make
      the first one correspond to standard output.   */
@@ -168,10 +174,7 @@ tee (int nfiles, const char **files)
          ok = false;
        }
       else
-       {
-         SETVBUF (descriptors[i], NULL, _IONBF, 0);
-         SET_BINARY (fileno (descriptors[i]));
-       }
+       SETVBUF (descriptors[i], NULL, _IONBF, 0);
     }
 
   while (1)
Index: src/tr.c
===================================================================
RCS file: /fetish/cu/src/tr.c,v
retrieving revision 1.143
diff -p -u -r1.143 tr.c
--- src/tr.c    18 Jun 2005 06:25:09 -0000      1.143
+++ src/tr.c    11 Jul 2005 18:08:44 -0000
@@ -1761,7 +1761,10 @@ main (int argc, char **argv)
   /* Use binary I/O, since `tr' is sometimes used to transliterate
      non-printable characters, or characters which are stripped away
      by text-mode reads (like CR and ^Z).  */
-  SET_BINARY2 (STDIN_FILENO, STDOUT_FILENO);
+  if (O_BINARY && ! isatty (STDIN_FILENO))
+    freopen (NULL, "rb", stdin);
+  if (O_BINARY && ! isatty (STDOUT_FILENO))
+    freopen (NULL, "wb", stdout);
 
   if (squeeze_repeats && non_option_args == 1)
     {
Index: src/unexpand.c
===================================================================
RCS file: /fetish/cu/src/unexpand.c,v
retrieving revision 1.93
diff -p -u -r1.93 unexpand.c
--- src/unexpand.c      5 Jul 2005 06:32:54 -0000       1.93
+++ src/unexpand.c      11 Jul 2005 18:08:44 -0000
@@ -302,9 +302,6 @@ unexpand (void)
   if (!fp)
     return;
 
-  /* Binary I/O will preserve the original EOL style (DOS/Unix) of files.  */
-  SET_BINARY2 (fileno (fp), STDOUT_FILENO);
-
   /* The worst case is a non-blank character, then one blank, then a
      tab stop, then MAX_COLUMN_WIDTH - 1 blanks, then a non-blank; so
      allocate MAX_COLUMN_WIDTH bytes to store the blanks.  */
@@ -348,7 +345,7 @@ unexpand (void)
       do
        {
          while ((c = getc (fp)) < 0 && (fp = next_file (fp)))
-           SET_BINARY2 (fileno (fp), STDOUT_FILENO);
+           continue;
 
          if (convert)
            {
Index: src/wc.c
===================================================================
RCS file: /fetish/cu/src/wc.c,v
retrieving revision 1.105
diff -p -u -r1.105 wc.c
--- src/wc.c    14 May 2005 07:58:37 -0000      1.105
+++ src/wc.c    11 Jul 2005 18:08:45 -0000
@@ -226,9 +226,6 @@ wc (int fd, char const *file_x, struct f
     }
   count_complicated = print_words | print_linelength;
 
-  /* We need binary input, since `wc' relies on `lseek' and byte counts.  */
-  SET_BINARY (fd);
-
   /* When counting only bytes, save some line- and word-counting
      overhead.  If FD is a `regular' Unix file, using lseek is enough
      to get its `size' in bytes.  Otherwise, read blocks of BUFFER_SIZE
@@ -504,14 +501,16 @@ wc (int fd, char const *file_x, struct f
 static bool
 wc_file (char const *file, struct fstatus *fstatus)
 {
-  if (STREQ (file, "-"))
+  if (! file || STREQ (file, "-"))
     {
       have_read_stdin = true;
+      if (O_BINARY && ! isatty (STDIN_FILENO))
+       freopen (NULL, "rb", stdin);
       return wc (STDIN_FILENO, file, fstatus);
     }
   else
     {
-      int fd = open (file, O_RDONLY);
+      int fd = open (file, O_RDONLY | O_BINARY);
       if (fd == -1)
        {
          error (0, errno, "%s", file);
@@ -595,6 +594,7 @@ compute_number_width (int nfiles, struct
 int
 main (int argc, char **argv)
 {
+  int i;
   bool ok;
   int optc;
   int nfiles;
@@ -653,23 +653,13 @@ main (int argc, char **argv)
   fstatus = get_input_fstatus (nfiles, argv + optind);
   number_width = compute_number_width (nfiles, fstatus);
 
-  if (! argv[optind])
-    {
-      have_read_stdin = true;
-      ok = wc (STDIN_FILENO, NULL, &fstatus[0]);
-    }
-  else
-    {
-      int i;
-
-      ok = true;
-      for (i = 0; i < nfiles; i++)
-       ok &= wc_file (argv[optind + i], &fstatus[i]);
-
-      if (nfiles > 1)
-       write_counts (total_lines, total_words, total_chars, total_bytes,
-                     max_line_length, _("total"));
-    }
+  ok = true;
+  for (i = 0; i < nfiles; i++)
+    ok &= wc_file (argv[optind + i], &fstatus[i]);
+
+  if (1 < nfiles)
+    write_counts (total_lines, total_words, total_chars, total_bytes,
+                 max_line_length, _("total"));
 
   free (fstatus);
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]