1mod buffer;
28mod child;
29mod pty;
30mod signals;
31
32use std::ffi::OsStr;
33
34pub use buffer::PtyBuffer;
35pub use child::{UnixPtyChild, spawn_child};
36pub use pty::{UnixPtyMaster, open_slave};
37pub use signals::{
38 PtySignalEvent, SignalHandle, is_sigchld, is_sigwinch, on_window_change, sigchld, sigwinch,
39 start_signal_handler,
40};
41
42use crate::config::PtyConfig;
43use crate::error::Result;
44use crate::traits::PtySystem;
45
46#[derive(Debug, Clone, Copy, Default)]
50pub struct UnixPtySystem;
51
52impl PtySystem for UnixPtySystem {
53 type Master = UnixPtyMaster;
54 type Child = UnixPtyChild;
55
56 async fn spawn<S, I>(
57 program: S,
58 args: I,
59 config: &PtyConfig,
60 ) -> Result<(Self::Master, Self::Child)>
61 where
62 S: AsRef<OsStr> + Send,
63 I: IntoIterator + Send,
64 I::Item: AsRef<OsStr>,
65 {
66 let (master, slave_path) = UnixPtyMaster::open()?;
68
69 let window_size = config.window_size.into();
71 master.set_window_size(window_size)?;
72
73 let slave_fd = open_slave(&slave_path)?;
75
76 let child = spawn_child(slave_fd, program, args, config).await?;
78
79 Ok((master, child))
80 }
81}
82
83pub type NativePtySystem = UnixPtySystem;
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[tokio::test]
91 async fn spawn_shell() {
92 let config = PtyConfig::default();
93 let result = UnixPtySystem::spawn_shell(&config).await;
94
95 if let Ok((mut master, mut child)) = result {
97 assert!(master.is_open());
98 assert!(child.is_running());
99
100 child.kill().ok();
102 master.close().ok();
103 }
104 }
105
106 #[tokio::test]
107 async fn spawn_echo() {
108 let config = PtyConfig::default();
109 let result = UnixPtySystem::spawn("echo", ["hello"], &config).await;
110
111 if let Ok((mut master, mut child)) = result {
112 let status = child.wait().await;
114 assert!(status.is_ok());
115
116 master.close().ok();
117 }
118 }
119}