diff options
author | Jesse Luehrs <doy@tozt.net> | 2020-07-16 03:43:20 -0400 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2020-07-16 03:43:20 -0400 |
commit | 06e90f8e12f207b65df99e93b6a6ef27c999a137 (patch) | |
tree | 6421223fab19a1e229301b2c393403352a0fbc46 | |
parent | 667878c1e186907b57b22b07b9f6d0e3ef76252a (diff) | |
download | pty-process-06e90f8e12f207b65df99e93b6a6ef27c999a137.tar.gz pty-process-06e90f8e12f207b65df99e93b6a6ef27c999a137.zip |
allow setting the terminal size
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | examples/basic.rs | 10 | ||||
-rw-r--r-- | src/command.rs | 6 | ||||
-rw-r--r-- | src/error.rs | 3 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/pty.rs | 62 |
6 files changed, 73 insertions, 11 deletions
@@ -5,5 +5,6 @@ authors = ["Jesse Luehrs <doy@tozt.net>"] edition = "2018" [dependencies] +libc = "*" nix = "0.17" thiserror = "1.0" diff --git a/examples/basic.rs b/examples/basic.rs index d3d795a..2f71bb4 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -4,9 +4,13 @@ use std::os::unix::io::AsRawFd as _; use pty_process::Command as _; fn main() { - let mut child = std::process::Command::new("cat") - // .args(&["--color=auto"]) - .spawn_pty() + let mut child = std::process::Command::new("perl") + .args(&[ + "-MTerm::ReadKey", + "-E", + "my @size = GetTerminalSize; say for @size", + ]) + .spawn_pty(Some(pty_process::Size::new(24, 80))) .unwrap(); let mut buf = [0_u8; 4096]; let pty = child.pty().as_raw_fd(); diff --git a/src/command.rs b/src/command.rs index d02df2d..926e097 100644 --- a/src/command.rs +++ b/src/command.rs @@ -4,13 +4,13 @@ use std::os::unix::io::{AsRawFd as _, FromRawFd as _}; use std::os::unix::process::CommandExt as _; pub trait Command { - fn spawn_pty(&mut self) -> Result<Child>; + fn spawn_pty(&mut self, size: Option<crate::pty::Size>) -> Result<Child>; } impl Command for std::process::Command { - fn spawn_pty(&mut self) -> Result<Child> { + fn spawn_pty(&mut self, size: Option<crate::pty::Size>) -> Result<Child> { let pty = crate::pty::Pty::new()?; - let pts = pty.pts()?; + let pts = pty.pts(size)?; let pt_fd = pty.pt().as_raw_fd(); let pts_fd = pts.as_raw_fd(); diff --git a/src/error.rs b/src/error.rs index b414cf9..97fd8a0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,6 +6,9 @@ pub enum Error { #[error("error opening pts at {0}")] OpenPts(std::path::PathBuf, #[source] std::io::Error), + #[error("error setting terminal size")] + SetTermSize(#[source] nix::Error), + #[error("error spawning subprocess")] Spawn(#[source] std::io::Error), } @@ -3,4 +3,4 @@ pub use command::Command; mod error; pub use error::{Error, Result}; mod pty; -pub use pty::Pty; +pub use pty::{Pty, Size}; @@ -1,6 +1,49 @@ use crate::error::*; -use std::os::unix::io::{FromRawFd as _, IntoRawFd as _}; +use std::os::unix::io::{AsRawFd as _, FromRawFd as _, IntoRawFd as _}; + +pub struct Size { + row: u16, + col: u16, + xpixel: u16, + ypixel: u16, +} + +impl Size { + pub fn new(row: u16, col: u16) -> Self { + Self { + row, + col, + xpixel: 0, + ypixel: 0, + } + } + + pub fn new_with_pixel( + row: u16, + col: u16, + xpixel: u16, + ypixel: u16, + ) -> Self { + Self { + row, + col, + xpixel, + ypixel, + } + } +} + +impl From<Size> for nix::pty::Winsize { + fn from(size: Size) -> Self { + Self { + ws_row: size.row, + ws_col: size.col, + ws_xpixel: size.xpixel, + ws_ypixel: size.ypixel, + } + } +} pub struct Pty { pt: std::fs::File, @@ -29,11 +72,22 @@ impl Pty { &self.pt } - pub fn pts(&self) -> Result<std::fs::File> { - Ok(std::fs::OpenOptions::new() + pub fn pts(&self, size: Option<Size>) -> Result<std::fs::File> { + let fh = std::fs::OpenOptions::new() .read(true) .write(true) .open(&self.ptsname) - .map_err(|e| Error::OpenPts(self.ptsname.clone(), e))?) + .map_err(|e| Error::OpenPts(self.ptsname.clone(), e))?; + let fd = fh.as_raw_fd(); + if let Some(size) = size { + let size = size.into(); + unsafe { + set_term_size(fd, &size as *const nix::pty::Winsize) + .map_err(Error::SetTermSize)?; + } + } + Ok(fh) } } + +nix::ioctl_write_ptr_bad!(set_term_size, libc::TIOCSWINSZ, nix::pty::Winsize); |