aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2021-02-22 04:00:53 -0500
committerJesse Luehrs <doy@tozt.net>2021-02-22 04:01:25 -0500
commit5b526af7c0d86158bc0bfc7db0e73dea3bc83cfe (patch)
tree7935a1efedc5e811d01994016eef47bf0c21a4af
parentedfffc8c490b9d179a62901dfb874a85ab0984e3 (diff)
downloadpty-process-5b526af7c0d86158bc0bfc7db0e73dea3bc83cfe.tar.gz
pty-process-5b526af7c0d86158bc0bfc7db0e73dea3bc83cfe.zip
add implementations for async-std and tokio
-rw-r--r--Cargo.toml8
-rw-r--r--src/command.rs5
-rw-r--r--src/command/async_process.rs37
-rw-r--r--src/command/tokio.rs36
4 files changed, 86 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
index d1673b2..27e5bf1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,3 +8,11 @@ edition = "2018"
libc = "*"
nix = "0.17"
thiserror = "1.0"
+
+async-process = { version = "1.0", optional = true }
+tokio = { version = "1.2", optional = true, features = ["process"] }
+
+[features]
+default = ["std"]
+
+std = []
diff --git a/src/command.rs b/src/command.rs
index ba7d764..ca7e4e3 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -4,6 +4,11 @@ use ::std::os::unix::io::AsRawFd as _;
mod std;
+#[cfg(feature = "async-process")]
+mod async_process;
+#[cfg(feature = "tokio")]
+mod tokio;
+
pub trait Command<T> {
fn spawn_pty(
&mut self,
diff --git a/src/command/async_process.rs b/src/command/async_process.rs
new file mode 100644
index 0000000..c712289
--- /dev/null
+++ b/src/command/async_process.rs
@@ -0,0 +1,37 @@
+use crate::error::*;
+
+use async_process::unix::CommandExt as _;
+use std::os::unix::io::{AsRawFd as _, FromRawFd as _};
+
+impl super::Command<async_process::Child> for async_process::Command {
+ fn spawn_pty(
+ &mut self,
+ size: Option<&crate::pty::Size>,
+ ) -> Result<super::Child<async_process::Child>> {
+ let (pty, pts, stdin, stdout, stderr) = super::setup_pty(size)?;
+
+ let pt_fd = pty.pt().as_raw_fd();
+ let pts_fd = pts.as_raw_fd();
+
+ // 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) });
+
+ // 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(move || {
+ super::pre_exec(pt_fd, pts_fd, stdin, stdout, stderr)
+ });
+ }
+
+ let child = self.spawn().map_err(Error::Spawn)?;
+
+ Ok(super::Child { child, pty })
+ }
+}
diff --git a/src/command/tokio.rs b/src/command/tokio.rs
new file mode 100644
index 0000000..f29c247
--- /dev/null
+++ b/src/command/tokio.rs
@@ -0,0 +1,36 @@
+use crate::error::*;
+
+use std::os::unix::io::{AsRawFd as _, FromRawFd as _};
+
+impl super::Command<tokio::process::Child> for tokio::process::Command {
+ fn spawn_pty(
+ &mut self,
+ size: Option<&crate::pty::Size>,
+ ) -> Result<super::Child<tokio::process::Child>> {
+ let (pty, pts, stdin, stdout, stderr) = super::setup_pty(size)?;
+
+ let pt_fd = pty.pt().as_raw_fd();
+ let pts_fd = pts.as_raw_fd();
+
+ // 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) });
+
+ // 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(move || {
+ super::pre_exec(pt_fd, pts_fd, stdin, stdout, stderr)
+ });
+ }
+
+ let child = self.spawn().map_err(Error::Spawn)?;
+
+ Ok(super::Child { child, pty })
+ }
+}