aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-07-16 03:43:20 -0400
committerJesse Luehrs <doy@tozt.net>2020-07-16 03:43:20 -0400
commit06e90f8e12f207b65df99e93b6a6ef27c999a137 (patch)
tree6421223fab19a1e229301b2c393403352a0fbc46
parent667878c1e186907b57b22b07b9f6d0e3ef76252a (diff)
downloadpty-process-06e90f8e12f207b65df99e93b6a6ef27c999a137.tar.gz
pty-process-06e90f8e12f207b65df99e93b6a6ef27c999a137.zip
allow setting the terminal size
-rw-r--r--Cargo.toml1
-rw-r--r--examples/basic.rs10
-rw-r--r--src/command.rs6
-rw-r--r--src/error.rs3
-rw-r--r--src/lib.rs2
-rw-r--r--src/pty.rs62
6 files changed, 73 insertions, 11 deletions
diff --git a/Cargo.toml b/Cargo.toml
index a71c256..d1673b2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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),
}
diff --git a/src/lib.rs b/src/lib.rs
index 2e6d894..bcf5ce9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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};
diff --git a/src/pty.rs b/src/pty.rs
index d76aa6b..a557f56 100644
--- a/src/pty.rs
+++ b/src/pty.rs
@@ -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);