On 02/15/2017 06:23 AM, Eric Blake wrote:
xfreopen() may need a patch

Thanks for pointing out the problems with my suggestion. I think I'd rather leave xfreopen alone, as silently adjusting its argument from "wb" to "ab" might cause other problems. Instead, I added a Gnulib module to set the file's text-vs-binary mode and changed grep to use that, by installing the attached patches, which I hope address your comments.

From cde60563801884ae65546090b24cb92620b1f828 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 16 Feb 2017 08:40:29 -0800
Subject: [PATCH 1/2] build: update gnulib submodule to latest

---
 gnulib | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gnulib b/gnulib
index b6acb8d..fad631e 160000
--- a/gnulib
+++ b/gnulib
@@ -1 +1 @@
-Subproject commit b6acb8db44af728e88a065526be035f7b927c0bf
+Subproject commit fad631e74dd6c1f0c7fadd99bad1b4b732f6eeb8
-- 
2.9.3

From c4485ac49a977d666187db4c5c25045215976577 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 16 Feb 2017 08:51:34 -0800
Subject: [PATCH 2/2] Fix up recent -U patches

Inspired by a suggestion by Eric Blake (Bug#25707#17).
* bootstrap.conf (gnulib_modules): Add xbinary-io,
and remove binary-io and xfreopen.
* doc/grep.texi (Other Options):
Fix typo and reword to be a bit more general.
* src/grep.c: Include xbinary-io.h instead of xfreopen.h.
(grepfile): Open with O_BINARY if binary.
(grepdesc): No need for set_binary_mode now.
(grep_command_line_arg, main): Set stdin to binary mode if binary.
(main): Avoid unnecessary test of stdin == NULL.
Use xsetmode instead of xfreopen.
* src/system.h: Do not include binary-io.h.
---
 bootstrap.conf |  7 +++----
 doc/grep.texi  | 27 ++++++++++++++-------------
 src/grep.c     | 27 ++++++++++++---------------
 src/system.h   |  1 -
 4 files changed, 29 insertions(+), 33 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index 4115f35..1c50974 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -26,7 +26,6 @@ gnulib_modules='
 alloca
 announce-gen
 argmatch
-binary-io
 c-ctype
 closeout
 dfa
@@ -53,10 +52,10 @@ isatty
 isblank
 iswctype
 largefile
-lseek
 locale
-malloc-gnu
+lseek
 maintainer-makefile
+malloc-gnu
 manywarnings
 mbrlen
 mbrtowc
@@ -95,7 +94,7 @@ wcrtomb
 wctob
 wctype-h
 xalloc
-xfreopen
+xbinary-io
 xstrtoimax
 '
 gnulib_name=libgreputils
diff --git a/doc/grep.texi b/doc/grep.texi
index 94a0621..077c05f 100644
--- a/doc/grep.texi
+++ b/doc/grep.texi
@@ -741,25 +741,26 @@ This can cause a performance penalty.
 @opindex -U
 @opindex --binary
 @cindex MS-Windows binary I/O
-@cindex binary I/O, /MS-Windows
-Under MS-Windows, use binary I/O when reading and writing files other
+@cindex binary I/O
+On platforms that distinguish between text and binary I/O,
+use the latter when reading and writing files other
 than the user's terminal, so that all input bytes are read and written
 as-is.  This overrides the default behavior where @command{grep}
-follows the operating system's advice whether to use binary or text
-I/O.  When @command{grep} uses text I/O it reads a carriage
-return--newline pair as a newline and a Control-Z as end-of-file, and
-it writes a newline as a carriage return--newline pair.  When this
-option is combined with @option{--byte-offset} (@option{-b}), byte
-counts treat each text I/O carriage return--newline as a single byte.
-
-When using text I/O, @option{--binary-files} heuristics are applied to
-input data after text-I/O processing.  These heuristics need not agree
+follows the operating system's advice whether to use text or binary
+I/O@.  On MS-Windows when @command{grep} uses text I/O it reads a
+carriage return--newline pair as a newline and a Control-Z as
+end-of-file, and it writes a newline as a carriage return--newline
+pair.
+
+When using text I/O @option{--byte-offset} (@option{-b}) counts and
+@option{--binary-files} heuristics apply to input data after text-I/O
+processing.  Also, the @option{--binary-files} heuristics need not agree
 with the @option{--binary} option; that is, they may treat the data as
 text even if @option{--binary} is given, or vice versa.
 @xref{File and Directory Selection}.
 
-This option has no effect on platforms other than MS-Windows.
-
+This option has no effect on GNU and other POSIX-compatible platforms,
+which do not distinguish text from binary I/O.
 
 @item -z
 @itemx --null-data
diff --git a/src/grep.c b/src/grep.c
index 32cb642..775f227 100644
--- a/src/grep.c
+++ b/src/grep.c
@@ -48,7 +48,7 @@
 #include "search.h"
 #include "version-etc.h"
 #include "xalloc.h"
-#include "xfreopen.h"
+#include "xbinary-io.h"
 #include "xstrtol.h"
 
 enum { SEP_CHAR_SELECTED = ':' };
@@ -1700,6 +1700,7 @@ static bool
 grepfile (int dirdesc, char const *name, bool follow, bool command_line)
 {
   int oflag = (O_RDONLY | O_NOCTTY
+               | (binary ? O_BINARY : 0)
                | (follow ? 0 : O_NOFOLLOW)
                | (skip_devices (command_line) ? O_NONBLOCK : 0));
   int desc = openat_safer (dirdesc, name, oflag);
@@ -1854,11 +1855,6 @@ grepdesc (int desc, bool command_line)
       goto closeout;
     }
 
-  /* Set input to binary mode.  Pipes are simulated with files
-     on DOS, so this includes the case of "foo | grep bar".  */
-  if (binary && !isatty (desc))
-    set_binary_mode (desc, O_BINARY);
-
   count = grep (desc, &st, &ineof);
   if (count_matches)
     {
@@ -1899,6 +1895,8 @@ grep_command_line_arg (char const *arg)
   if (STREQ (arg, "-"))
     {
       filename = label;
+      if (binary)
+        xset_binary_mode (STDIN_FILENO, O_BINARY);
       return grepdesc (STDIN_FILENO, true);
     }
   else
@@ -2579,14 +2577,15 @@ main (int argc, char **argv)
         if (STREQ (optarg, "-"))
           {
             if (binary)
-              xfreopen (NULL, "rb", stdin);
+              xset_binary_mode (STDIN_FILENO, O_BINARY);
             fp = stdin;
           }
         else
-          fp = fopen (optarg, binary ? "rb" : "r");
-
-        if (!fp)
-          die (EXIT_TROUBLE, errno, "%s", optarg);
+          {
+            fp = fopen (optarg, binary ? "rb" : "r");
+            if (!fp)
+              die (EXIT_TROUBLE, errno, "%s", optarg);
+          }
         oldcc = keycc;
         for (;; keycc += cc)
           {
@@ -2897,10 +2896,8 @@ main (int argc, char **argv)
   if ((argc - optind > 1 && !no_filenames) || with_filenames)
     out_file = 1;
 
-  /* Output is set to binary mode because we shouldn't convert
-     NL to CR-LF pairs, especially when grepping binary files.  */
-  if (binary && !isatty (STDOUT_FILENO))
-    xfreopen (NULL, "wb", stdout);
+  if (binary)
+    xset_binary_mode (STDOUT_FILENO, O_BINARY);
 
   /* Prefer sysconf for page size, as getpagesize typically returns int.  */
 #ifdef _SC_PAGESIZE
diff --git a/src/system.h b/src/system.h
index 05d8f1a..6292a28 100644
--- a/src/system.h
+++ b/src/system.h
@@ -23,7 +23,6 @@
 #include <unistd.h>
 #include <errno.h>
 
-#include "binary-io.h"
 #include "configmake.h"
 #include "dirname.h"
 #include "ignore-value.h"
-- 
2.9.3

Reply via email to