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_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 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 } else {
163 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 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}