about summary refs log tree commit diff
path: root/library/std/src/sys/process/unsupported.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/process/unsupported.rs')
-rw-r--r--library/std/src/sys/process/unsupported.rs322
1 files changed, 322 insertions, 0 deletions
diff --git a/library/std/src/sys/process/unsupported.rs b/library/std/src/sys/process/unsupported.rs
new file mode 100644
index 00000000000..fee81744f09
--- /dev/null
+++ b/library/std/src/sys/process/unsupported.rs
@@ -0,0 +1,322 @@
+pub use crate::ffi::OsString as EnvKey;
+use crate::ffi::{OsStr, OsString};
+use crate::num::NonZero;
+use crate::path::Path;
+use crate::sys::fs::File;
+use crate::sys::pipe::AnonPipe;
+use crate::sys::unsupported;
+use crate::sys_common::process::{CommandEnv, CommandEnvs};
+use crate::{fmt, io};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Command {
+    program: OsString,
+    args: Vec<OsString>,
+    env: CommandEnv,
+
+    cwd: Option<OsString>,
+    stdin: Option<Stdio>,
+    stdout: Option<Stdio>,
+    stderr: Option<Stdio>,
+}
+
+// passed back to std::process with the pipes connected to the child, if any
+// were requested
+pub struct StdioPipes {
+    pub stdin: Option<AnonPipe>,
+    pub stdout: Option<AnonPipe>,
+    pub stderr: Option<AnonPipe>,
+}
+
+#[derive(Debug)]
+pub enum Stdio {
+    Inherit,
+    Null,
+    MakePipe,
+    ParentStdout,
+    ParentStderr,
+    #[allow(dead_code)] // This variant exists only for the Debug impl
+    InheritFile(File),
+}
+
+impl Command {
+    pub fn new(program: &OsStr) -> Command {
+        Command {
+            program: program.to_owned(),
+            args: vec![program.to_owned()],
+            env: Default::default(),
+            cwd: None,
+            stdin: None,
+            stdout: None,
+            stderr: None,
+        }
+    }
+
+    pub fn arg(&mut self, arg: &OsStr) {
+        self.args.push(arg.to_owned());
+    }
+
+    pub fn env_mut(&mut self) -> &mut CommandEnv {
+        &mut self.env
+    }
+
+    pub fn cwd(&mut self, dir: &OsStr) {
+        self.cwd = Some(dir.to_owned());
+    }
+
+    pub fn stdin(&mut self, stdin: Stdio) {
+        self.stdin = Some(stdin);
+    }
+
+    pub fn stdout(&mut self, stdout: Stdio) {
+        self.stdout = Some(stdout);
+    }
+
+    pub fn stderr(&mut self, stderr: Stdio) {
+        self.stderr = Some(stderr);
+    }
+
+    pub fn get_program(&self) -> &OsStr {
+        &self.program
+    }
+
+    pub fn get_args(&self) -> CommandArgs<'_> {
+        let mut iter = self.args.iter();
+        iter.next();
+        CommandArgs { iter }
+    }
+
+    pub fn get_envs(&self) -> CommandEnvs<'_> {
+        self.env.iter()
+    }
+
+    pub fn get_current_dir(&self) -> Option<&Path> {
+        self.cwd.as_ref().map(|cs| Path::new(cs))
+    }
+
+    pub fn spawn(
+        &mut self,
+        _default: Stdio,
+        _needs_stdin: bool,
+    ) -> io::Result<(Process, StdioPipes)> {
+        unsupported()
+    }
+
+    pub fn output(&mut self) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
+        unsupported()
+    }
+}
+
+impl From<AnonPipe> for Stdio {
+    fn from(pipe: AnonPipe) -> Stdio {
+        pipe.diverge()
+    }
+}
+
+impl From<io::Stdout> for Stdio {
+    fn from(_: io::Stdout) -> Stdio {
+        Stdio::ParentStdout
+    }
+}
+
+impl From<io::Stderr> for Stdio {
+    fn from(_: io::Stderr) -> Stdio {
+        Stdio::ParentStderr
+    }
+}
+
+impl From<File> for Stdio {
+    fn from(file: File) -> Stdio {
+        Stdio::InheritFile(file)
+    }
+}
+
+impl fmt::Debug for Command {
+    // show all attributes
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if f.alternate() {
+            let mut debug_command = f.debug_struct("Command");
+            debug_command.field("program", &self.program).field("args", &self.args);
+            if !self.env.is_unchanged() {
+                debug_command.field("env", &self.env);
+            }
+
+            if self.cwd.is_some() {
+                debug_command.field("cwd", &self.cwd);
+            }
+
+            if self.stdin.is_some() {
+                debug_command.field("stdin", &self.stdin);
+            }
+            if self.stdout.is_some() {
+                debug_command.field("stdout", &self.stdout);
+            }
+            if self.stderr.is_some() {
+                debug_command.field("stderr", &self.stderr);
+            }
+
+            debug_command.finish()
+        } else {
+            if let Some(ref cwd) = self.cwd {
+                write!(f, "cd {cwd:?} && ")?;
+            }
+            if self.env.does_clear() {
+                write!(f, "env -i ")?;
+                // Altered env vars will be printed next, that should exactly work as expected.
+            } else {
+                // Removed env vars need the command to be wrapped in `env`.
+                let mut any_removed = false;
+                for (key, value_opt) in self.get_envs() {
+                    if value_opt.is_none() {
+                        if !any_removed {
+                            write!(f, "env ")?;
+                            any_removed = true;
+                        }
+                        write!(f, "-u {} ", key.to_string_lossy())?;
+                    }
+                }
+            }
+            // Altered env vars can just be added in front of the program.
+            for (key, value_opt) in self.get_envs() {
+                if let Some(value) = value_opt {
+                    write!(f, "{}={value:?} ", key.to_string_lossy())?;
+                }
+            }
+            if self.program != self.args[0] {
+                write!(f, "[{:?}] ", self.program)?;
+            }
+            write!(f, "{:?}", self.args[0])?;
+
+            for arg in &self.args[1..] {
+                write!(f, " {:?}", arg)?;
+            }
+            Ok(())
+        }
+    }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
+#[non_exhaustive]
+pub struct ExitStatus();
+
+impl ExitStatus {
+    pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
+        Ok(())
+    }
+
+    pub fn code(&self) -> Option<i32> {
+        Some(0)
+    }
+}
+
+impl fmt::Display for ExitStatus {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "<dummy exit status>")
+    }
+}
+
+pub struct ExitStatusError(!);
+
+impl Clone for ExitStatusError {
+    fn clone(&self) -> ExitStatusError {
+        self.0
+    }
+}
+
+impl Copy for ExitStatusError {}
+
+impl PartialEq for ExitStatusError {
+    fn eq(&self, _other: &ExitStatusError) -> bool {
+        self.0
+    }
+}
+
+impl Eq for ExitStatusError {}
+
+impl fmt::Debug for ExitStatusError {
+    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0
+    }
+}
+
+impl Into<ExitStatus> for ExitStatusError {
+    fn into(self) -> ExitStatus {
+        self.0
+    }
+}
+
+impl ExitStatusError {
+    pub fn code(self) -> Option<NonZero<i32>> {
+        self.0
+    }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitCode(u8);
+
+impl ExitCode {
+    pub const SUCCESS: ExitCode = ExitCode(0);
+    pub const FAILURE: ExitCode = ExitCode(1);
+
+    pub fn as_i32(&self) -> i32 {
+        self.0 as i32
+    }
+}
+
+impl From<u8> for ExitCode {
+    fn from(code: u8) -> Self {
+        Self(code)
+    }
+}
+
+pub struct Process(!);
+
+impl Process {
+    pub fn id(&self) -> u32 {
+        self.0
+    }
+
+    pub fn kill(&mut self) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn wait(&mut self) -> io::Result<ExitStatus> {
+        self.0
+    }
+
+    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+        self.0
+    }
+}
+
+pub struct CommandArgs<'a> {
+    iter: crate::slice::Iter<'a, OsString>,
+}
+
+impl<'a> Iterator for CommandArgs<'a> {
+    type Item = &'a OsStr;
+    fn next(&mut self) -> Option<&'a OsStr> {
+        self.iter.next().map(|os| &**os)
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.iter.size_hint()
+    }
+}
+
+impl<'a> ExactSizeIterator for CommandArgs<'a> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
+
+impl<'a> fmt::Debug for CommandArgs<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_list().entries(self.iter.clone()).finish()
+    }
+}