From e6a3feb286ed68876a7c9fd9162266f741ca1a32 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Tue, 23 Feb 2021 01:22:49 -0500 Subject: add async implementations of the pty itself --- Cargo.toml | 2 +- src/command.rs | 4 +++- src/error.rs | 3 +++ src/pty.rs | 16 +++++++++------- src/pty/async_io.rs | 15 ++++++++++++--- src/pty/std.rs | 11 +++++++++-- src/pty/tokio.rs | 15 ++++++++++++--- 7 files changed, 49 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6357d07..f6fd441 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ thiserror = "1.0" async-io = { version = "1.3", optional = true } async-process = { version = "1.0", optional = true } -tokio = { version = "1.2", optional = true, features = ["process"] } +tokio = { version = "1.2", optional = true, features = ["fs", "process"] } [features] default = ["std"] diff --git a/src/command.rs b/src/command.rs index 4679579..96ece15 100644 --- a/src/command.rs +++ b/src/command.rs @@ -24,6 +24,8 @@ impl Command for T where T: CommandImpl, T::Pty: crate::pty::Pty, + <::Pty as crate::pty::Pty>::Pt: + ::std::os::unix::io::AsRawFd, { type Child = T::Child; type Pty = T::Pty; @@ -82,7 +84,7 @@ impl Child where P: crate::pty::Pty, { - pub fn pty(&self) -> &::std::fs::File { + pub fn pty(&self) -> &P::Pt { self.pty.pt() } diff --git a/src/error.rs b/src/error.rs index 9b65d6a..7521544 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,8 @@ #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("error making pty async")] + AsyncPty(#[source] std::io::Error), + #[error("error creating pty")] CreatePty(#[source] nix::Error), diff --git a/src/pty.rs b/src/pty.rs index f192298..b017225 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -1,6 +1,6 @@ use crate::error::*; -use ::std::os::unix::io::{AsRawFd as _, IntoRawFd as _}; +use ::std::os::unix::io::IntoRawFd as _; pub mod std; @@ -10,14 +10,14 @@ pub mod async_io; pub mod tokio; pub trait Pty { + type Pt; + fn new() -> Result where Self: Sized; - fn pt(&self) -> &::std::fs::File; + fn pt(&self) -> &Self::Pt; fn pts(&self) -> Result<::std::fs::File>; - fn resize(&self, size: &super::Size) -> Result<()> { - set_term_size(self.pt(), size).map_err(Error::SetTermSize) - } + fn resize(&self, size: &super::Size) -> Result<()>; } pub struct Size { @@ -84,9 +84,11 @@ nix::ioctl_write_ptr_bad!( nix::pty::Winsize ); -fn set_term_size(file: &::std::fs::File, size: &Size) -> nix::Result<()> { +fn set_term_size( + fd: ::std::os::unix::io::RawFd, + size: &Size, +) -> nix::Result<()> { let size = size.into(); - let fd = file.as_raw_fd(); // safe because std::fs::File is required to contain a valid file // descriptor and size is guaranteed to be initialized because it's a // normal rust value, and nix::pty::Winsize is a repr(C) struct with the diff --git a/src/pty/async_io.rs b/src/pty/async_io.rs index 84097f9..3021f7a 100644 --- a/src/pty/async_io.rs +++ b/src/pty/async_io.rs @@ -1,13 +1,15 @@ use crate::error::*; -use std::os::unix::io::FromRawFd as _; +use std::os::unix::io::{AsRawFd as _, FromRawFd as _}; pub struct Pty { - pt: std::fs::File, + pt: async_io::Async, ptsname: std::path::PathBuf, } impl super::Pty for Pty { + type Pt = async_io::Async; + fn new() -> Result { let (pt_fd, ptsname) = super::create_pt()?; @@ -18,10 +20,12 @@ impl super::Pty for Pty { // 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(|e| Error::AsyncPty(e))?; + Ok(Self { pt, ptsname }) } - fn pt(&self) -> &std::fs::File { + fn pt(&self) -> &Self::Pt { &self.pt } @@ -33,4 +37,9 @@ impl super::Pty for Pty { .map_err(|e| Error::OpenPts(self.ptsname.clone(), e))?; Ok(fh) } + + fn resize(&self, size: &super::Size) -> Result<()> { + super::set_term_size(self.pt().as_raw_fd(), size) + .map_err(Error::SetTermSize) + } } diff --git a/src/pty/std.rs b/src/pty/std.rs index 84097f9..a68e3fc 100644 --- a/src/pty/std.rs +++ b/src/pty/std.rs @@ -1,6 +1,6 @@ use crate::error::*; -use std::os::unix::io::FromRawFd as _; +use std::os::unix::io::{AsRawFd as _, FromRawFd as _}; pub struct Pty { pt: std::fs::File, @@ -8,6 +8,8 @@ pub struct Pty { } impl super::Pty for Pty { + type Pt = std::fs::File; + fn new() -> Result { let (pt_fd, ptsname) = super::create_pt()?; @@ -21,7 +23,7 @@ impl super::Pty for Pty { Ok(Self { pt, ptsname }) } - fn pt(&self) -> &std::fs::File { + fn pt(&self) -> &Self::Pt { &self.pt } @@ -33,4 +35,9 @@ impl super::Pty for Pty { .map_err(|e| Error::OpenPts(self.ptsname.clone(), e))?; Ok(fh) } + + fn resize(&self, size: &super::Size) -> Result<()> { + super::set_term_size(self.pt().as_raw_fd(), size) + .map_err(Error::SetTermSize) + } } diff --git a/src/pty/tokio.rs b/src/pty/tokio.rs index 84097f9..995a154 100644 --- a/src/pty/tokio.rs +++ b/src/pty/tokio.rs @@ -1,13 +1,15 @@ use crate::error::*; -use std::os::unix::io::FromRawFd as _; +use std::os::unix::io::{AsRawFd as _, FromRawFd as _}; pub struct Pty { - pt: std::fs::File, + pt: tokio::fs::File, ptsname: std::path::PathBuf, } impl super::Pty for Pty { + type Pt = tokio::fs::File; + fn new() -> Result { let (pt_fd, ptsname) = super::create_pt()?; @@ -18,10 +20,12 @@ impl super::Pty for Pty { // File object to take full ownership. let pt = unsafe { std::fs::File::from_raw_fd(pt_fd) }; + let pt = tokio::fs::File::from_std(pt); + Ok(Self { pt, ptsname }) } - fn pt(&self) -> &std::fs::File { + fn pt(&self) -> &Self::Pt { &self.pt } @@ -33,4 +37,9 @@ impl super::Pty for Pty { .map_err(|e| Error::OpenPts(self.ptsname.clone(), e))?; Ok(fh) } + + fn resize(&self, size: &super::Size) -> Result<()> { + super::set_term_size(self.pt().as_raw_fd(), size) + .map_err(Error::SetTermSize) + } } -- cgit v1.2.3