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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
//! Process control: detached spawning and console-window suppression.
use OsStr;
use Command;
/// Configure `cmd` so the spawned child detaches into its own process group,
/// surviving the terminal that launched it.
///
/// On Unix this uses the safe, stable `Command::process_group(0)`; on non-Unix
/// platforms it is a no-op. Call this before `cmd.spawn()`.
/// Configure `cmd` so the spawned child gets no console window.
///
/// On Windows a console application is given a console. A child of a process
/// that has one shares it and draws nothing; a child of a process that has
/// none, such as the daemon started from Explorer, from a service, or from a UI
/// console, gets a brand new window on the interactive desktop. Agent tooling
/// spawns `cmd.exe` many times per run, so without this the desktop fills with
/// flashing consoles (issue #228). Elsewhere this is a no-op: no other platform
/// hands a child a window.
///
/// Apply it to a child whose stdout/stderr are already piped or nulled, which
/// is what every caller in this workspace does. Do **not** apply it to a child
/// meant to share the user's terminal: the editor launched by `lev run` needs
/// that console to draw in, and starting `vim` without one just breaks it.
///
/// One sharp edge worth knowing: `Command::creation_flags` *assigns* the flag
/// word rather than OR-ing into it, so two callers setting different flags on
/// one command would silently clobber each other. This function is deliberately
/// the only writer of creation flags in the workspace. Add any future flag
/// here, alongside `CREATE_NO_WINDOW`, rather than at a call site.
/// A [`Command`] for a child that must not take a console window.
///
/// **This is where the decision is made.** Hiding used to be a second call the
/// caller made after building the command, at seven sites across five crates,
/// and a new spawn site that forgot it looked exactly like one that did not
/// need it. Making it part of construction means the only way to get a child
/// process is to have already answered the question.
///
/// The counterpart is [`terminal_command`], for the single child that is meant
/// to be seen. There is no third option on purpose: a `Command::new` outside
/// this module is rejected by `.sgrules/no-raw-command-new.yml`.
/// The tokio twin of [`child_command`].
///
/// `tokio::process::Command` wraps a `std::process::Command`, so `as_std_mut`
/// reaches the one the flag is written on and both flavours share a single
/// implementation rather than a second copy of the `#[cfg]`.
/// A [`Command`] for a child that *must* inherit the user's terminal.
///
/// The editor `lev run` opens is the only one: it draws in the terminal it
/// inherits, and starting `vim` without a console leaves it nowhere to draw and
/// nothing to read from. Named rather than reached for with a bare
/// `Command::new` so the exception is a decision in the source instead of an
/// omission, and so the lint has something to point at.
/// SIGKILL every process in the group led by `pgid` (a no-op on platforms
/// without process groups).
///
/// Killing a child shell is not enough to stop what it started: the shell's own
/// children are reparented to init and keep running. A cancelled agent's
/// `sleep 400` outliving the run that started it is exactly that. Spawning the
/// shell into its own group (via [`configure_detached`]) and signalling the
/// group tears down the whole tree.
///
/// Errors are the ordinary case (the group already exited) and are the caller's
/// to ignore.
/// The calling user's numeric id.
///
/// Used to address a per-user service domain (`launchctl bootstrap gui/<uid>`).
/// Returns `0` on platforms with no POSIX uid, where no such domain exists.
/// The effective uid of the process on the other end of a connected
/// Unix-domain socket.
///
/// The kernel's answer, not the peer's claim, so it cannot be spoofed by
/// anything the peer sends. This is what makes the daemon's control socket
/// safe: file permissions on a Unix socket are advisory on macOS and the BSDs
/// (the mode is not consulted on `connect`), so the mode alone was never the
/// guarantee it was documented to be.
///
/// `None` when the platform cannot report it - which the caller must treat as
/// "refuse", since an unidentifiable peer is not an authorized one.
///
/// Unix-only: on Windows the control channel is not a Unix socket, so there is
/// no fd to interrogate and no caller for this.