From cb611ab3142ccf3c76b2c277ede8f8c539369f67 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 16 Jul 2020 02:35:24 -0400 Subject: move all of the logic into the spawn method keep the command class as a pure builder --- examples/basic.rs | 6 ++--- src/command.rs | 72 +++++++++++++++++++++++++++++++++---------------------- 2 files changed, 46 insertions(+), 32 deletions(-) diff --git a/examples/basic.rs b/examples/basic.rs index 39ef088..6082b09 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -6,7 +6,7 @@ fn main() { // cmd.args(&["--color=auto"]); let mut child = cmd.spawn().unwrap(); let mut buf = [0_u8; 4096]; - let pty = cmd.pty().as_raw_fd(); + let pty = child.pty().as_raw_fd(); let stdin = std::io::stdin().as_raw_fd(); loop { let mut set = nix::sys::select::FdSet::new(); @@ -17,7 +17,7 @@ fn main() { Ok(n) => { if n > 0 { if set.contains(pty) { - match cmd.pty().read(&mut buf) { + match child.pty().read(&mut buf) { Ok(bytes) => { let buf = &buf[..bytes]; print!( @@ -37,7 +37,7 @@ fn main() { match std::io::stdin().read(&mut buf) { Ok(bytes) => { let buf = &buf[..bytes]; - cmd.pty().write_all(buf).unwrap(); + child.pty().write_all(buf).unwrap(); } Err(e) => { eprintln!("stdin read failed: {:?}", e); diff --git a/src/command.rs b/src/command.rs index cf01767..421f2b8 100644 --- a/src/command.rs +++ b/src/command.rs @@ -4,37 +4,13 @@ use std::os::unix::io::{AsRawFd as _, FromRawFd as _}; use std::os::unix::process::CommandExt as _; pub struct Command { - pty: crate::pty::Pty, command: std::process::Command, - pts_fh: Option, } impl Command { pub fn new>(program: S) -> Result { - let pty = crate::pty::Pty::new()?; - let pt_fd = pty.pt().as_raw_fd(); - let pts_fh = pty.pts()?; - let pts_fd = pts_fh.as_raw_fd(); - let mut command = std::process::Command::new(program); - command - .stdin(unsafe { std::process::Stdio::from_raw_fd(pts_fd) }) - .stdout(unsafe { std::process::Stdio::from_raw_fd(pts_fd) }) - .stderr(unsafe { std::process::Stdio::from_raw_fd(pts_fd) }); - unsafe { - command.pre_exec(move || { - // XXX unwrap - nix::unistd::close(pt_fd) - .map_err(|e| e.as_errno().unwrap())?; - nix::unistd::close(pts_fd) - .map_err(|e| e.as_errno().unwrap())?; - Ok(()) - }); - } - Ok(Self { - pty, - command, - pts_fh: Some(pts_fh), - }) + let command = std::process::Command::new(program); + Ok(Self { command }) } pub fn arg>(&mut self, arg: S) -> &mut Self { @@ -101,13 +77,51 @@ impl Command { self } - pub fn spawn(&mut self) -> Result { + pub fn spawn(&mut self) -> Result { + let pty = crate::pty::Pty::new()?; + let pt_fd = pty.pt().as_raw_fd(); + let pts = pty.pts()?; + let pts_fd = pts.as_raw_fd(); + self.command + .stdin(unsafe { std::process::Stdio::from_raw_fd(pts_fd) }) + .stdout(unsafe { std::process::Stdio::from_raw_fd(pts_fd) }) + .stderr(unsafe { std::process::Stdio::from_raw_fd(pts_fd) }); + unsafe { + self.command.pre_exec(move || { + // XXX unwrap + nix::unistd::close(pt_fd) + .map_err(|e| e.as_errno().unwrap())?; + nix::unistd::close(pts_fd) + .map_err(|e| e.as_errno().unwrap())?; + Ok(()) + }); + } let child = self.command.spawn()?; - self.pts_fh = None; - Ok(child) + Ok(Child { child, pty }) } +} +pub struct Child { + child: std::process::Child, + pty: crate::pty::Pty, +} + +impl Child { pub fn pty(&self) -> &std::fs::File { self.pty.pt() } } + +impl std::ops::Deref for Child { + type Target = std::process::Child; + + fn deref(&self) -> &Self::Target { + &self.child + } +} + +impl std::ops::DerefMut for Child { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.child + } +} -- cgit v1.2.3