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