diff options
author | Jesse Luehrs <doy@tozt.net> | 2021-12-30 23:14:55 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2021-12-30 23:14:55 -0500 |
commit | 09ff545fe44242734d5f6daf4a74946d2f04728d (patch) | |
tree | 79e5b7080dd58137020748fcaf15fb089493b864 | |
parent | a5b7f59b19052b69f3ada89e4b07c1fb6dbfaf34 (diff) | |
download | pty-process-09ff545fe44242734d5f6daf4a74946d2f04728d.tar.gz pty-process-09ff545fe44242734d5f6daf4a74946d2f04728d.zip |
docs
-rw-r--r-- | src/blocking/command.rs | 32 | ||||
-rw-r--r-- | src/blocking/mod.rs | 3 | ||||
-rw-r--r-- | src/blocking/pty.rs | 9 | ||||
-rw-r--r-- | src/command.rs | 33 | ||||
-rw-r--r-- | src/error.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 32 | ||||
-rw-r--r-- | src/pty.rs | 10 |
7 files changed, 120 insertions, 1 deletions
diff --git a/src/blocking/command.rs b/src/blocking/command.rs index 0fa97ea..6c4a825 100644 --- a/src/blocking/command.rs +++ b/src/blocking/command.rs @@ -1,5 +1,6 @@ use std::os::unix::process::CommandExt as _; +/// Wrapper around [`std::process::Command`] pub struct Command { inner: std::process::Command, stdin: bool, @@ -12,6 +13,7 @@ pub struct Command { } impl Command { + /// See [`std::process::Command::new`] pub fn new<S: AsRef<std::ffi::OsStr>>(program: S) -> Self { Self { inner: std::process::Command::new(program), @@ -23,11 +25,13 @@ impl Command { } } + /// See [`std::process::Command::arg`] pub fn arg<S: AsRef<std::ffi::OsStr>>(&mut self, arg: S) -> &mut Self { self.inner.arg(arg); self } + /// See [`std::process::Command::args`] pub fn args<I, S>(&mut self, args: I) -> &mut Self where I: IntoIterator<Item = S>, @@ -37,6 +41,7 @@ impl Command { self } + /// See [`std::process::Command::env`] pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Self where K: AsRef<std::ffi::OsStr>, @@ -46,6 +51,7 @@ impl Command { self } + /// See [`std::process::Command::envs`] pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self where I: IntoIterator<Item = (K, V)>, @@ -56,6 +62,7 @@ impl Command { self } + /// See [`std::process::Command::env_remove`] pub fn env_remove<K: AsRef<std::ffi::OsStr>>( &mut self, key: K, @@ -64,11 +71,13 @@ impl Command { self } + /// See [`std::process::Command::env_clear`] pub fn env_clear(&mut self) -> &mut Self { self.inner.env_clear(); self } + /// See [`std::process::Command::current_dir`] pub fn current_dir<P: AsRef<std::path::Path>>( &mut self, dir: P, @@ -77,6 +86,7 @@ impl Command { self } + /// See [`std::process::Command::stdin`] pub fn stdin<T: Into<std::process::Stdio>>( &mut self, cfg: T, @@ -86,6 +96,7 @@ impl Command { self } + /// See [`std::process::Command::stdout`] pub fn stdout<T: Into<std::process::Stdio>>( &mut self, cfg: T, @@ -95,6 +106,7 @@ impl Command { self } + /// See [`std::process::Command::stderr`] pub fn stderr<T: Into<std::process::Stdio>>( &mut self, cfg: T, @@ -104,6 +116,22 @@ impl Command { self } + /// 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. + /// + /// # Errors + /// Returns an error if we fail to allocate new file descriptors for + /// attaching the pty to the child process, or if we fail to spawn the + /// child process (see the documentation for + /// [`std::process::Command::spawn`]), or if we fail to make the child a + /// session leader or set its controlling terminal. pub fn spawn( &mut self, pty: &crate::blocking::Pty, @@ -140,16 +168,20 @@ impl Command { Ok(self.inner.spawn()?) } + /// See [`std::os::unix::process::CommandExt::uid`] pub fn uid(&mut self, id: u32) -> &mut Self { self.inner.uid(id); self } + /// See [`std::os::unix::process::CommandExt::gid`] pub fn gid(&mut self, id: u32) -> &mut Self { self.inner.gid(id); self } + /// See [`std::os::unix::process::CommandExt::pre_exec`] + #[allow(clippy::missing_safety_doc)] pub unsafe fn pre_exec<F>(&mut self, f: F) -> &mut Self where F: FnMut() -> std::io::Result<()> + Send + Sync + 'static, diff --git a/src/blocking/mod.rs b/src/blocking/mod.rs index cdf66da..17a0733 100644 --- a/src/blocking/mod.rs +++ b/src/blocking/mod.rs @@ -1,3 +1,6 @@ +//! Blocking equivalents for [`pty_process::Command`](crate::Command) and +//! [`pty_process::Pty`](crate::Pty) + mod command; pub use command::Command; mod pty; diff --git a/src/blocking/pty.rs b/src/blocking/pty.rs index d864bd6..6fa3382 100644 --- a/src/blocking/pty.rs +++ b/src/blocking/pty.rs @@ -1,9 +1,14 @@ +/// An allocated pty pub struct Pty { pt: std::fs::File, pts: std::fs::File, } impl Pty { + /// Allocate and return a new 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() @@ -13,6 +18,10 @@ impl Pty { Ok(Self { pt, pts }) } + /// Change the terminal size associated with the 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)?) } diff --git a/src/command.rs b/src/command.rs index 00b51e7..8627a35 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,5 +1,6 @@ use async_process::unix::CommandExt as _; +/// Wrapper around [`async_process::Command`] pub struct Command { inner: async_process::Command, stdin: bool, @@ -12,6 +13,7 @@ pub struct Command { } impl Command { + /// See [`async_process::Command::new`] pub fn new<S: AsRef<std::ffi::OsStr>>(program: S) -> Self { Self { inner: async_process::Command::new(program), @@ -23,11 +25,13 @@ impl Command { } } + /// See [`async_process::Command::arg`] pub fn arg<S: AsRef<std::ffi::OsStr>>(&mut self, arg: S) -> &mut Self { self.inner.arg(arg); self } + /// See [`async_process::Command::args`] pub fn args<I, S>(&mut self, args: I) -> &mut Self where I: IntoIterator<Item = S>, @@ -37,6 +41,7 @@ impl Command { self } + /// See [`async_process::Command::env`] pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Self where K: AsRef<std::ffi::OsStr>, @@ -46,6 +51,7 @@ impl Command { self } + /// See [`async_process::Command::envs`] pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self where I: IntoIterator<Item = (K, V)>, @@ -56,6 +62,7 @@ impl Command { self } + /// See [`async_process::Command::env_remove`] pub fn env_remove<K: AsRef<std::ffi::OsStr>>( &mut self, key: K, @@ -64,11 +71,13 @@ impl Command { self } + /// See [`async_process::Command::env_clear`] pub fn env_clear(&mut self) -> &mut Self { self.inner.env_clear(); self } + /// See [`async_process::Command::current_dir`] pub fn current_dir<P: AsRef<std::path::Path>>( &mut self, dir: P, @@ -77,6 +86,7 @@ impl Command { self } + /// See [`async_process::Command::stdin`] pub fn stdin<T: Into<std::process::Stdio>>( &mut self, cfg: T, @@ -86,6 +96,7 @@ impl Command { self } + /// See [`async_process::Command::stdout`] pub fn stdout<T: Into<std::process::Stdio>>( &mut self, cfg: T, @@ -95,6 +106,7 @@ impl Command { self } + /// See [`async_process::Command::stderr`] pub fn stderr<T: Into<std::process::Stdio>>( &mut self, cfg: T, @@ -104,6 +116,22 @@ impl Command { self } + /// Executes the command as a child process via + /// [`async_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. + /// + /// # Errors + /// Returns an error if we fail to allocate new file descriptors for + /// attaching the pty to the child process, or if we fail to spawn the + /// child process (see the documentation for + /// [`async_process::Command::spawn`]), or if we fail to make the child a + /// session leader or set its controlling terminal. pub fn spawn( &mut self, pty: &crate::Pty, @@ -140,16 +168,20 @@ impl Command { Ok(self.inner.spawn()?) } + /// See [`async_process::unix::CommandExt::uid`] pub fn uid(&mut self, id: u32) -> &mut Self { self.inner.uid(id); self } + /// See [`async_process::unix::CommandExt::gid`] pub fn gid(&mut self, id: u32) -> &mut Self { self.inner.gid(id); self } + /// See [`async_process::unix::CommandExt::pre_exec`] + #[allow(clippy::missing_safety_doc)] pub unsafe fn pre_exec<F>(&mut self, f: F) -> &mut Self where F: FnMut() -> std::io::Result<()> + Send + Sync + 'static, @@ -158,6 +190,7 @@ impl Command { self } + /// See [`async_process::unix::CommandExt::arg0`] pub fn arg0<S>(&mut self, arg: S) -> &mut Self where S: AsRef<std::ffi::OsStr>, diff --git a/src/error.rs b/src/error.rs index 57994df..9d4c31e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,4 @@ -/// Source for errors in this crate +/// Error type for errors from this crate #[derive(Debug)] pub enum Error { /// error came from std::io::Error @@ -1,3 +1,35 @@ +//! This crate is a wrapper around [`std::process::Command`] or +//! [`async_process::Command`] which provides the ability to allocate a pty +//! and spawn new processes attached to that pty, with the pty as their +//! controlling terminal. This allows for manipulation of interactive +//! programs. +//! +//! The basic functionality looks like this: +//! +//! ```no_run +//! let mut pty = pty_process::Pty::new().unwrap(); +//! pty.resize(pty_process::Size::new(24, 80)).unwrap(); +//! let mut cmd = pty_process::Command::new("nethack"); +//! let child = cmd.spawn(&pty).unwrap(); +//! ``` +//! +//! The returned `child` is a normal instance of [`async_process::Child`] (or +//! [`std::process::Child`] for the [`blocking`](crate::blocking) variant), +//! with its `stdin`/`stdout`/`stderr` file descriptors pointing at the given +//! pty. The `pty` instance implements [`std::io::Read`] and +//! [`std::io::Write`] (or [`futures_io::AsyncRead`] and +//! [`futures_io::AsyncWrite`] for the [`blocking`] variant), and can be used +//! to communicate with the child process. The child process will also be made +//! a session leader of a new session, and the controlling terminal of that +//! session will be set to the given pty. +//! +//! # Features +//! +//! By default, only the [`blocking`](crate::blocking) APIs are available. To +//! include the asynchronous APIs, you must enable the `async` feature. See +//! the `examples` directory in the repository for examples of how to use this +//! crate with the various different asynchronous frameworks. + #![warn(clippy::cargo)] #![warn(clippy::pedantic)] #![warn(clippy::nursery)] @@ -1,9 +1,15 @@ +/// An allocated pty pub struct Pty { pt: async_io::Async<std::fs::File>, pts: std::fs::File, } impl Pty { + /// Allocate and return a new pty. + /// + /// # Errors + /// Returns an error if the pty failed to be allocated, or if we were + /// unable to put it into non-blocking mode. pub fn new() -> crate::Result<Self> { let (pt, ptsname) = crate::sys::create_pt()?; let pt = async_io::Async::new(pt)?; @@ -14,6 +20,10 @@ impl Pty { Ok(Self { pt, pts }) } + /// Change the terminal size associated with the 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)?) } |