zbus/abstractions/
process.rs

1#[cfg(not(feature = "tokio"))]
2use async_process::{unix::CommandExt, Child};
3#[cfg(target_os = "macos")]
4use std::process::Output;
5use std::{ffi::OsStr, io::Error, process::Stdio};
6#[cfg(feature = "tokio")]
7use tokio::process::Child;
8
9use crate::address::transport::Unixexec;
10
11/// A wrapper around the command API of the underlying async runtime.
12pub struct Command(
13    #[cfg(not(feature = "tokio"))] async_process::Command,
14    #[cfg(feature = "tokio")] tokio::process::Command,
15);
16
17impl Command {
18    /// Constructs a new `Command` for launching the program at path `program`.
19    pub fn new<S>(program: S) -> Self
20    where
21        S: AsRef<OsStr>,
22    {
23        #[cfg(not(feature = "tokio"))]
24        return Self(async_process::Command::new(program));
25
26        #[cfg(feature = "tokio")]
27        return Self(tokio::process::Command::new(program));
28    }
29
30    /// Constructs a new `Command` from a `unixexec` address.
31    pub fn for_unixexec(unixexec: &Unixexec) -> Self {
32        let mut command = Self::new(unixexec.path());
33        command.args(unixexec.args());
34
35        if let Some(arg0) = unixexec.arg0() {
36            command.arg0(arg0);
37        }
38
39        command
40    }
41
42    /// Sets executable argument.
43    ///
44    /// Set the first process argument, `argv[0]`, to something other than the
45    /// default executable path.
46    pub fn arg0<S>(&mut self, arg: S) -> &mut Self
47    where
48        S: AsRef<OsStr>,
49    {
50        self.0.arg0(arg);
51        self
52    }
53
54    /// Adds multiple arguments to pass to the program.
55    pub fn args<I, S>(&mut self, args: I) -> &mut Self
56    where
57        I: IntoIterator<Item = S>,
58        S: AsRef<OsStr>,
59    {
60        self.0.args(args);
61        self
62    }
63
64    /// Executes the command as a child process, waiting for it to finish and
65    /// collecting all of its output.
66    #[cfg(target_os = "macos")]
67    pub async fn output(&mut self) -> Result<Output, Error> {
68        self.0.output().await
69    }
70
71    /// Sets configuration for the child process's standard input (stdin) handle.
72    pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
73        self.0.stdin(cfg);
74        self
75    }
76
77    /// Sets configuration for the child process's standard output (stdout) handle.
78    pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
79        self.0.stdout(cfg);
80        self
81    }
82
83    /// Sets configuration for the child process's standard error (stderr) handle.
84    pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self {
85        self.0.stderr(cfg);
86        self
87    }
88
89    /// Executes the command as a child process, returning a handle to it.
90    pub fn spawn(&mut self) -> Result<Child, Error> {
91        self.0.spawn()
92    }
93}
94
95/// An asynchronous wrapper around running and getting command output
96#[cfg(target_os = "macos")]
97pub async fn run<I, S>(program: S, args: I) -> Result<Output, Error>
98where
99    I: IntoIterator<Item = S>,
100    S: AsRef<OsStr>,
101{
102    Command::new(program).args(args).output().await
103}