From e07994ad1df7b5e5e9d77d5e0127b9f6b6ed63f7 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Fri, 29 Jul 2016 20:32:58 -0600
Subject: [PATCH] Correct usage of new psuedoterminals

---
 src/terminal/main.rs | 64 +++++++++++++++++---------------------------
 1 file changed, 25 insertions(+), 39 deletions(-)

diff --git a/src/terminal/main.rs b/src/terminal/main.rs
index 7b03d58..829ac05 100644
--- a/src/terminal/main.rs
+++ b/src/terminal/main.rs
@@ -5,13 +5,14 @@ extern crate orbclient;
 
 use orbclient::event;
 
-use std::env;
+use std::{env, str, thread};
 use std::error::Error;
+use std::fs::File;
 use std::io::{Read, Write, self};
+use std::os::unix::io::{FromRawFd, IntoRawFd};
 use std::process::{Command, Stdio};
 use std::sync::{Arc, Mutex};
 use std::time::Duration;
-use std::thread;
 
 use console::Console;
 
@@ -20,24 +21,41 @@ mod console;
 fn main() {
     let shell = env::args().nth(1).unwrap_or("sh".to_string());
 
+    let master = File::create("pty:").unwrap();
+    let tty_path = master.path().unwrap();
+    let master_fd = master.into_raw_fd();
+
+    let slave_stdin = File::open(&tty_path).unwrap();
+    let slave_stdout = File::open(&tty_path).unwrap();
+    let slave_stderr = File::open(&tty_path).unwrap();
+
     let width = 640;
     let height = 480;
 
     env::set_var("COLUMNS", format!("{}", width/8));
     env::set_var("LINES", format!("{}", height/16));
-    match Command::new(&shell).stdin(Stdio::piped()).stdout(Stdio::piped()).stderr(Stdio::piped()).spawn() {
-        Ok(process) => {
+    env::set_var("TTY", format!("{}", tty_path.display()));
+
+    match unsafe {
+        Command::new(&shell)
+            .stdin(Stdio::from_raw_fd(slave_stdin.into_raw_fd()))
+            .stdout(Stdio::from_raw_fd(slave_stdout.into_raw_fd()))
+            .stderr(Stdio::from_raw_fd(slave_stderr.into_raw_fd()))
+            .spawn()
+    } {
+        Ok(_process) => {
             let output_mutex = Arc::new(Mutex::new(Some(Vec::new())));
+            let mut master_stdin = unsafe { File::from_raw_fd(master_fd) };
 
             {
-                let mut stdout = process.stdout.unwrap();
                 let stdout_output_mutex = output_mutex.clone();
                 thread::spawn(move || {
+                    let mut master_stdout = unsafe { File::from_raw_fd(master_fd) };
                     let term_stderr = io::stderr();
                     let mut term_stderr = term_stderr.lock();
                     'stdout: loop {
                         let mut buf = [0; 4096];
-                        match stdout.read(&mut buf) {
+                        match master_stdout.read(&mut buf) {
                             Ok(0) => break 'stdout,
                             Ok(count) => match stdout_output_mutex.lock() {
                                 Ok(mut stdout_output_option) => match *stdout_output_option {
@@ -61,38 +79,6 @@ fn main() {
                 });
             }
 
-            {
-                let mut stderr = process.stderr.unwrap();
-                let stderr_output_mutex = output_mutex.clone();
-                thread::spawn(move || {
-                    let mut term_stderr = io::stderr();
-                    'stderr: loop {
-                        let mut buf = [0; 4096];
-                        match stderr.read(&mut buf) {
-                            Ok(0) => break 'stderr,
-                            Ok(count) => match stderr_output_mutex.lock() {
-                                Ok(mut stderr_output_option) => match *stderr_output_option {
-                                    Some(ref mut stderr_output) => stderr_output.extend_from_slice(&buf[..count]),
-                                    None => break 'stderr
-                                },
-                                Err(_) => {
-                                    let _ = term_stderr.write(b"failed to lock stdout output mutex\n");
-                                    break 'stderr;
-                                }
-                            },
-                            Err(err) => {
-                                let _ = term_stderr.write(b"failed to read stderr: ");
-                                let _ = term_stderr.write(err.description().as_bytes());
-                                let _ = term_stderr.write(b"\n");
-                                break 'stderr;
-                            }
-                        }
-                    }
-                    stderr_output_mutex.lock().unwrap().take();
-                });
-            }
-
-            let mut stdin = process.stdin.unwrap();
             let mut console = Console::new(width, height);
             'events: loop {
                 match output_mutex.lock() {
@@ -117,7 +103,7 @@ fn main() {
                     }
 
                     if let Some(line) = console.event(event) {
-                        if let Err(err) = stdin.write(&line.as_bytes()) {
+                        if let Err(err) = master_stdin.write(&line.as_bytes()) {
                             let term_stderr = io::stderr();
                             let mut term_stderr = term_stderr.lock();
 
-- 
GitLab