aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2023-03-08 00:39:55 -0500
committerJesse Luehrs <doy@tozt.net>2023-03-08 00:39:55 -0500
commit7378dfbc0052dcda076cd3242f29d31eab265566 (patch)
treeadeffc194766f0d44e47351bc23ea2ffb2d1a017
parent959af70ee832299101826a5bda41cb99cb7cd50d (diff)
downloadpty-process-7378dfbc0052dcda076cd3242f29d31eab265566.tar.gz
pty-process-7378dfbc0052dcda076cd3242f29d31eab265566.zip
use the new fd apis in std
-rw-r--r--examples/basic.rs4
-rw-r--r--examples/raw_guard/mod.rs2
-rw-r--r--src/blocking/pty.rs12
-rw-r--r--src/pty.rs12
-rw-r--r--src/sys.rs78
-rw-r--r--tests/behavior.rs43
-rw-r--r--tests/pipe.rs34
7 files changed, 109 insertions, 76 deletions
diff --git a/examples/basic.rs b/examples/basic.rs
index db83818..c490008 100644
--- a/examples/basic.rs
+++ b/examples/basic.rs
@@ -2,7 +2,7 @@ mod raw_guard;
mod main {
use std::io::{Read as _, Write as _};
- use std::os::unix::io::AsRawFd as _;
+ use std::os::fd::{AsFd as _, AsRawFd as _};
pub fn run(
child: &mut std::process::Child,
@@ -10,7 +10,7 @@ mod main {
) {
let _raw = super::raw_guard::RawGuard::new();
let mut buf = [0_u8; 4096];
- let pty_fd = pty.as_raw_fd();
+ let pty_fd = pty.as_fd().as_raw_fd();
let stdin_fd = std::io::stdin().as_raw_fd();
loop {
diff --git a/examples/raw_guard/mod.rs b/examples/raw_guard/mod.rs
index cb6a7d6..4ce498b 100644
--- a/examples/raw_guard/mod.rs
+++ b/examples/raw_guard/mod.rs
@@ -1,4 +1,4 @@
-use std::os::unix::io::AsRawFd as _;
+use std::os::fd::AsRawFd as _;
pub struct RawGuard {
termios: nix::sys::termios::Termios,
diff --git a/src/blocking/pty.rs b/src/blocking/pty.rs
index e2c5bde..445f102 100644
--- a/src/blocking/pty.rs
+++ b/src/blocking/pty.rs
@@ -30,9 +30,15 @@ impl Pty {
}
}
-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 From<Pty> for std::os::fd::OwnedFd {
+ fn from(pty: Pty) -> Self {
+ pty.0.into()
+ }
+}
+
+impl std::os::fd::AsFd for Pty {
+ fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
+ self.0.as_fd()
}
}
diff --git a/src/pty.rs b/src/pty.rs
index 1071df9..87ec874 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -59,9 +59,15 @@ impl Pty {
}
}
-impl std::os::unix::io::AsRawFd for Pty {
- fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
- self.0.as_raw_fd()
+impl From<Pty> for std::os::fd::OwnedFd {
+ fn from(pty: Pty) -> Self {
+ pty.0.into_inner().into()
+ }
+}
+
+impl std::os::fd::AsFd for Pty {
+ fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
+ self.0.get_ref().as_fd()
}
}
diff --git a/src/sys.rs b/src/sys.rs
index 272255f..60c61e9 100644
--- a/src/sys.rs
+++ b/src/sys.rs
@@ -1,4 +1,4 @@
-use std::os::unix::io::{AsRawFd as _, FromRawFd as _, IntoRawFd as _};
+use std::os::fd::{AsRawFd as _, FromRawFd as _};
#[derive(Debug)]
pub struct Pty(pub nix::pty::PtyMaster);
@@ -35,7 +35,7 @@ impl Pty {
.read(true)
.write(true)
.open(nix::pty::ptsname_r(&self.0)?)?
- .into_raw_fd()))
+ .into()))
}
#[cfg(feature = "async")]
@@ -58,43 +58,49 @@ impl Pty {
}
}
-impl std::os::unix::io::AsRawFd for Pty {
- fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
+impl From<Pty> for std::os::fd::OwnedFd {
+ fn from(pty: Pty) -> Self {
+ let Pty(nix_ptymaster) = pty;
+ let raw_fd = nix_ptymaster.as_raw_fd();
+ std::mem::forget(nix_ptymaster);
+
+ // Safety: nix::pty::PtyMaster is required to contain a valid file
+ // descriptor, and we ensured that the file descriptor will remain
+ // valid by skipping the drop implementation for nix::pty::PtyMaster
+ unsafe { Self::from_raw_fd(raw_fd) }
+ }
+}
+
+impl std::os::fd::AsFd for Pty {
+ fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
+ let raw_fd = self.0.as_raw_fd();
+
+ // Safety: nix::pty::PtyMaster is required to contain a valid file
+ // descriptor, and it is owned by self
+ unsafe { std::os::fd::BorrowedFd::borrow_raw(raw_fd) }
+ }
+}
+
+impl std::os::fd::AsRawFd for Pty {
+ fn as_raw_fd(&self) -> std::os::fd::RawFd {
self.0.as_raw_fd()
}
}
-pub struct Pts(std::os::unix::io::RawFd);
+pub struct Pts(std::os::fd::OwnedFd);
impl Pts {
pub fn setup_subprocess(
&self,
- ) -> nix::Result<(
+ ) -> std::io::Result<(
std::process::Stdio,
std::process::Stdio,
std::process::Stdio,
)> {
- let pts_fd = self.0.as_raw_fd();
-
- let stdin = nix::fcntl::fcntl(
- pts_fd,
- nix::fcntl::FcntlArg::F_DUPFD_CLOEXEC(0),
- )?;
- let stdout = nix::fcntl::fcntl(
- pts_fd,
- nix::fcntl::FcntlArg::F_DUPFD_CLOEXEC(0),
- )?;
- let stderr = nix::fcntl::fcntl(
- pts_fd,
- nix::fcntl::FcntlArg::F_DUPFD_CLOEXEC(0),
- )?;
-
- // Safety: these file descriptors were all just returned from dup, so
- // they must be valid
Ok((
- unsafe { std::process::Stdio::from_raw_fd(stdin) },
- unsafe { std::process::Stdio::from_raw_fd(stdout) },
- unsafe { std::process::Stdio::from_raw_fd(stderr) },
+ self.0.try_clone()?.into(),
+ self.0.try_clone()?.into(),
+ self.0.try_clone()?.into(),
))
}
@@ -102,7 +108,7 @@ impl Pts {
let pts_fd = self.0.as_raw_fd();
move || {
nix::unistd::setsid()?;
- // Safety: Pts is required to contain a valid file descriptor
+ // Safety: OwnedFds are required to contain a valid file descriptor
unsafe {
set_controlling_terminal_unsafe(pts_fd, std::ptr::null())
}?;
@@ -111,15 +117,21 @@ impl Pts {
}
}
-impl Drop for Pts {
- fn drop(&mut self) {
- let _ = nix::unistd::close(self.0);
+impl From<Pts> for std::os::fd::OwnedFd {
+ fn from(pts: Pts) -> Self {
+ pts.0
}
}
-impl std::os::unix::io::AsRawFd for Pts {
- fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
- self.0
+impl std::os::fd::AsFd for Pts {
+ fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
+ self.0.as_fd()
+ }
+}
+
+impl std::os::fd::AsRawFd for Pts {
+ fn as_raw_fd(&self) -> std::os::fd::RawFd {
+ self.0.as_raw_fd()
}
}
diff --git a/tests/behavior.rs b/tests/behavior.rs
index ee51cb4..8712643 100644
--- a/tests/behavior.rs
+++ b/tests/behavior.rs
@@ -63,26 +63,24 @@ async fn test_multiple_async() {
#[test]
fn test_multiple_configured() {
use std::io::BufRead as _;
- use std::os::unix::io::FromRawFd as _;
+ use std::os::fd::AsRawFd as _;
let pty = pty_process::blocking::Pty::new().unwrap();
let pts = pty.pts().unwrap();
pty.resize(pty_process::Size::new(24, 80)).unwrap();
- let (stderr_pipe_r, stderr_pipe_w) = nix::unistd::pipe().unwrap();
- let mut stderr_pipe_r = std::io::BufReader::new(unsafe {
- std::fs::File::from_raw_fd(stderr_pipe_r)
- });
- let (pre_exec_pipe_r, pre_exec_pipe_w) = nix::unistd::pipe().unwrap();
- let mut pre_exec_pipe_r = std::io::BufReader::new(unsafe {
- std::fs::File::from_raw_fd(pre_exec_pipe_r)
- });
+ let (stderr_pipe_r, stderr_pipe_w) = pipe();
+ let mut stderr_pipe_r =
+ std::io::BufReader::new(std::fs::File::from(stderr_pipe_r));
+ let (pre_exec_pipe_r, pre_exec_pipe_w) = pipe();
+ let mut pre_exec_pipe_r =
+ std::io::BufReader::new(std::fs::File::from(pre_exec_pipe_r));
let mut cmd = pty_process::blocking::Command::new("perl");
cmd.arg("-Esay 'foo'; say STDERR 'foo-stderr'; open my $fh, '>&=3'; say $fh 'foo-3';")
- .stderr(unsafe { std::process::Stdio::from_raw_fd(stderr_pipe_w) });
+ .stderr(std::process::Stdio::from(stderr_pipe_w));
unsafe {
cmd.pre_exec(move || {
- nix::unistd::dup2(pre_exec_pipe_w, 3)?;
+ nix::unistd::dup2(pre_exec_pipe_w.as_raw_fd(), 3)?;
nix::fcntl::fcntl(
3,
nix::fcntl::F_SETFD(nix::fcntl::FdFlag::empty()),
@@ -135,7 +133,7 @@ fn test_multiple_configured() {
#[tokio::test]
async fn test_multiple_configured_async() {
use futures::stream::StreamExt as _;
- use std::os::unix::io::FromRawFd as _;
+ use std::os::fd::{AsRawFd as _, FromRawFd as _, IntoRawFd as _};
use tokio::io::AsyncBufReadExt as _;
let mut pty = pty_process::Pty::new().unwrap();
@@ -143,13 +141,13 @@ async fn test_multiple_configured_async() {
pty.resize(pty_process::Size::new(24, 80)).unwrap();
let (pty_r, _) = pty.split();
- let (stderr_pipe_r, stderr_pipe_w) = nix::unistd::pipe().unwrap();
+ let (stderr_pipe_r, stderr_pipe_w) = pipe();
let mut stderr_pipe_r = tokio::io::BufReader::new(unsafe {
- tokio::fs::File::from_raw_fd(stderr_pipe_r)
+ tokio::fs::File::from_raw_fd(stderr_pipe_r.into_raw_fd())
});
- let (pre_exec_pipe_r, pre_exec_pipe_w) = nix::unistd::pipe().unwrap();
+ let (pre_exec_pipe_r, pre_exec_pipe_w) = pipe();
let mut pre_exec_pipe_r = tokio::io::BufReader::new(unsafe {
- tokio::fs::File::from_raw_fd(pre_exec_pipe_r)
+ tokio::fs::File::from_raw_fd(pre_exec_pipe_r.into_raw_fd())
});
let mut cmd = pty_process::Command::new("perl");
cmd.arg(
@@ -158,10 +156,10 @@ async fn test_multiple_configured_async() {
open my $fh, '>&=3'; \
say $fh 'foo-3';",
)
- .stderr(unsafe { std::process::Stdio::from_raw_fd(stderr_pipe_w) });
+ .stderr(std::process::Stdio::from(stderr_pipe_w));
unsafe {
cmd.pre_exec(move || {
- nix::unistd::dup2(pre_exec_pipe_w, 3)?;
+ nix::unistd::dup2(pre_exec_pipe_w.as_raw_fd(), 3)?;
nix::fcntl::fcntl(
3,
nix::fcntl::F_SETFD(nix::fcntl::FdFlag::empty()),
@@ -304,3 +302,12 @@ async fn test_session_leader_async() {
eprintln!("{:?}", status);
assert_eq!(status.code().unwrap(), 0);
}
+
+fn pipe() -> (std::os::fd::OwnedFd, std::os::fd::OwnedFd) {
+ use std::os::fd::FromRawFd as _;
+
+ let (r, w) = nix::unistd::pipe().unwrap();
+ (unsafe { std::os::fd::OwnedFd::from_raw_fd(r) }, unsafe {
+ std::os::fd::OwnedFd::from_raw_fd(w)
+ })
+}
diff --git a/tests/pipe.rs b/tests/pipe.rs
index c3d7b9f..3c63602 100644
--- a/tests/pipe.rs
+++ b/tests/pipe.rs
@@ -1,16 +1,13 @@
#[test]
fn test_pipe_basic() {
- use std::os::unix::io::FromRawFd as _;
-
- let (read_fd, write_fd) =
- nix::unistd::pipe2(nix::fcntl::OFlag::O_CLOEXEC).unwrap();
+ let (read_fd, write_fd) = pipe();
let mut child_from = std::process::Command::new("seq");
child_from.args(["1", "10"]);
- child_from.stdout(unsafe { std::process::Stdio::from_raw_fd(write_fd) });
+ child_from.stdout(std::process::Stdio::from(write_fd));
let mut child_to = std::process::Command::new("tac");
- child_to.stdin(unsafe { std::process::Stdio::from_raw_fd(read_fd) });
+ child_to.stdin(std::process::Stdio::from(read_fd));
child_to.stdout(std::process::Stdio::piped());
assert!(child_from.status().unwrap().success());
@@ -23,23 +20,21 @@ fn test_pipe_basic() {
#[test]
fn test_pipe_blocking() {
use std::io::Read as _;
- use std::os::unix::io::FromRawFd as _;
- let (read_fd, write_fd) =
- nix::unistd::pipe2(nix::fcntl::OFlag::O_CLOEXEC).unwrap();
+ let (read_fd, write_fd) = pipe();
let pty_from = pty_process::blocking::Pty::new().unwrap();
let pts_from = pty_from.pts().unwrap();
pty_from.resize(pty_process::Size::new(24, 80)).unwrap();
let mut cmd_from = pty_process::blocking::Command::new("seq");
cmd_from.args(["1", "10"]);
- cmd_from.stdout(unsafe { std::process::Stdio::from_raw_fd(write_fd) });
+ cmd_from.stdout(std::process::Stdio::from(write_fd));
let mut child_from = cmd_from.spawn(&pts_from).unwrap();
let mut pty_to = pty_process::blocking::Pty::new().unwrap();
let pts_to = pty_to.pts().unwrap();
let mut cmd_to = pty_process::blocking::Command::new("tac");
- cmd_to.stdin(unsafe { std::process::Stdio::from_raw_fd(read_fd) });
+ cmd_to.stdin(std::process::Stdio::from(read_fd));
let mut child_to = cmd_to.spawn(&pts_to).unwrap();
assert!(child_from.wait().unwrap().success());
@@ -62,24 +57,22 @@ fn test_pipe_blocking() {
#[cfg(feature = "async")]
#[tokio::test]
async fn test_pipe_async() {
- use std::os::unix::io::FromRawFd as _;
use tokio::io::AsyncReadExt as _;
- let (read_fd, write_fd) =
- nix::unistd::pipe2(nix::fcntl::OFlag::O_CLOEXEC).unwrap();
+ let (read_fd, write_fd) = pipe();
let pty_from = pty_process::Pty::new().unwrap();
let pts_from = pty_from.pts().unwrap();
pty_from.resize(pty_process::Size::new(24, 80)).unwrap();
let mut cmd_from = pty_process::Command::new("seq");
cmd_from.args(["1", "10"]);
- cmd_from.stdout(unsafe { std::process::Stdio::from_raw_fd(write_fd) });
+ cmd_from.stdout(std::process::Stdio::from(write_fd));
let mut child_from = cmd_from.spawn(&pts_from).unwrap();
let mut pty_to = pty_process::Pty::new().unwrap();
let pts_to = pty_to.pts().unwrap();
let mut cmd_to = pty_process::Command::new("tac");
- cmd_to.stdin(unsafe { std::process::Stdio::from_raw_fd(read_fd) });
+ cmd_to.stdin(std::process::Stdio::from(read_fd));
let mut child_to = cmd_to.spawn(&pts_to).unwrap();
assert!(child_from.wait().await.unwrap().success());
@@ -98,3 +91,12 @@ async fn test_pipe_async() {
assert!(child_to.wait().await.unwrap().success());
}
+
+fn pipe() -> (std::os::fd::OwnedFd, std::os::fd::OwnedFd) {
+ use std::os::fd::FromRawFd as _;
+
+ let (r, w) = nix::unistd::pipe2(nix::fcntl::OFlag::O_CLOEXEC).unwrap();
+ (unsafe { std::os::fd::OwnedFd::from_raw_fd(r) }, unsafe {
+ std::os::fd::OwnedFd::from_raw_fd(w)
+ })
+}