diff options
Diffstat (limited to 'src/blocking')
-rw-r--r-- | src/blocking/command.rs | 23 | ||||
-rw-r--r-- | src/blocking/mod.rs | 2 | ||||
-rw-r--r-- | src/blocking/pty.rs | 65 |
3 files changed, 45 insertions, 45 deletions
diff --git a/src/blocking/command.rs b/src/blocking/command.rs index 6c4a825..9cacebe 100644 --- a/src/blocking/command.rs +++ b/src/blocking/command.rs @@ -117,14 +117,13 @@ impl Command { } /// Executes the command as a child process via - /// [`std::process::Command::spawn`], and attaches the given `pty` to - /// that child. The pty will be attached to all of `stdin`, `stdout`, and - /// `stderr` of the child, unless those file descriptors were previously - /// overridden through calls to [`stdin`](Self::stdin), - /// [`stdout`](Self::stdout), or [`stderr`](Self::stderr). The newly - /// created child process will also be made the session leader of a new - /// session, and will have the given `pty` instance set as its controlling - /// terminal. + /// [`std::process::Command::spawn`] on the given pty. The pty will be + /// attached to all of `stdin`, `stdout`, and `stderr` of the child, + /// unless those file descriptors were previously overridden through calls + /// to [`stdin`](Self::stdin), [`stdout`](Self::stdout), or + /// [`stderr`](Self::stderr). The newly created child process will also be + /// made the session leader of a new session, and will have the given + /// pty set as its controlling terminal. /// /// # Errors /// Returns an error if we fail to allocate new file descriptors for @@ -134,10 +133,9 @@ impl Command { /// session leader or set its controlling terminal. pub fn spawn( &mut self, - pty: &crate::blocking::Pty, + pts: &crate::blocking::Pts, ) -> crate::Result<std::process::Child> { - let pts = pty.pts(); - let (stdin, stdout, stderr) = crate::sys::setup_subprocess(pts)?; + let (stdin, stdout, stderr) = pts.0.setup_subprocess()?; if !self.stdin { self.inner.stdin(stdin); @@ -149,7 +147,7 @@ impl Command { self.inner.stderr(stderr); } - let mut session_leader = crate::sys::session_leader(pts); + let mut session_leader = pts.0.session_leader(); // Safety: setsid() is an async-signal-safe function and ioctl() is a // raw syscall (which is inherently async-signal-safe). if let Some(mut custom) = self.pre_exec.take() { @@ -190,6 +188,7 @@ impl Command { self } + /// See [`std::os::unix::process::CommandExt::arg0`] pub fn arg0<S>(&mut self, arg: S) -> &mut Self where S: AsRef<std::ffi::OsStr>, diff --git a/src/blocking/mod.rs b/src/blocking/mod.rs index 17a0733..9f4e284 100644 --- a/src/blocking/mod.rs +++ b/src/blocking/mod.rs @@ -4,4 +4,4 @@ mod command; pub use command::Command; mod pty; -pub use pty::Pty; +pub use pty::{Pts, Pty}; diff --git a/src/blocking/pty.rs b/src/blocking/pty.rs index 6fa3382..e2c5bde 100644 --- a/src/blocking/pty.rs +++ b/src/blocking/pty.rs @@ -1,8 +1,5 @@ /// An allocated pty -pub struct Pty { - pt: std::fs::File, - pts: std::fs::File, -} +pub struct Pty(crate::sys::Pty); impl Pty { /// Allocate and return a new pty. @@ -10,12 +7,7 @@ impl Pty { /// # Errors /// Returns an error if the pty failed to be allocated. pub fn new() -> crate::Result<Self> { - let (pt, ptsname) = crate::sys::create_pt()?; - let pts = std::fs::OpenOptions::new() - .read(true) - .write(true) - .open(&ptsname)?; - Ok(Self { pt, pts }) + Ok(Self(crate::sys::Pty::open()?)) } /// Change the terminal size associated with the pty. @@ -23,51 +15,60 @@ impl Pty { /// # Errors /// Returns an error if we were unable to set the terminal size. pub fn resize(&self, size: crate::Size) -> crate::Result<()> { - Ok(crate::sys::set_term_size(self, size)?) + self.0.set_term_size(size) } - pub(crate) fn pts(&self) -> &std::fs::File { - &self.pts + /// Opens a file descriptor for the other end of the pty, which should be + /// attached to the child process running in it. See + /// [`Command::spawn`](crate::blocking::Command::spawn). + /// + /// # Errors + /// Returns an error if the device node to open could not be determined, + /// or if the device node could not be opened. + pub fn pts(&self) -> crate::Result<Pts> { + Ok(Pts(self.0.pts()?)) } } -impl std::ops::Deref for Pty { - type Target = std::fs::File; - - fn deref(&self) -> &Self::Target { - &self.pt +impl std::os::unix::io::AsRawFd for Pty { + fn as_raw_fd(&self) -> std::os::unix::io::RawFd { + self.0 .0.as_raw_fd() } } -impl std::ops::DerefMut for Pty { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.pt +impl std::io::Read for Pty { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { + self.0 .0.read(buf) } } -impl std::os::unix::io::AsRawFd for Pty { - fn as_raw_fd(&self) -> std::os::unix::io::RawFd { - self.pt.as_raw_fd() +impl std::io::Write for Pty { + fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { + self.0 .0.write(buf) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.0 .0.flush() } } -// there is a Read impl for &std::fs::File, but without this explicit impl, -// rust finds the Read impl for std::fs::File first, and then complains that -// it requires &mut self, because method resolution/autoderef doesn't take -// mutability into account impl std::io::Read for &Pty { fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { - (&self.pt).read(buf) + (&self.0 .0).read(buf) } } -// same as above impl std::io::Write for &Pty { fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { - (&self.pt).write(buf) + (&self.0 .0).write(buf) } fn flush(&mut self) -> std::io::Result<()> { - (&self.pt).flush() + (&self.0 .0).flush() } } + +/// The child end of the pty +/// +/// See [`Pty::pts`] and [`Command::spawn`](crate::blocking::Command::spawn) +pub struct Pts(pub(crate) crate::sys::Pts); |