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