From 4fefc9d675f0efe5fb26ef97ee2ecf9e87336937 Mon Sep 17 00:00:00 2001
From: Hunter Goldstein <hunter.d.goldstein@gmail.com>
Date: Fri, 28 Jul 2017 13:04:13 -0400
Subject: [PATCH] read builtin now detects if STDIN is a tty

---
 src/shell/variables.rs | 23 ++++++++++++++++++-----
 src/sys/redox.rs       |  9 +++++++++
 src/sys/unix.rs        |  4 ++++
 3 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/src/shell/variables.rs b/src/shell/variables.rs
index 5177a5a4..edee55e8 100644
--- a/src/shell/variables.rs
+++ b/src/shell/variables.rs
@@ -1,5 +1,6 @@
 use fnv::FnvHashMap;
 use std::env;
+use std::io::{self, BufRead};
 use std::process;
 
 use super::directory_stack::DirectoryStack;
@@ -14,6 +15,7 @@ use sys::getpid;
 #[cfg(all(unix, not(target_os = "unix")))]
 use sys::getpid;
 
+use sys;
 use sys::variables as self_sys;
 
 #[derive(Debug)]
@@ -80,11 +82,22 @@ impl Variables {
     pub fn read<I: IntoIterator>(&mut self, args: I) -> i32
         where I::Item: AsRef<str>
     {
-        let mut con = Context::new();
-        for arg in args.into_iter().skip(1) {
-            match con.read_line(format!("{}=", arg.as_ref().trim()), &mut |_| {}) {
-                Ok(buffer) => self.set_var(arg.as_ref(), buffer.trim()),
-                Err(_) => return FAILURE,
+        if sys::isatty(sys::STDIN_FILENO) {
+            let mut con = Context::new();
+            for arg in args.into_iter().skip(1) {
+                match con.read_line(format!("{}=", arg.as_ref().trim()), &mut |_| {}) {
+                    Ok(buffer) => self.set_var(arg.as_ref(), buffer.trim()),
+                    Err(_) => return FAILURE,
+                }
+            }
+        } else {
+            let stdin = io::stdin();
+            let handle = stdin.lock();
+            let mut lines = handle.lines();
+            for arg in args.into_iter().skip(1) {
+                if let Some(Ok(line)) = lines.next() {
+                    self.set_var(arg.as_ref(), line.trim());
+                }
             }
         }
         SUCCESS
diff --git a/src/sys/redox.rs b/src/sys/redox.rs
index 0796a541..f750d98b 100644
--- a/src/sys/redox.rs
+++ b/src/sys/redox.rs
@@ -82,6 +82,15 @@ pub fn close(fd: RawFd) -> io::Result<()> {
     cvt(syscall::close(fd)).and(Ok(()))
 }
 
+pub fn isatty(fd: RawFd) -> bool {
+    if let Ok(fd) = syscall::dup(f, &[]) {
+        let _ = syscall::close(fd);
+        true
+    } else {
+        false
+    }
+}
+
 // Support function for converting syscall error to io error
 fn cvt(result: Result<usize, syscall::Error>) -> io::Result<usize> {
     result.map_err(|err| io::Error::from_raw_os_error(err.errno))
diff --git a/src/sys/unix.rs b/src/sys/unix.rs
index e0a09774..019bd395 100644
--- a/src/sys/unix.rs
+++ b/src/sys/unix.rs
@@ -74,6 +74,10 @@ pub fn close(fd: RawFd) -> io::Result<()> {
     cvt(unsafe { libc::close(fd) }).and(Ok(()))
 }
 
+pub fn isatty(fd: RawFd) -> bool {
+    unsafe { libc::isatty(fd) == 1 }
+}
+
 // Support functions for converting libc return values to io errors {
 trait IsMinusOne {
     fn is_minus_one(&self) -> bool;
-- 
GitLab