aboutsummaryrefslogtreecommitdiffstats
path: root/src/blocking
diff options
context:
space:
mode:
Diffstat (limited to 'src/blocking')
-rw-r--r--src/blocking/command.rs23
-rw-r--r--src/blocking/mod.rs2
-rw-r--r--src/blocking/pty.rs65
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);