aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-12-28 03:33:52 -0500
committerJesse Luehrs <doy@tozt.net>2021-12-28 05:28:28 -0500
commitf8780ca1e76286688b74d8a6c64d5fadf3cfd2a1 (patch)
treeb1e0fe6a378f3a8810e0332ca572a86185fd556c /src
parentb181b63a69d5db78769c1c3723a9940f66491466 (diff)
downloadpty-process-f8780ca1e76286688b74d8a6c64d5fadf3cfd2a1.tar.gz
pty-process-f8780ca1e76286688b74d8a6c64d5fadf3cfd2a1.zip
wip
Diffstat (limited to 'src')
-rw-r--r--src/async_std.rs7
-rw-r--r--src/command.rs172
-rw-r--r--src/command/async_process.rs33
-rw-r--r--src/command/std.rs33
-rw-r--r--src/command/tokio.rs34
-rw-r--r--src/lib.rs2
-rw-r--r--src/pty.rs83
-rw-r--r--src/pty/async_io.rs49
-rw-r--r--src/pty/std.rs44
-rw-r--r--src/pty/tokio.rs72
-rw-r--r--src/smol.rs7
-rw-r--r--src/std.rs6
-rw-r--r--src/tokio.rs6
13 files changed, 235 insertions, 313 deletions
diff --git a/src/async_std.rs b/src/async_std.rs
index 2a66647..8d0e877 100644
--- a/src/async_std.rs
+++ b/src/async_std.rs
@@ -1,2 +1,5 @@
-pub type Child =
- crate::Child<async_process::Child, crate::pty::async_io::Pty>;
+type Pt = async_io::Async<std::fs::File>;
+
+pub type Command = crate::Command<async_process::Command, Pt>;
+pub type Child = crate::Child<async_process::Child, Pt>;
+pub type Pty = crate::Pty<Pt>;
diff --git a/src/command.rs b/src/command.rs
index 303b885..b3d1104 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -1,6 +1,4 @@
-use crate::pty::Pty as _;
-
-use ::std::os::unix::io::AsRawFd as _;
+use ::std::os::unix::io::{AsRawFd as _, FromRawFd as _};
#[cfg(any(feature = "backend-async-std", feature = "backend-smol"))]
mod async_process;
@@ -9,47 +7,59 @@ mod std;
#[cfg(feature = "backend-tokio")]
mod tokio;
-/// Adds methods to the existing `Command` struct.
-///
-/// This trait is automatically implemented for a backend's `Command` struct
-/// when that backend's feature is enabled.
-pub trait Command {
- type Child;
- type Pty;
+pub struct Command<C: Impl, P: crate::pty::Impl> {
+ inner: C,
+ stdin_set: bool,
+ stdout_set: bool,
+ stderr_set: bool,
- /// Creates a new pty, associates the command's stdin/stdout/stderr with
- /// that pty, and then calls `spawn`. This will override any previous
- /// calls to `stdin`/`stdout`/`stderr`.
- ///
- /// # Errors
- /// * `Error::CreatePty`: error creating pty
- /// * `Error::SetTermSize`: error setting terminal size
- /// * `Error::Spawn`: error spawning subprocess
- fn spawn_pty(
- &mut self,
- size: Option<&crate::pty::Size>,
- ) -> crate::error::Result<Child<Self::Child, Self::Pty>>;
+ _phantom: ::std::marker::PhantomData<P>,
}
-impl<T> Command for T
-where
- T: Impl,
- T::Pty: crate::pty::Pty,
- <<T as Impl>::Pty as crate::pty::Pty>::Pt: ::std::os::unix::io::AsRawFd,
-{
- type Child = T::Child;
- type Pty = T::Pty;
+impl<C: Impl, P: crate::pty::Impl> Command<C, P> {
+ pub fn new<S: AsRef<::std::ffi::OsStr>>(program: S) -> Self {
+ Self {
+ inner: C::new_impl(program.as_ref()),
+ stdin_set: false,
+ stdout_set: false,
+ stderr_set: false,
+
+ _phantom: ::std::marker::PhantomData,
+ }
+ }
+
+ pub fn stdin<T: Into<::std::process::Stdio>>(&mut self, cfg: T) {
+ self.stdin_set = true;
+ self.inner.stdin_impl(cfg.into());
+ }
+
+ pub fn stdout<T: Into<::std::process::Stdio>>(&mut self, cfg: T) {
+ self.stdout_set = true;
+ self.inner.stdout_impl(cfg.into());
+ }
+
+ pub fn stderr<T: Into<::std::process::Stdio>>(&mut self, cfg: T) {
+ self.stderr_set = true;
+ self.inner.stderr_impl(cfg.into());
+ }
- fn spawn_pty(
+ pub fn spawn(
&mut self,
- size: Option<&crate::pty::Size>,
- ) -> crate::error::Result<Child<Self::Child, Self::Pty>> {
- let (pty, pts, stdin, stdout, stderr) = setup_pty::<Self::Pty>(size)?;
+ pty: crate::Pty<P>,
+ ) -> crate::Result<Child<<C as Impl>::Child, P>> {
+ let (pts, stdin, stdout, stderr) = pty.setup()?;
let pt_fd = pty.pt().as_raw_fd();
let pts_fd = pts.as_raw_fd();
- self.std_fds(stdin, stdout, stderr);
+ self.inner
+ .stdin_impl(unsafe { ::std::process::Stdio::from_raw_fd(stdin) });
+ self.inner.stdout_impl(unsafe {
+ ::std::process::Stdio::from_raw_fd(stdout)
+ });
+ self.inner.stderr_impl(unsafe {
+ ::std::process::Stdio::from_raw_fd(stderr)
+ });
let pre_exec = move || {
nix::unistd::setsid()?;
@@ -75,30 +85,44 @@ where
// safe because setsid() and close() are async-signal-safe functions
// and ioctl() is a raw syscall (which is inherently
// async-signal-safe).
- unsafe { self.pre_exec_impl(pre_exec) };
+ unsafe { self.inner.pre_exec_impl(pre_exec) };
+
+ let child = self.inner.spawn_impl()?;
+
+ Ok(Child::new(child, pty))
+ }
+}
+
+impl<C: Impl, P: crate::pty::Impl> ::std::ops::Deref for Command<C, P> {
+ type Target = C;
- let child = self.spawn_impl().map_err(crate::error::spawn)?;
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+}
- Ok(Child { child, pty })
+impl<C: Impl, P: crate::pty::Impl> ::std::ops::DerefMut for Command<C, P> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.inner
}
}
-/// Wrapper struct adding pty methods to the normal `Child` struct.
-pub struct Child<C, P> {
- child: C,
- pty: P,
+pub struct Child<C, P: crate::pty::Impl> {
+ inner: C,
+ pty: crate::Pty<P>,
}
-impl<C, P> Child<C, P>
-where
- P: crate::pty::Pty,
-{
+impl<C, P: crate::pty::Impl> Child<C, P> {
+ fn new(inner: C, pty: crate::Pty<P>) -> Self {
+ Self { inner, pty }
+ }
+
/// Returns a reference to the pty.
///
/// The underlying pty instance is guaranteed to implement
/// [`AsRawFd`](::std::os::unix::io::AsRawFd), as well as the appropriate
/// `Read` and `Write` traits for the associated backend.
- pub fn pty(&self) -> &P::Pt {
+ pub fn pty(&self) -> &P {
self.pty.pt()
}
@@ -111,7 +135,7 @@ where
/// This method is primarily useful for the tokio backend, since tokio's
/// `AsyncRead` and `AsyncWrite` traits have methods which take mutable
/// references.
- pub fn pty_mut(&mut self) -> &mut P::Pt {
+ pub fn pty_mut(&mut self) -> &mut P {
self.pty.pt_mut()
}
@@ -124,70 +148,38 @@ where
/// * `Error::SetTermSize`: error setting terminal size
pub fn resize_pty(
&self,
- size: &crate::pty::Size,
+ size: crate::pty::Size,
) -> crate::error::Result<()> {
self.pty.resize(size)
}
}
-impl<C, P> ::std::ops::Deref for Child<C, P> {
+impl<C, P: crate::pty::Impl> ::std::ops::Deref for Child<C, P> {
type Target = C;
fn deref(&self) -> &Self::Target {
- &self.child
+ &self.inner
}
}
-impl<C, P> ::std::ops::DerefMut for Child<C, P> {
+impl<C, P: crate::pty::Impl> ::std::ops::DerefMut for Child<C, P> {
fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.child
+ &mut self.inner
}
}
-// XXX shouldn't be pub?
pub trait Impl {
type Child;
- type Pty;
- fn std_fds(
- &mut self,
- stdin: ::std::os::unix::io::RawFd,
- stdout: ::std::os::unix::io::RawFd,
- stderr: ::std::os::unix::io::RawFd,
- );
+ fn new_impl(program: &::std::ffi::OsStr) -> Self;
+ fn stdin_impl(&mut self, cfg: ::std::process::Stdio);
+ fn stdout_impl(&mut self, cfg: ::std::process::Stdio);
+ fn stderr_impl(&mut self, cfg: ::std::process::Stdio);
unsafe fn pre_exec_impl<F>(&mut self, f: F)
where
F: FnMut() -> ::std::io::Result<()> + Send + Sync + 'static;
- fn spawn_impl(&mut self) -> ::std::io::Result<Self::Child>;
-}
-
-fn setup_pty<P>(
- size: Option<&crate::pty::Size>,
-) -> crate::error::Result<(
- P,
- ::std::fs::File,
- ::std::os::unix::io::RawFd,
- ::std::os::unix::io::RawFd,
- ::std::os::unix::io::RawFd,
-)>
-where
- P: crate::pty::Pty,
-{
- let pty = P::new()?;
- if let Some(size) = size {
- pty.resize(size)?;
- }
-
- let pts = pty.pts()?;
- let pts_fd = pts.as_raw_fd();
-
- let stdin = nix::unistd::dup(pts_fd).map_err(crate::error::create_pty)?;
- let stdout =
- nix::unistd::dup(pts_fd).map_err(crate::error::create_pty)?;
- let stderr =
- nix::unistd::dup(pts_fd).map_err(crate::error::create_pty)?;
- Ok((pty, pts, stdin, stdout, stderr))
+ fn spawn_impl(&mut self) -> crate::Result<Self::Child>;
}
fn set_controlling_terminal(
diff --git a/src/command/async_process.rs b/src/command/async_process.rs
index 4a1d042..a0aaa47 100644
--- a/src/command/async_process.rs
+++ b/src/command/async_process.rs
@@ -1,23 +1,22 @@
use async_process::unix::CommandExt as _;
-use std::os::unix::io::FromRawFd as _;
impl super::Impl for async_process::Command {
type Child = async_process::Child;
- type Pty = crate::pty::async_io::Pty;
- fn std_fds(
- &mut self,
- stdin: ::std::os::unix::io::RawFd,
- stdout: ::std::os::unix::io::RawFd,
- stderr: ::std::os::unix::io::RawFd,
- ) {
- // safe because the fds are valid (otherwise pty.pts() or dup() would
- // have returned an Err and we would have exited early) and are not
- // owned by any other structure (since dup() returns a fresh copy of
- // the file descriptor), allowing from_raw_fd to take ownership of it.
- self.stdin(unsafe { std::process::Stdio::from_raw_fd(stdin) })
- .stdout(unsafe { std::process::Stdio::from_raw_fd(stdout) })
- .stderr(unsafe { std::process::Stdio::from_raw_fd(stderr) });
+ fn new_impl(program: &::std::ffi::OsStr) -> Self {
+ Self::new(program)
+ }
+
+ fn stdin_impl(&mut self, cfg: ::std::process::Stdio) {
+ self.stdin(cfg);
+ }
+
+ fn stdout_impl(&mut self, cfg: ::std::process::Stdio) {
+ self.stdout(cfg);
+ }
+
+ fn stderr_impl(&mut self, cfg: ::std::process::Stdio) {
+ self.stderr(cfg);
}
unsafe fn pre_exec_impl<F>(&mut self, f: F)
@@ -27,7 +26,7 @@ impl super::Impl for async_process::Command {
self.pre_exec(f);
}
- fn spawn_impl(&mut self) -> ::std::io::Result<Self::Child> {
- self.spawn()
+ fn spawn_impl(&mut self) -> crate::Result<Self::Child> {
+ self.spawn().map_err(crate::error::spawn)
}
}
diff --git a/src/command/std.rs b/src/command/std.rs
index 5c08808..2a89db5 100644
--- a/src/command/std.rs
+++ b/src/command/std.rs
@@ -1,23 +1,22 @@
-use std::os::unix::io::FromRawFd as _;
use std::os::unix::process::CommandExt as _;
impl super::Impl for std::process::Command {
type Child = std::process::Child;
- type Pty = crate::pty::std::Pty;
- fn std_fds(
- &mut self,
- stdin: ::std::os::unix::io::RawFd,
- stdout: ::std::os::unix::io::RawFd,
- stderr: ::std::os::unix::io::RawFd,
- ) {
- // safe because the fds are valid (otherwise pty.pts() or dup() would
- // have returned an Err and we would have exited early) and are not
- // owned by any other structure (since dup() returns a fresh copy of
- // the file descriptor), allowing from_raw_fd to take ownership of it.
- self.stdin(unsafe { std::process::Stdio::from_raw_fd(stdin) })
- .stdout(unsafe { std::process::Stdio::from_raw_fd(stdout) })
- .stderr(unsafe { std::process::Stdio::from_raw_fd(stderr) });
+ fn new_impl(program: &::std::ffi::OsStr) -> Self {
+ Self::new(program)
+ }
+
+ fn stdin_impl(&mut self, cfg: ::std::process::Stdio) {
+ self.stdin(cfg);
+ }
+
+ fn stdout_impl(&mut self, cfg: ::std::process::Stdio) {
+ self.stdout(cfg);
+ }
+
+ fn stderr_impl(&mut self, cfg: ::std::process::Stdio) {
+ self.stderr(cfg);
}
unsafe fn pre_exec_impl<F>(&mut self, f: F)
@@ -27,7 +26,7 @@ impl super::Impl for std::process::Command {
self.pre_exec(f);
}
- fn spawn_impl(&mut self) -> ::std::io::Result<Self::Child> {
- self.spawn()
+ fn spawn_impl(&mut self) -> crate::Result<Self::Child> {
+ self.spawn().map_err(crate::error::spawn)
}
}
diff --git a/src/command/tokio.rs b/src/command/tokio.rs
index 58d2c26..c63b18a 100644
--- a/src/command/tokio.rs
+++ b/src/command/tokio.rs
@@ -1,22 +1,20 @@
-use std::os::unix::io::FromRawFd as _;
-
impl super::Impl for tokio::process::Command {
type Child = tokio::process::Child;
- type Pty = crate::pty::tokio::Pty;
- fn std_fds(
- &mut self,
- stdin: ::std::os::unix::io::RawFd,
- stdout: ::std::os::unix::io::RawFd,
- stderr: ::std::os::unix::io::RawFd,
- ) {
- // safe because the fds are valid (otherwise pty.pts() or dup() would
- // have returned an Err and we would have exited early) and are not
- // owned by any other structure (since dup() returns a fresh copy of
- // the file descriptor), allowing from_raw_fd to take ownership of it.
- self.stdin(unsafe { std::process::Stdio::from_raw_fd(stdin) })
- .stdout(unsafe { std::process::Stdio::from_raw_fd(stdout) })
- .stderr(unsafe { std::process::Stdio::from_raw_fd(stderr) });
+ fn new_impl(program: &::std::ffi::OsStr) -> Self {
+ Self::new(program)
+ }
+
+ fn stdin_impl(&mut self, cfg: ::std::process::Stdio) {
+ self.stdin(cfg);
+ }
+
+ fn stdout_impl(&mut self, cfg: ::std::process::Stdio) {
+ self.stdout(cfg);
+ }
+
+ fn stderr_impl(&mut self, cfg: ::std::process::Stdio) {
+ self.stderr(cfg);
}
unsafe fn pre_exec_impl<F>(&mut self, f: F)
@@ -26,7 +24,7 @@ impl super::Impl for tokio::process::Command {
self.pre_exec(f);
}
- fn spawn_impl(&mut self) -> ::std::io::Result<Self::Child> {
- self.spawn()
+ fn spawn_impl(&mut self) -> crate::Result<Self::Child> {
+ self.spawn().map_err(crate::error::spawn)
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 06f1bbd..5ccaed5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -63,7 +63,7 @@ pub use command::{Child, Command};
mod error;
pub use error::{Error, Result, Source};
mod pty;
-pub use pty::Size;
+pub use pty::{Pty, Size};
#[cfg(feature = "backend-async-std")]
pub mod async_std;
diff --git a/src/pty.rs b/src/pty.rs
index a569f88..72c59e1 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -1,4 +1,4 @@
-use ::std::os::unix::io::IntoRawFd as _;
+use ::std::os::unix::io::{AsRawFd as _, FromRawFd as _, IntoRawFd as _};
#[cfg(any(feature = "backend-async-std", feature = "backend-smol"))]
pub mod async_io;
@@ -7,19 +7,76 @@ pub mod std;
#[cfg(feature = "backend-tokio")]
pub mod tokio;
-pub trait Pty {
- type Pt;
+pub struct Pty<Pt: Impl> {
+ pt: Pt,
+ ptsname: ::std::path::PathBuf,
+}
+
+impl<Pt: Impl> Pty<Pt> {
+ pub fn new() -> crate::error::Result<Self> {
+ let (pt_fd, ptsname) = create_pt()?;
+
+ // safe because posix_openpt (or the previous functions operating on
+ // the result) would have returned an Err (causing us to return early)
+ // if the file descriptor was invalid. additionally, into_raw_fd gives
+ // up ownership over the file descriptor, allowing the newly created
+ // File object to take full ownership.
+ let fh = unsafe { ::std::fs::File::from_raw_fd(pt_fd) };
+ let pt = Pt::new_from_fh(fh)?;
+
+ Ok(Self { pt, ptsname })
+ }
+
+ pub fn pt(&self) -> &Pt {
+ &self.pt
+ }
+
+ pub fn pt_mut(&mut self) -> &mut Pt {
+ &mut self.pt
+ }
+
+ pub fn resize(&self, size: crate::Size) -> crate::error::Result<()> {
+ set_term_size(self.pt().as_raw_fd(), size)
+ .map_err(crate::error::set_term_size)
+ }
+
+ fn pts(&self) -> crate::error::Result<::std::fs::File> {
+ let fh = ::std::fs::OpenOptions::new()
+ .read(true)
+ .write(true)
+ .open(&self.ptsname)
+ .map_err(crate::error::create_pty)?;
+ Ok(fh)
+ }
+
+ pub(crate) fn setup(
+ &self,
+ ) -> crate::Result<(
+ ::std::fs::File,
+ ::std::os::unix::io::RawFd,
+ ::std::os::unix::io::RawFd,
+ ::std::os::unix::io::RawFd,
+ )> {
+ let pts = self.pts()?;
+ let pts_fd = pts.as_raw_fd();
+
+ let stdin =
+ nix::unistd::dup(pts_fd).map_err(crate::error::create_pty)?;
+ let stdout =
+ nix::unistd::dup(pts_fd).map_err(crate::error::create_pty)?;
+ let stderr =
+ nix::unistd::dup(pts_fd).map_err(crate::error::create_pty)?;
+
+ Ok((pts, stdin, stdout, stderr))
+ }
+}
- fn new() -> crate::error::Result<Self>
- where
- Self: Sized;
- fn pt(&self) -> &Self::Pt;
- fn pt_mut(&mut self) -> &mut Self::Pt;
- fn pts(&self) -> crate::error::Result<::std::fs::File>;
- fn resize(&self, size: &super::Size) -> crate::error::Result<()>;
+pub trait Impl: ::std::os::unix::io::AsRawFd + Sized {
+ fn new_from_fh(fh: ::std::fs::File) -> crate::Result<Self>;
}
/// Represents the size of the pty.
+#[derive(Debug, Clone, Copy)]
pub struct Size {
row: u16,
col: u16,
@@ -58,8 +115,8 @@ impl Size {
}
}
-impl From<&Size> for nix::pty::Winsize {
- fn from(size: &Size) -> Self {
+impl From<Size> for nix::pty::Winsize {
+ fn from(size: Size) -> Self {
Self {
ws_row: size.row,
ws_col: size.col,
@@ -96,7 +153,7 @@ nix::ioctl_write_ptr_bad!(
fn set_term_size(
fd: ::std::os::unix::io::RawFd,
- size: &Size,
+ size: Size,
) -> nix::Result<()> {
let size = size.into();
// safe because std::fs::File is required to contain a valid file
diff --git a/src/pty/async_io.rs b/src/pty/async_io.rs
index 304f403..d76c92c 100644
--- a/src/pty/async_io.rs
+++ b/src/pty/async_io.rs
@@ -1,48 +1,5 @@
-use std::os::unix::io::{AsRawFd as _, FromRawFd as _};
-
-pub struct Pty {
- pt: async_io::Async<std::fs::File>,
- ptsname: std::path::PathBuf,
-}
-
-impl super::Pty for Pty {
- type Pt = async_io::Async<std::fs::File>;
-
- fn new() -> crate::error::Result<Self> {
- let (pt_fd, ptsname) = super::create_pt()?;
-
- // safe because posix_openpt (or the previous functions operating on
- // the result) would have returned an Err (causing us to return early)
- // if the file descriptor was invalid. additionally, into_raw_fd gives
- // up ownership over the file descriptor, allowing the newly created
- // File object to take full ownership.
- let pt = unsafe { std::fs::File::from_raw_fd(pt_fd) };
-
- let pt =
- async_io::Async::new(pt).map_err(crate::error::create_pty)?;
-
- Ok(Self { pt, ptsname })
- }
-
- fn pt(&self) -> &Self::Pt {
- &self.pt
- }
-
- fn pt_mut(&mut self) -> &mut Self::Pt {
- &mut self.pt
- }
-
- fn pts(&self) -> crate::error::Result<std::fs::File> {
- let fh = std::fs::OpenOptions::new()
- .read(true)
- .write(true)
- .open(&self.ptsname)
- .map_err(crate::error::create_pty)?;
- Ok(fh)
- }
-
- fn resize(&self, size: &super::Size) -> crate::error::Result<()> {
- super::set_term_size(self.pt().as_raw_fd(), size)
- .map_err(crate::error::set_term_size)
+impl super::Impl for async_io::Async<std::fs::File> {
+ fn new_from_fh(fh: std::fs::File) -> crate::Result<Self> {
+ Self::new(fh).map_err(crate::error::create_pty)
}
}
diff --git a/src/pty/std.rs b/src/pty/std.rs
index c907052..f88e7ba 100644
--- a/src/pty/std.rs
+++ b/src/pty/std.rs
@@ -1,45 +1,5 @@
-use std::os::unix::io::{AsRawFd as _, FromRawFd as _};
-
-pub struct Pty {
- pt: std::fs::File,
- ptsname: std::path::PathBuf,
-}
-
-impl super::Pty for Pty {
- type Pt = std::fs::File;
-
- fn new() -> crate::error::Result<Self> {
- let (pt_fd, ptsname) = super::create_pt()?;
-
- // safe because posix_openpt (or the previous functions operating on
- // the result) would have returned an Err (causing us to return early)
- // if the file descriptor was invalid. additionally, into_raw_fd gives
- // up ownership over the file descriptor, allowing the newly created
- // File object to take full ownership.
- let pt = unsafe { std::fs::File::from_raw_fd(pt_fd) };
-
- Ok(Self { pt, ptsname })
- }
-
- fn pt(&self) -> &Self::Pt {
- &self.pt
- }
-
- fn pt_mut(&mut self) -> &mut Self::Pt {
- &mut self.pt
- }
-
- fn pts(&self) -> crate::error::Result<std::fs::File> {
- let fh = std::fs::OpenOptions::new()
- .read(true)
- .write(true)
- .open(&self.ptsname)
- .map_err(crate::error::create_pty)?;
+impl super::Impl for std::fs::File {
+ fn new_from_fh(fh: std::fs::File) -> crate::Result<Self> {
Ok(fh)
}
-
- fn resize(&self, size: &super::Size) -> crate::error::Result<()> {
- super::set_term_size(self.pt().as_raw_fd(), size)
- .map_err(crate::error::set_term_size)
- }
}
diff --git a/src/pty/tokio.rs b/src/pty/tokio.rs
index e11bffb..ff0b280 100644
--- a/src/pty/tokio.rs
+++ b/src/pty/tokio.rs
@@ -1,5 +1,13 @@
use std::io::{Read as _, Write as _};
-use std::os::unix::io::{AsRawFd as _, FromRawFd as _};
+
+impl super::Impl for AsyncPty {
+ fn new_from_fh(fh: std::fs::File) -> crate::Result<Self> {
+ Ok(Self(
+ tokio::io::unix::AsyncFd::new(fh)
+ .map_err(crate::error::create_pty)?,
+ ))
+ }
+}
// ideally i would just be able to use tokio::fs::File::from_std on the
// std::fs::File i create from the pty fd, but it appears that tokio::fs::File
@@ -91,65 +99,3 @@ impl tokio::io::AsyncWrite for AsyncPty {
std::task::Poll::Ready(Ok(()))
}
}
-
-pub struct Pty {
- pt: AsyncPty,
- ptsname: std::path::PathBuf,
-}
-
-impl super::Pty for Pty {
- type Pt = AsyncPty;
-
- fn new() -> crate::error::Result<Self> {
- let (pt_fd, ptsname) = super::create_pt()?;
-
- let bits = nix::fcntl::fcntl(pt_fd, nix::fcntl::FcntlArg::F_GETFL)
- .map_err(crate::error::create_pty)?;
- // this should be safe because i am just using the return value of
- // F_GETFL directly, but for whatever reason nix doesn't like
- // from_bits(bits) (it claims it has an unknown field)
- let opts = unsafe {
- nix::fcntl::OFlag::from_bits_unchecked(
- bits | nix::fcntl::OFlag::O_NONBLOCK.bits(),
- )
- };
- nix::fcntl::fcntl(pt_fd, nix::fcntl::FcntlArg::F_SETFL(opts))
- .map_err(crate::error::create_pty)?;
-
- // safe because posix_openpt (or the previous functions operating on
- // the result) would have returned an Err (causing us to return early)
- // if the file descriptor was invalid. additionally, into_raw_fd gives
- // up ownership over the file descriptor, allowing the newly created
- // File object to take full ownership.
- let pt = unsafe { std::fs::File::from_raw_fd(pt_fd) };
-
- let pt = AsyncPty(
- tokio::io::unix::AsyncFd::new(pt)
- .map_err(crate::error::create_pty)?,
- );
-
- Ok(Self { pt, ptsname })
- }
-
- fn pt(&self) -> &Self::Pt {
- &self.pt
- }
-
- fn pt_mut(&mut self) -> &mut Self::Pt {
- &mut self.pt
- }
-
- fn pts(&self) -> crate::error::Result<std::fs::File> {
- let fh = std::fs::OpenOptions::new()
- .read(true)
- .write(true)
- .open(&self.ptsname)
- .map_err(crate::error::create_pty)?;
- Ok(fh)
- }
-
- fn resize(&self, size: &super::Size) -> crate::error::Result<()> {
- super::set_term_size(self.pt().as_raw_fd(), size)
- .map_err(crate::error::set_term_size)
- }
-}
diff --git a/src/smol.rs b/src/smol.rs
index 2a66647..8d0e877 100644
--- a/src/smol.rs
+++ b/src/smol.rs
@@ -1,2 +1,5 @@
-pub type Child =
- crate::Child<async_process::Child, crate::pty::async_io::Pty>;
+type Pt = async_io::Async<std::fs::File>;
+
+pub type Command = crate::Command<async_process::Command, Pt>;
+pub type Child = crate::Child<async_process::Child, Pt>;
+pub type Pty = crate::Pty<Pt>;
diff --git a/src/std.rs b/src/std.rs
index 969c51a..4bc0eb0 100644
--- a/src/std.rs
+++ b/src/std.rs
@@ -1 +1,5 @@
-pub type Child = crate::Child<std::process::Child, crate::pty::std::Pty>;
+type Pt = std::fs::File;
+
+pub type Command = crate::Command<std::process::Command, Pt>;
+pub type Child = crate::Child<std::process::Child, Pt>;
+pub type Pty = crate::Pty<Pt>;
diff --git a/src/tokio.rs b/src/tokio.rs
index b0ad53c..e2efa56 100644
--- a/src/tokio.rs
+++ b/src/tokio.rs
@@ -1 +1,5 @@
-pub type Child = crate::Child<tokio::process::Child, crate::pty::tokio::Pty>;
+type Pt = crate::pty::tokio::AsyncPty;
+
+pub type Command = crate::Command<tokio::process::Command, Pt>;
+pub type Child = crate::Child<tokio::process::Child, Pt>;
+pub type Pty = crate::Pty<Pt>;