std/sys/process/
unsupported.rs

1use 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
12////////////////////////////////////////////////////////////////////////////////
13// Command
14////////////////////////////////////////////////////////////////////////////////
15
16pub 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)] // This variant exists only for the Debug impl
35    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    // show all attributes
136    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                // Altered env vars will be printed next, that should exactly work as expected.
166            } else {
167                // Removed env vars need the command to be wrapped in `env`.
168                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            // Altered env vars can just be added in front of the program.
180            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}