mod buffer;
mod child;
mod pty;
mod signals;
use std::ffi::OsStr;
pub use buffer::PtyBuffer;
pub use child::{UnixPtyChild, spawn_child};
pub use pty::{UnixPtyMaster, open_slave};
pub use signals::{
PtySignalEvent, SignalHandle, is_sigchld, is_sigwinch, on_window_change, sigchld, sigwinch,
start_signal_handler,
};
use crate::config::PtyConfig;
use crate::error::Result;
use crate::traits::PtySystem;
#[derive(Debug, Clone, Copy, Default)]
pub struct UnixPtySystem;
impl PtySystem for UnixPtySystem {
type Master = UnixPtyMaster;
type Child = UnixPtyChild;
async fn spawn<S, I>(
program: S,
args: I,
config: &PtyConfig,
) -> Result<(Self::Master, Self::Child)>
where
S: AsRef<OsStr> + Send,
I: IntoIterator + Send,
I::Item: AsRef<OsStr>,
{
let (master, slave_path) = UnixPtyMaster::open()?;
let window_size = config.window_size.into();
master.set_window_size(window_size)?;
let slave_fd = open_slave(&slave_path)?;
let child = spawn_child(slave_fd, program, args, config).await?;
Ok((master, child))
}
}
pub type NativePtySystem = UnixPtySystem;
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn spawn_shell() {
let config = PtyConfig::default();
let result = UnixPtySystem::spawn_shell(&config).await;
if let Ok((mut master, mut child)) = result {
assert!(master.is_open());
assert!(child.is_running());
child.kill().ok();
master.close().ok();
}
}
#[tokio::test]
async fn spawn_echo() {
let config = PtyConfig::default();
let result = UnixPtySystem::spawn("echo", ["hello"], &config).await;
if let Ok((mut master, mut child)) = result {
let status = child.wait().await;
assert!(status.is_ok());
master.close().ok();
}
}
}