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_current_dir(&self) -> Option<&Path> {
90        self.cwd.as_ref().map(|cs| Path::new(cs))
91    }
92
93    pub fn spawn(
94        &mut self,
95        _default: Stdio,
96        _needs_stdin: bool,
97    ) -> io::Result<(Process, StdioPipes)> {
98        unsupported()
99    }
100}
101
102pub fn output(_cmd: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
103    unsupported()
104}
105
106impl From<AnonPipe> for Stdio {
107    fn from(pipe: AnonPipe) -> Stdio {
108        pipe.diverge()
109    }
110}
111
112impl From<io::Stdout> for Stdio {
113    fn from(_: io::Stdout) -> Stdio {
114        Stdio::ParentStdout
115    }
116}
117
118impl From<io::Stderr> for Stdio {
119    fn from(_: io::Stderr) -> Stdio {
120        Stdio::ParentStderr
121    }
122}
123
124impl From<File> for Stdio {
125    fn from(file: File) -> Stdio {
126        Stdio::InheritFile(file)
127    }
128}
129
130impl fmt::Debug for Command {
131    // show all attributes
132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133        if f.alternate() {
134            let mut debug_command = f.debug_struct("Command");
135            debug_command.field("program", &self.program).field("args", &self.args);
136            if !self.env.is_unchanged() {
137                debug_command.field("env", &self.env);
138            }
139
140            if self.cwd.is_some() {
141                debug_command.field("cwd", &self.cwd);
142            }
143
144            if self.stdin.is_some() {
145                debug_command.field("stdin", &self.stdin);
146            }
147            if self.stdout.is_some() {
148                debug_command.field("stdout", &self.stdout);
149            }
150            if self.stderr.is_some() {
151                debug_command.field("stderr", &self.stderr);
152            }
153
154            debug_command.finish()
155        } else {
156            if let Some(ref cwd) = self.cwd {
157                write!(f, "cd {cwd:?} && ")?;
158            }
159            if self.env.does_clear() {
160                write!(f, "env -i ")?;
161                // Altered env vars will be printed next, that should exactly work as expected.
162            } else {
163                // Removed env vars need the command to be wrapped in `env`.
164                let mut any_removed = false;
165                for (key, value_opt) in self.get_envs() {
166                    if value_opt.is_none() {
167                        if !any_removed {
168                            write!(f, "env ")?;
169                            any_removed = true;
170                        }
171                        write!(f, "-u {} ", key.to_string_lossy())?;
172                    }
173                }
174            }
175            // Altered env vars can just be added in front of the program.
176            for (key, value_opt) in self.get_envs() {
177                if let Some(value) = value_opt {
178                    write!(f, "{}={value:?} ", key.to_string_lossy())?;
179                }
180            }
181            if self.program != self.args[0] {
182                write!(f, "[{:?}] ", self.program)?;
183            }
184            write!(f, "{:?}", self.args[0])?;
185
186            for arg in &self.args[1..] {
187                write!(f, " {:?}", arg)?;
188            }
189            Ok(())
190        }
191    }
192}
193
194#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
195#[non_exhaustive]
196pub struct ExitStatus();
197
198impl ExitStatus {
199    pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
200        Ok(())
201    }
202
203    pub fn code(&self) -> Option<i32> {
204        Some(0)
205    }
206}
207
208impl fmt::Display for ExitStatus {
209    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210        write!(f, "<dummy exit status>")
211    }
212}
213
214pub struct ExitStatusError(!);
215
216impl Clone for ExitStatusError {
217    fn clone(&self) -> ExitStatusError {
218        self.0
219    }
220}
221
222impl Copy for ExitStatusError {}
223
224impl PartialEq for ExitStatusError {
225    fn eq(&self, _other: &ExitStatusError) -> bool {
226        self.0
227    }
228}
229
230impl Eq for ExitStatusError {}
231
232impl fmt::Debug for ExitStatusError {
233    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
234        self.0
235    }
236}
237
238impl Into<ExitStatus> for ExitStatusError {
239    fn into(self) -> ExitStatus {
240        self.0
241    }
242}
243
244impl ExitStatusError {
245    pub fn code(self) -> Option<NonZero<i32>> {
246        self.0
247    }
248}
249
250#[derive(PartialEq, Eq, Clone, Copy, Debug)]
251pub struct ExitCode(u8);
252
253impl ExitCode {
254    pub const SUCCESS: ExitCode = ExitCode(0);
255    pub const FAILURE: ExitCode = ExitCode(1);
256
257    pub fn as_i32(&self) -> i32 {
258        self.0 as i32
259    }
260}
261
262impl From<u8> for ExitCode {
263    fn from(code: u8) -> Self {
264        Self(code)
265    }
266}
267
268pub struct Process(!);
269
270impl Process {
271    pub fn id(&self) -> u32 {
272        self.0
273    }
274
275    pub fn kill(&mut self) -> io::Result<()> {
276        self.0
277    }
278
279    pub fn wait(&mut self) -> io::Result<ExitStatus> {
280        self.0
281    }
282
283    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
284        self.0
285    }
286}
287
288pub struct CommandArgs<'a> {
289    iter: crate::slice::Iter<'a, OsString>,
290}
291
292impl<'a> Iterator for CommandArgs<'a> {
293    type Item = &'a OsStr;
294    fn next(&mut self) -> Option<&'a OsStr> {
295        self.iter.next().map(|os| &**os)
296    }
297    fn size_hint(&self) -> (usize, Option<usize>) {
298        self.iter.size_hint()
299    }
300}
301
302impl<'a> ExactSizeIterator for CommandArgs<'a> {
303    fn len(&self) -> usize {
304        self.iter.len()
305    }
306    fn is_empty(&self) -> bool {
307        self.iter.is_empty()
308    }
309}
310
311impl<'a> fmt::Debug for CommandArgs<'a> {
312    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
313        f.debug_list().entries(self.iter.clone()).finish()
314    }
315}