From a5ef87836c9dba23c187e361a70dddef87c03746 Mon Sep 17 00:00:00 2001
From: Kaz Kylheku <kaz@kylheku.com>
Date: Mon, 30 Oct 2017 06:56:03 -0700
Subject: streams: allow "b" flag on open-command.

Currently, using "rb" in open-command reports an error on
GNU/Linux, due to popen not liking the "b" mode.
On Cygwin, the "b" flag is useful with popen.

* stream.c (normalize_mode_no_bin): New function.
(open_command): Use normalize_mode_no_bin instead of
normalize_mode to strip out the binary flag.
This doesn't happen on Cygwin, though.

* stream.h (normalize_mode_no_bin): Declared.

* share/txr/stdlib/getput.tl (command-get-buf): Since
we are getting binary data, pass the "rb" mode to
open-command, now that it works.
(command-put-buf): Add "b" flag to mode passed
to open-command.
---
 share/txr/stdlib/getput.tl |  4 ++--
 stream.c                   | 18 +++++++++++++++++-
 stream.h                   |  1 +
 3 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/share/txr/stdlib/getput.tl b/share/txr/stdlib/getput.tl
index cb3e621e..53779b6c 100644
--- a/share/txr/stdlib/getput.tl
+++ b/share/txr/stdlib/getput.tl
@@ -107,9 +107,9 @@
     (put-lines lines s)))
 
 (defun command-get-buf (cmd)
-  (with-stream (s (open-command cmd))
+  (with-stream (s (open-command cmd "rb"))
     (sys:get-buf-common s)))
 
 (defun command-put-buf (cmd buf)
-  (with-stream (s (open-command cmd "w"))
+  (with-stream (s (open-command cmd "wb"))
     (put-buf buf 0 s)))
diff --git a/stream.c b/stream.c
index 2af67db2..9c4f40d5 100644
--- a/stream.c
+++ b/stream.c
@@ -1446,6 +1446,22 @@ val normalize_mode(struct stdio_mode *m, val mode_str, struct stdio_mode m_dfl)
   return format_mode(*m);
 }
 
+val normalize_mode_no_bin(struct stdio_mode *m, val mode_str, struct stdio_mode m_dfl)
+{
+#ifdef __CYGWIN__
+  return normalize_mode(m, mode_str, m_dfl);
+#else
+  *m = do_parse_mode(mode_str, m_dfl);
+
+  if (m->malformed)
+    uw_throwf(file_error_s, lit("invalid file open mode ~a"), mode_str, nao);
+
+  m->binary = 0;
+
+  return format_mode(*m);
+#endif
+}
+
 val set_mode_props(const struct stdio_mode m, val stream)
 {
   if (m.interactive || m.linebuf || m.unbuf || m.buforder != -1) {
@@ -3857,7 +3873,7 @@ static void fds_restore(struct save_fds *fds)
 val open_command(val path, val mode_str)
 {
   struct stdio_mode m, m_r = stdio_mode_init_r;
-  val mode = normalize_mode(&m, mode_str, m_r);
+  val mode = normalize_mode_no_bin(&m, mode_str, m_r);
   int input = m.read != 0;
   struct save_fds sfds;
   FILE *f = 0;
diff --git a/stream.h b/stream.h
index 149e9ded..17b64aa1 100644
--- a/stream.h
+++ b/stream.h
@@ -143,6 +143,7 @@ void stream_mark_op(val stream);
 void stream_destroy_op(val stream);
 struct stdio_mode parse_mode(val mode_str, struct stdio_mode m_dfl);
 val normalize_mode(struct stdio_mode *m, val mode_str, struct stdio_mode m_dfl);
+val normalize_mode_no_bin(struct stdio_mode *m, val mode_str, struct stdio_mode m_dfl);
 val set_mode_props(const struct stdio_mode m, val stream);
 val generic_get_line(val stream);
 val errno_to_string(val err);
-- 
cgit v1.2.3