1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Pseudo-terminal (PTY) launch backend for the opt-in
//! [`Command::use_pty`](crate::Command::use_pty) mode.
//!
//! A PTY replaces the three independent stdio pipes with a **single master
//! fd/handle** carrying the child's *merged* stdout+stderr, plus an input side
//! for stdin — `openpty` on Unix, `CreatePseudoConsole` (ConPTY) on Windows. It
//! exists so tools that demand a controlling terminal (an `isatty()`-gated
//! agentic CLI, an `ssh`/`sudo` password prompt) work; it is a *minimal*
//! single-master-fd mode, not a terminal emulator.
//!
//! # Containment is unchanged (K-032)
//!
//! The PTY spawn does **not** fork a parallel containment structure. On Unix it
//! wires the pty **slave** as the child's stdio and then spawns through the very
//! same per-platform [`Job::spawn`](crate::sys::Job) path (cgroup / process-group
//! join in `pre_exec`), so the child lands in the same job as any other. On
//! Windows the ConPTY child is created suspended, `AssignProcessToJobObject`'d to
//! the same Job Object, then resumed — identical containment to
//! [`Job::spawn`](crate::sys::Job). Kill-on-drop, timeouts, and cancellation are
//! therefore unaffected; only the I/O wiring changes.
//!
//! Exactly one platform module (`unix.rs` / `windows.rs`) compiles per target,
//! each exposing the same [`PtyChild`] shape and a `spawn_pty` entry point.
// `io` is used only by the Unix `EofOnEio` adapter below.
use io;
// The platform child-lifecycle handle and the platform spawn entry point. Only
// one `imp` compiles per target, so this re-export resolves to the Unix (tokio
// `Child` + `openpty` master) or Windows (raw `CreateProcessW` + ConPTY) form.
pub use ;
/// The pseudo-terminal window size a PTY spawn falls back to when no explicit
/// [`Command::pty_size`](crate::Command::pty_size) was requested — `(cols, rows)`
/// = 80×24, the historical hard-coded default and the conventional terminal
/// dimensions a size-querying child expects. Shared by both platform backends so
/// the "unset → 80×24" rule lives in exactly one place.
pub const DEFAULT_PTY_SIZE: = ;
/// A boxed async reader over the PTY master's **merged** output (stdout+stderr).
/// Flows through the same [`pump_lines_core`](crate::pump) machinery a real
/// child's stdout does — the pump is generic over [`AsyncRead`](tokio::io::AsyncRead).
/// `+ Sync` keeps [`RunningProcess`](crate::RunningProcess) `Sync` when a PTY
/// backend stores it (see [`OutputReader`](crate::running)).
pub type PtyReader = ;
/// A boxed async writer over the PTY master's input side (the child's stdin).
/// `+ Sync` for the same auto-trait-preserving reason as [`PtyReader`].
pub type PtyWriter = ;
/// The exit status of a PTY child, in the platform-agnostic shape the
/// [`RunningProcess`](crate::RunningProcess) reap paths consume: an exit code,
/// plus (Unix only) a terminating signal number — mirroring
/// [`std::process::ExitStatus`]'s `code()` / `signal()`.
pub
/// Everything a PTY spawn hands back to the launch path: the child-lifecycle
/// handle ([`PtyChild`]), the merged output reader, the stdin writer, and the pid.
/// The master fd/handle (and, on Windows, the pseudoconsole and its pipes) are
/// owned by these fields and closed when they drop — the reader/writer own the
/// I/O ends, [`PtyChild`] owns the process handle (and the ConPTY handle on
/// Windows).
pub
/// Map an `EIO` read error on a Unix pty master to a clean end-of-stream.
///
/// When the slave side of a pty closes (the child exits), a subsequent `read` on
/// the master returns `EIO` on Linux rather than a `0`-length EOF read. The pump
/// treats a read error as an *incomplete capture* ([`ErrorReason::Io`](crate::ErrorReason::Io));
/// wrapping the master reader in this adapter turns that expected end-of-session
/// `EIO` into a normal EOF so a PTY run reads exactly like a pipe one at close.
/// A genuine mid-stream error of any other kind is passed through unchanged.
pub ;