std/sys/process/
unsupported.rs1use super::env::{CommandEnv, CommandEnvs};
2pub use crate::ffi::OsString as EnvKey;
3use crate::ffi::{OsStr, OsString};
4use crate::num::NonZero;
5use crate::path::Path;
6use crate::process::StdioPipes;
7use crate::sys::fs::File;
8use crate::sys::pipe::AnonPipe;
9use crate::sys::unsupported;
10use crate::{fmt, io};
11
12pub struct Command {
17 program: OsString,
18 args: Vec<OsString>,
19 env: CommandEnv,
20
21 cwd: Option<OsString>,
22 stdin: Option<Stdio>,
23 stdout: Option<Stdio>,
24 stderr: Option<Stdio>,
25}
26
27#[derive(Debug)]
28pub enum Stdio {
29 Inherit,
30 Null,
31 MakePipe,
32 ParentStdout,
33 ParentStderr,
34 #[allow(dead_code)] InheritFile(File),
36}
37
38impl Command {
39 pub fn new(program: &OsStr) -> Command {
40 Command {
41 program: program.to_owned(),
42 args: vec![program.to_owned()],
43 env: Default::default(),
44 cwd: None,
45 stdin: None,
46 stdout: None,
47 stderr: None,
48 }
49 }
50
51 pub fn arg(&mut self, arg: &OsStr) {
52 self.args.push(arg.to_owned());
53 }
54
55 pub fn env_mut(&mut self) -> &mut CommandEnv {
56 &mut self.env
57 }
58
59 pub fn cwd(&mut self, dir: &OsStr) {
60 self.cwd = Some(dir.to_owned());
61 }
62
63 pub fn stdin(&mut self, stdin: Stdio) {
64 self.stdin = Some(stdin);
65 }
66
67 pub fn stdout(&mut self, stdout: Stdio) {
68 self.stdout = Some(stdout);
69 }
70
71 pub fn stderr(&mut self, stderr: Stdio) {
72 self.stderr = Some(stderr);
73 }
74
75 pub fn get_program(&self) -> &OsStr {
76 &self.program
77 }
78
79 pub fn get_args(&self) -> CommandArgs<'_> {
80 let mut iter = self.args.iter();
81 iter.next();
82 CommandArgs { iter }
83 }
84
85 pub fn get_envs(&self) -> CommandEnvs<'_> {
86 self.env.iter()
87 }
88
89 pub fn get_env_clear(&self) -> bool {
90 self.env.does_clear()
91 }
92
93 pub fn get_current_dir(&self) -> Option<&Path> {
94 self.cwd.as_ref().map(|cs| Path::new(cs))
95 }
96
97 pub fn spawn(
98 &mut self,
99 _default: Stdio,
100 _needs_stdin: bool,
101 ) -> io::Result<(Process, StdioPipes)> {
102 unsupported()
103 }
104}
105
106pub fn output(_cmd: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
107 unsupported()
108}
109
110impl From<AnonPipe> for Stdio {
111 fn from(pipe: AnonPipe) -> Stdio {
112 pipe.diverge()
113 }
114}
115
116impl From<io::Stdout> for Stdio {
117 fn from(_: io::Stdout) -> Stdio {
118 Stdio::ParentStdout
119 }
120}
121
122impl From<io::Stderr> for Stdio {
123 fn from(_: io::Stderr) -> Stdio {
124 Stdio::ParentStderr
125 }
126}
127
128impl From<File> for Stdio {
129 fn from(file: File) -> Stdio {
130 Stdio::InheritFile(file)
131 }
132}
133
134impl fmt::Debug for Command {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 if f.alternate() {
138 let mut debug_command = f.debug_struct("Command");
139 debug_command.field("program", &self.program).field("args", &self.args);
140 if !self.env.is_unchanged() {
141 debug_command.field("env", &self.env);
142 }
143
144 if self.cwd.is_some() {
145 debug_command.field("cwd", &self.cwd);
146 }
147
148 if self.stdin.is_some() {
149 debug_command.field("stdin", &self.stdin);
150 }
151 if self.stdout.is_some() {
152 debug_command.field("stdout", &self.stdout);
153 }
154 if self.stderr.is_some() {
155 debug_command.field("stderr", &self.stderr);
156 }
157
158 debug_command.finish()
159 } else {
160 if let Some(ref cwd) = self.cwd {
161 write!(f, "cd {cwd:?} && ")?;
162 }
163 if self.env.does_clear() {
164 write!(f, "env -i ")?;
165 } else {
167 let mut any_removed = false;
169 for (key, value_opt) in self.get_envs() {
170 if value_opt.is_none() {
171 if !any_removed {
172 write!(f, "env ")?;
173 any_removed = true;
174 }
175 write!(f, "-u {} ", key.to_string_lossy())?;
176 }
177 }
178 }
179 for (key, value_opt) in self.get_envs() {
181 if let Some(value) = value_opt {
182 write!(f, "{}={value:?} ", key.to_string_lossy())?;
183 }
184 }
185 if self.program != self.args[0] {
186 write!(f, "[{:?}] ", self.program)?;
187 }
188 write!(f, "{:?}", self.args[0])?;
189
190 for arg in &self.args[1..] {
191 write!(f, " {:?}", arg)?;
192 }
193 Ok(())
194 }
195 }
196}
197
198#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
199#[non_exhaustive]
200pub struct ExitStatus();
201
202impl ExitStatus {
203 pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
204 Ok(())
205 }
206
207 pub fn code(&self) -> Option<i32> {
208 Some(0)
209 }
210}
211
212impl fmt::Display for ExitStatus {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 write!(f, "<dummy exit status>")
215 }
216}
217
218pub struct ExitStatusError(!);
219
220impl Clone for ExitStatusError {
221 fn clone(&self) -> ExitStatusError {
222 self.0
223 }
224}
225
226impl Copy for ExitStatusError {}
227
228impl PartialEq for ExitStatusError {
229 fn eq(&self, _other: &ExitStatusError) -> bool {
230 self.0
231 }
232}
233
234impl Eq for ExitStatusError {}
235
236impl fmt::Debug for ExitStatusError {
237 fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
238 self.0
239 }
240}
241
242impl Into<ExitStatus> for ExitStatusError {
243 fn into(self) -> ExitStatus {
244 self.0
245 }
246}
247
248impl ExitStatusError {
249 pub fn code(self) -> Option<NonZero<i32>> {
250 self.0
251 }
252}
253
254#[derive(PartialEq, Eq, Clone, Copy, Debug)]
255pub struct ExitCode(u8);
256
257impl ExitCode {
258 pub const SUCCESS: ExitCode = ExitCode(0);
259 pub const FAILURE: ExitCode = ExitCode(1);
260
261 pub fn as_i32(&self) -> i32 {
262 self.0 as i32
263 }
264}
265
266impl From<u8> for ExitCode {
267 fn from(code: u8) -> Self {
268 Self(code)
269 }
270}
271
272pub struct Process(!);
273
274impl Process {
275 pub fn id(&self) -> u32 {
276 self.0
277 }
278
279 pub fn kill(&mut self) -> io::Result<()> {
280 self.0
281 }
282
283 pub fn wait(&mut self) -> io::Result<ExitStatus> {
284 self.0
285 }
286
287 pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
288 self.0
289 }
290}
291
292pub struct CommandArgs<'a> {
293 iter: crate::slice::Iter<'a, OsString>,
294}
295
296impl<'a> Iterator for CommandArgs<'a> {
297 type Item = &'a OsStr;
298 fn next(&mut self) -> Option<&'a OsStr> {
299 self.iter.next().map(|os| &**os)
300 }
301 fn size_hint(&self) -> (usize, Option<usize>) {
302 self.iter.size_hint()
303 }
304}
305
306impl<'a> ExactSizeIterator for CommandArgs<'a> {
307 fn len(&self) -> usize {
308 self.iter.len()
309 }
310 fn is_empty(&self) -> bool {
311 self.iter.is_empty()
312 }
313}
314
315impl<'a> fmt::Debug for CommandArgs<'a> {
316 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
317 f.debug_list().entries(self.iter.clone()).finish()
318 }
319}