2016-09-29 22:10:42 +00:00
|
|
|
|
//! A module for working with processes.
|
|
|
|
|
//!
|
2017-10-16 02:45:07 +00:00
|
|
|
|
//! This module is mostly concerned with spawning and interacting with child
|
|
|
|
|
//! processes, but it also provides [`abort`] and [`exit`] for terminating the
|
|
|
|
|
//! current process.
|
2016-09-29 22:10:42 +00:00
|
|
|
|
//!
|
2017-10-16 02:45:07 +00:00
|
|
|
|
//! # Spawning a process
|
2016-09-29 22:10:42 +00:00
|
|
|
|
//!
|
2017-10-16 02:45:07 +00:00
|
|
|
|
//! The [`Command`] struct is used to configure and spawn processes:
|
2016-09-29 22:10:42 +00:00
|
|
|
|
//!
|
2019-03-14 04:53:44 +00:00
|
|
|
|
//! ```no_run
|
2016-09-29 22:10:42 +00:00
|
|
|
|
//! use std::process::Command;
|
|
|
|
|
//!
|
2017-10-16 02:45:07 +00:00
|
|
|
|
//! let output = Command::new("echo")
|
|
|
|
|
//! .arg("Hello world")
|
|
|
|
|
//! .output()
|
|
|
|
|
//! .expect("Failed to execute command");
|
2016-09-29 22:10:42 +00:00
|
|
|
|
//!
|
2017-10-16 02:45:07 +00:00
|
|
|
|
//! assert_eq!(b"Hello world\n", output.stdout.as_slice());
|
2016-09-29 22:10:42 +00:00
|
|
|
|
//! ```
|
2017-02-27 06:01:47 +00:00
|
|
|
|
//!
|
2017-10-16 02:45:07 +00:00
|
|
|
|
//! Several methods on [`Command`], such as [`spawn`] or [`output`], can be used
|
|
|
|
|
//! to spawn a process. In particular, [`output`] spawns the child process and
|
|
|
|
|
//! waits until the process terminates, while [`spawn`] will return a [`Child`]
|
|
|
|
|
//! that represents the spawned child process.
|
|
|
|
|
//!
|
|
|
|
|
//! # Handling I/O
|
|
|
|
|
//!
|
2017-10-18 00:49:02 +00:00
|
|
|
|
//! The [`stdout`], [`stdin`], and [`stderr`] of a child process can be
|
|
|
|
|
//! configured by passing an [`Stdio`] to the corresponding method on
|
|
|
|
|
//! [`Command`]. Once spawned, they can be accessed from the [`Child`]. For
|
|
|
|
|
//! example, piping output from one command into another command can be done
|
|
|
|
|
//! like so:
|
2017-10-14 06:38:55 +00:00
|
|
|
|
//!
|
2017-10-29 03:24:49 +00:00
|
|
|
|
//! ```no_run
|
2017-10-14 06:38:55 +00:00
|
|
|
|
//! use std::process::{Command, Stdio};
|
2016-09-29 22:10:42 +00:00
|
|
|
|
//!
|
2017-10-14 06:38:55 +00:00
|
|
|
|
//! // stdout must be configured with `Stdio::piped` in order to use
|
|
|
|
|
//! // `echo_child.stdout`
|
|
|
|
|
//! let echo_child = Command::new("echo")
|
|
|
|
|
//! .arg("Oh no, a tpyo!")
|
|
|
|
|
//! .stdout(Stdio::piped())
|
|
|
|
|
//! .spawn()
|
|
|
|
|
//! .expect("Failed to start echo process");
|
|
|
|
|
//!
|
|
|
|
|
//! // Note that `echo_child` is moved here, but we won't be needing
|
|
|
|
|
//! // `echo_child` anymore
|
|
|
|
|
//! let echo_out = echo_child.stdout.expect("Failed to open echo stdout");
|
|
|
|
|
//!
|
|
|
|
|
//! let mut sed_child = Command::new("sed")
|
|
|
|
|
//! .arg("s/tpyo/typo/")
|
|
|
|
|
//! .stdin(Stdio::from(echo_out))
|
|
|
|
|
//! .stdout(Stdio::piped())
|
|
|
|
|
//! .spawn()
|
|
|
|
|
//! .expect("Failed to start sed process");
|
2016-09-29 22:10:42 +00:00
|
|
|
|
//!
|
2017-10-14 06:38:55 +00:00
|
|
|
|
//! let output = sed_child.wait_with_output().expect("Failed to wait on sed");
|
|
|
|
|
//! assert_eq!(b"Oh no, a typo!\n", output.stdout.as_slice());
|
2016-09-29 22:10:42 +00:00
|
|
|
|
//! ```
|
2017-02-27 06:01:47 +00:00
|
|
|
|
//!
|
2018-01-04 21:01:57 +00:00
|
|
|
|
//! Note that [`ChildStderr`] and [`ChildStdout`] implement [`Read`] and
|
|
|
|
|
//! [`ChildStdin`] implements [`Write`]:
|
2017-02-27 06:01:47 +00:00
|
|
|
|
//!
|
|
|
|
|
//! ```no_run
|
|
|
|
|
//! use std::process::{Command, Stdio};
|
|
|
|
|
//! use std::io::Write;
|
|
|
|
|
//!
|
|
|
|
|
//! let mut child = Command::new("/bin/cat")
|
|
|
|
|
//! .stdin(Stdio::piped())
|
|
|
|
|
//! .stdout(Stdio::piped())
|
|
|
|
|
//! .spawn()
|
|
|
|
|
//! .expect("failed to execute child");
|
|
|
|
|
//!
|
2021-03-09 18:30:39 +00:00
|
|
|
|
//! // If the child process fills its stdout buffer, it may end up
|
|
|
|
|
//! // waiting until the parent reads the stdout, and not be able to
|
|
|
|
|
//! // read stdin in the meantime, causing a deadlock.
|
|
|
|
|
//! // Writing from another thread ensures that stdout is being read
|
|
|
|
|
//! // at the same time, avoiding the problem.
|
|
|
|
|
//! let mut stdin = child.stdin.take().expect("failed to get stdin");
|
|
|
|
|
//! std::thread::spawn(move || {
|
2017-02-27 06:01:47 +00:00
|
|
|
|
//! stdin.write_all(b"test").expect("failed to write to stdin");
|
2021-03-09 18:30:39 +00:00
|
|
|
|
//! });
|
2017-02-27 06:01:47 +00:00
|
|
|
|
//!
|
|
|
|
|
//! let output = child
|
|
|
|
|
//! .wait_with_output()
|
|
|
|
|
//! .expect("failed to wait on child");
|
|
|
|
|
//!
|
|
|
|
|
//! assert_eq!(b"test", output.stdout.as_slice());
|
|
|
|
|
//! ```
|
2017-10-14 06:38:55 +00:00
|
|
|
|
//!
|
2020-08-12 01:02:24 +00:00
|
|
|
|
//! [`spawn`]: Command::spawn
|
|
|
|
|
//! [`output`]: Command::output
|
2017-10-16 02:45:07 +00:00
|
|
|
|
//!
|
2020-08-12 01:02:24 +00:00
|
|
|
|
//! [`stdout`]: Command::stdout
|
|
|
|
|
//! [`stdin`]: Command::stdin
|
|
|
|
|
//! [`stderr`]: Command::stderr
|
2017-10-16 02:45:07 +00:00
|
|
|
|
//!
|
2020-08-12 01:02:24 +00:00
|
|
|
|
//! [`Write`]: io::Write
|
|
|
|
|
//! [`Read`]: io::Read
|
2015-02-06 17:42:57 +00:00
|
|
|
|
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#![stable(feature = "process", since = "1.0.0")]
|
2020-07-02 07:16:04 +00:00
|
|
|
|
#![deny(unsafe_op_in_unsafe_fn)]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
|
2020-10-27 13:10:31 +00:00
|
|
|
|
#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
|
2020-08-27 13:45:01 +00:00
|
|
|
|
mod tests;
|
|
|
|
|
|
2019-02-10 19:23:21 +00:00
|
|
|
|
use crate::io::prelude::*;
|
|
|
|
|
|
2021-09-02 20:03:41 +00:00
|
|
|
|
use crate::convert::Infallible;
|
2019-02-10 19:23:21 +00:00
|
|
|
|
use crate::ffi::OsStr;
|
|
|
|
|
use crate::fmt;
|
|
|
|
|
use crate::fs;
|
2021-01-18 06:28:18 +00:00
|
|
|
|
use crate::io::{self, IoSlice, IoSliceMut};
|
2021-03-03 12:17:16 +00:00
|
|
|
|
use crate::num::NonZeroI32;
|
2019-02-10 19:23:21 +00:00
|
|
|
|
use crate::path::Path;
|
|
|
|
|
use crate::str;
|
|
|
|
|
use crate::sys::pipe::{read2, AnonPipe};
|
|
|
|
|
use crate::sys::process as imp;
|
2021-10-05 22:09:11 +00:00
|
|
|
|
#[stable(feature = "command_access", since = "1.57.0")]
|
2020-09-21 18:32:06 +00:00
|
|
|
|
pub use crate::sys_common::process::CommandEnvs;
|
2019-02-10 19:23:21 +00:00
|
|
|
|
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
2015-02-06 17:42:57 +00:00
|
|
|
|
|
|
|
|
|
/// Representation of a running or exited child process.
|
|
|
|
|
///
|
|
|
|
|
/// This structure is used to represent and manage child processes. A child
|
2016-07-09 15:47:12 +00:00
|
|
|
|
/// process is created via the [`Command`] struct, which configures the
|
|
|
|
|
/// spawning process and can itself be constructed using a builder-style
|
|
|
|
|
/// interface.
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
2017-03-25 03:29:23 +00:00
|
|
|
|
/// There is no implementation of [`Drop`] for child processes,
|
|
|
|
|
/// so if you do not ensure the `Child` has exited then it will continue to
|
|
|
|
|
/// run, even after the `Child` handle to the child process has gone out of
|
|
|
|
|
/// scope.
|
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// Calling [`wait`] (or other functions that wrap around it) will make
|
2017-03-25 03:29:23 +00:00
|
|
|
|
/// the parent process wait until the child has actually exited before
|
|
|
|
|
/// continuing.
|
|
|
|
|
///
|
2019-05-01 13:57:02 +00:00
|
|
|
|
/// # Warning
|
|
|
|
|
///
|
2020-08-23 23:38:23 +00:00
|
|
|
|
/// On some systems, calling [`wait`] or similar is necessary for the OS to
|
2019-05-01 13:57:02 +00:00
|
|
|
|
/// release resources. A process that terminated but has not been waited on is
|
|
|
|
|
/// still around as a "zombie". Leaving too many zombies around may exhaust
|
|
|
|
|
/// global resources (for example process IDs).
|
|
|
|
|
///
|
|
|
|
|
/// The standard library does *not* automatically wait on child processes (not
|
|
|
|
|
/// even if the `Child` is dropped), it is up to the application developer to do
|
|
|
|
|
/// so. As a consequence, dropping `Child` handles without waiting on them first
|
|
|
|
|
/// is not recommended in long-running applications.
|
|
|
|
|
///
|
2015-03-12 01:11:40 +00:00
|
|
|
|
/// # Examples
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
2015-03-26 20:30:33 +00:00
|
|
|
|
/// ```should_panic
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
2015-04-29 21:00:10 +00:00
|
|
|
|
/// let mut child = Command::new("/bin/cat")
|
2015-04-29 22:21:23 +00:00
|
|
|
|
/// .arg("file.txt")
|
|
|
|
|
/// .spawn()
|
2016-03-21 13:17:17 +00:00
|
|
|
|
/// .expect("failed to execute child");
|
2015-04-29 21:00:10 +00:00
|
|
|
|
///
|
|
|
|
|
/// let ecode = child.wait()
|
2016-03-21 13:17:17 +00:00
|
|
|
|
/// .expect("failed to wait on child");
|
2015-04-29 21:00:10 +00:00
|
|
|
|
///
|
|
|
|
|
/// assert!(ecode.success());
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// ```
|
2016-01-31 19:50:22 +00:00
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`wait`]: Child::wait
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub struct Child {
|
Add Linux-specific pidfd process extensions
Background:
Over the last year, pidfd support was added to the Linux kernel. This
allows interacting with other processes. In particular, this allows
waiting on a child process with a timeout in a race-free way, bypassing
all of the awful signal-handler tricks that are usually required.
Pidfds can be obtained for a child process (as well as any other
process) via the `pidfd_open` syscall. Unfortunately, this requires
several conditions to hold in order to be race-free (i.e. the pid is not
reused).
Per `man pidfd_open`:
```
· the disposition of SIGCHLD has not been explicitly set to SIG_IGN
(see sigaction(2));
· the SA_NOCLDWAIT flag was not specified while establishing a han‐
dler for SIGCHLD or while setting the disposition of that signal to
SIG_DFL (see sigaction(2)); and
· the zombie process was not reaped elsewhere in the program (e.g.,
either by an asynchronously executed signal handler or by wait(2)
or similar in another thread).
If any of these conditions does not hold, then the child process
(along with a PID file descriptor that refers to it) should instead
be created using clone(2) with the CLONE_PIDFD flag.
```
Sadly, these conditions are impossible to guarantee once any libraries
are used. For example, C code runnng in a different thread could call
`wait()`, which is impossible to detect from Rust code trying to open a
pidfd.
While pid reuse issues should (hopefully) be rare in practice, we can do
better. By passing the `CLONE_PIDFD` flag to `clone()` or `clone3()`, we
can obtain a pidfd for the child process in a guaranteed race-free
manner.
This PR:
This PR adds Linux-specific process extension methods to allow obtaining
pidfds for processes spawned via the standard `Command` API. Other than
being made available to user code, the standard library does not make
use of these pidfds in any way. In particular, the implementation of
`Child::wait` is completely unchanged.
Two Linux-specific helper methods are added: `CommandExt::create_pidfd`
and `ChildExt::pidfd`. These methods are intended to serve as a building
block for libraries to build higher-level abstractions - in particular,
waiting on a process with a timeout.
I've included a basic test, which verifies that pidfds are created iff
the `create_pidfd` method is used. This test is somewhat special - it
should always succeed on systems with the `clone3` system call
available, and always fail on systems without `clone3` available. I'm
not sure how to best ensure this programatically.
This PR relies on the newer `clone3` system call to pass the `CLONE_FD`,
rather than the older `clone` system call. `clone3` was added to Linux
in the same release as pidfds, so this shouldn't unnecessarily limit the
kernel versions that this code supports.
Unresolved questions:
* What should the name of the feature gate be for these newly added
methods?
* Should the `pidfd` method distinguish between an error occurring
and `create_pidfd` not being called?
2020-09-16 03:35:08 +00:00
|
|
|
|
pub(crate) handle: imp::Process,
|
2015-02-06 17:42:57 +00:00
|
|
|
|
|
2017-09-16 03:02:50 +00:00
|
|
|
|
/// The handle for writing to the child's standard input (stdin), if it has
|
2020-07-09 18:18:06 +00:00
|
|
|
|
/// been captured. To avoid partially moving
|
|
|
|
|
/// the `child` and thus blocking yourself from calling
|
|
|
|
|
/// functions on `child` while using `stdin`,
|
|
|
|
|
/// you might find it helpful:
|
|
|
|
|
///
|
|
|
|
|
/// ```compile_fail,E0425
|
|
|
|
|
/// let stdin = child.stdin.take().unwrap();
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub stdin: Option<ChildStdin>,
|
|
|
|
|
|
2017-09-16 03:02:50 +00:00
|
|
|
|
/// The handle for reading from the child's standard output (stdout), if it
|
2020-07-09 18:18:06 +00:00
|
|
|
|
/// has been captured. You might find it helpful to do
|
|
|
|
|
///
|
|
|
|
|
/// ```compile_fail,E0425
|
|
|
|
|
/// let stdout = child.stdout.take().unwrap();
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// to avoid partially moving the `child` and thus blocking yourself from calling
|
|
|
|
|
/// functions on `child` while using `stdout`.
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub stdout: Option<ChildStdout>,
|
|
|
|
|
|
2017-09-16 03:02:50 +00:00
|
|
|
|
/// The handle for reading from the child's standard error (stderr), if it
|
2020-07-09 18:18:06 +00:00
|
|
|
|
/// has been captured. You might find it helpful to do
|
|
|
|
|
///
|
|
|
|
|
/// ```compile_fail,E0425
|
|
|
|
|
/// let stderr = child.stderr.take().unwrap();
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// to avoid partially moving the `child` and thus blocking yourself from calling
|
|
|
|
|
/// functions on `child` while using `stderr`.
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub stderr: Option<ChildStderr>,
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-04 12:15:05 +00:00
|
|
|
|
/// Allows extension traits within `std`.
|
|
|
|
|
#[unstable(feature = "sealed", issue = "none")]
|
|
|
|
|
impl crate::sealed::Sealed for Child {}
|
|
|
|
|
|
2015-05-12 18:03:49 +00:00
|
|
|
|
impl AsInner<imp::Process> for Child {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn as_inner(&self) -> &imp::Process {
|
|
|
|
|
&self.handle
|
|
|
|
|
}
|
2015-05-12 18:03:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-04 19:10:37 +00:00
|
|
|
|
impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
|
|
|
|
|
fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child {
|
|
|
|
|
Child {
|
2017-08-07 05:54:09 +00:00
|
|
|
|
handle,
|
2016-02-04 19:10:37 +00:00
|
|
|
|
stdin: io.stdin.map(ChildStdin::from_inner),
|
|
|
|
|
stdout: io.stdout.map(ChildStdout::from_inner),
|
|
|
|
|
stderr: io.stderr.map(ChildStderr::from_inner),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-16 06:31:24 +00:00
|
|
|
|
impl IntoInner<imp::Process> for Child {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn into_inner(self) -> imp::Process {
|
|
|
|
|
self.handle
|
|
|
|
|
}
|
2015-07-16 06:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-29 13:31:47 +00:00
|
|
|
|
#[stable(feature = "std_debug", since = "1.16.0")]
|
2016-11-25 18:21:49 +00:00
|
|
|
|
impl fmt::Debug for Child {
|
2019-03-01 08:34:11 +00:00
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2016-11-25 18:21:49 +00:00
|
|
|
|
f.debug_struct("Child")
|
|
|
|
|
.field("stdin", &self.stdin)
|
|
|
|
|
.field("stdout", &self.stdout)
|
|
|
|
|
.field("stderr", &self.stderr)
|
2021-03-27 12:29:23 +00:00
|
|
|
|
.finish_non_exhaustive()
|
2016-11-25 18:21:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-16 03:02:50 +00:00
|
|
|
|
/// A handle to a child process's standard input (stdin).
|
2017-05-03 05:13:18 +00:00
|
|
|
|
///
|
|
|
|
|
/// This struct is used in the [`stdin`] field on [`Child`].
|
2016-07-09 15:47:12 +00:00
|
|
|
|
///
|
2017-09-16 02:57:12 +00:00
|
|
|
|
/// When an instance of `ChildStdin` is [dropped], the `ChildStdin`'s underlying
|
2017-09-22 01:11:11 +00:00
|
|
|
|
/// file handle will be closed. If the child process was blocked on input prior
|
|
|
|
|
/// to being dropped, it will become unblocked after dropping.
|
2017-09-16 02:57:12 +00:00
|
|
|
|
///
|
2020-08-12 03:10:41 +00:00
|
|
|
|
/// [`stdin`]: Child::stdin
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [dropped]: Drop
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub struct ChildStdin {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
inner: AnonPipe,
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-28 13:28:06 +00:00
|
|
|
|
// In addition to the `impl`s here, `ChildStdin` also has `impl`s for
|
|
|
|
|
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
|
|
|
|
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
|
|
|
|
// `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and
|
|
|
|
|
// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.
|
|
|
|
|
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
impl Write for ChildStdin {
|
|
|
|
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
2020-09-11 09:11:34 +00:00
|
|
|
|
(&*self).write(buf)
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 15:34:08 +00:00
|
|
|
|
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
2020-09-11 09:11:34 +00:00
|
|
|
|
(&*self).write_vectored(bufs)
|
std: Add `{read,write}_vectored` for more types
This commit implements the `{read,write}_vectored` methods on more types
in the standard library, namely:
* `std::fs::File`
* `std::process::ChildStd{in,out,err}`
* `std::io::Std{in,out,err}`
* `std::io::Std{in,out,err}Lock`
* `std::io::Std{in,out,err}Raw`
Where supported the OS implementations hook up to native support,
otherwise it falls back to the already-defaulted implementation.
2019-04-10 19:51:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 01:02:52 +00:00
|
|
|
|
fn is_write_vectored(&self) -> bool {
|
2020-09-11 09:11:34 +00:00
|
|
|
|
io::Write::is_write_vectored(&&*self)
|
2020-09-02 21:25:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn flush(&mut self) -> io::Result<()> {
|
2020-09-11 09:11:34 +00:00
|
|
|
|
(&*self).flush()
|
2020-09-02 21:25:09 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 07:12:40 +00:00
|
|
|
|
#[stable(feature = "write_mt", since = "1.48.0")]
|
2020-09-02 21:25:09 +00:00
|
|
|
|
impl Write for &ChildStdin {
|
2015-02-06 17:42:57 +00:00
|
|
|
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
|
|
|
self.inner.write(buf)
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-27 15:34:08 +00:00
|
|
|
|
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
std: Add `{read,write}_vectored` for more types
This commit implements the `{read,write}_vectored` methods on more types
in the standard library, namely:
* `std::fs::File`
* `std::process::ChildStd{in,out,err}`
* `std::io::Std{in,out,err}`
* `std::io::Std{in,out,err}Lock`
* `std::io::Std{in,out,err}Raw`
Where supported the OS implementations hook up to native support,
otherwise it falls back to the already-defaulted implementation.
2019-04-10 19:51:25 +00:00
|
|
|
|
self.inner.write_vectored(bufs)
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 01:02:52 +00:00
|
|
|
|
fn is_write_vectored(&self) -> bool {
|
|
|
|
|
self.inner.is_write_vectored()
|
2020-01-03 19:26:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 17:42:57 +00:00
|
|
|
|
fn flush(&mut self) -> io::Result<()> {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-12 18:03:49 +00:00
|
|
|
|
impl AsInner<AnonPipe> for ChildStdin {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn as_inner(&self) -> &AnonPipe {
|
|
|
|
|
&self.inner
|
|
|
|
|
}
|
2015-05-12 18:03:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-16 06:31:24 +00:00
|
|
|
|
impl IntoInner<AnonPipe> for ChildStdin {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn into_inner(self) -> AnonPipe {
|
|
|
|
|
self.inner
|
|
|
|
|
}
|
2015-07-16 06:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-04 19:10:37 +00:00
|
|
|
|
impl FromInner<AnonPipe> for ChildStdin {
|
|
|
|
|
fn from_inner(pipe: AnonPipe) -> ChildStdin {
|
|
|
|
|
ChildStdin { inner: pipe }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-29 13:31:47 +00:00
|
|
|
|
#[stable(feature = "std_debug", since = "1.16.0")]
|
2016-11-25 18:21:49 +00:00
|
|
|
|
impl fmt::Debug for ChildStdin {
|
2019-03-01 08:34:11 +00:00
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-04-05 11:31:11 +00:00
|
|
|
|
f.debug_struct("ChildStdin").finish_non_exhaustive()
|
2016-11-25 18:21:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-16 03:02:50 +00:00
|
|
|
|
/// A handle to a child process's standard output (stdout).
|
2017-05-03 05:13:18 +00:00
|
|
|
|
///
|
|
|
|
|
/// This struct is used in the [`stdout`] field on [`Child`].
|
2016-07-09 15:47:12 +00:00
|
|
|
|
///
|
2017-09-16 02:57:12 +00:00
|
|
|
|
/// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s
|
|
|
|
|
/// underlying file handle will be closed.
|
|
|
|
|
///
|
2020-08-12 03:10:41 +00:00
|
|
|
|
/// [`stdout`]: Child::stdout
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [dropped]: Drop
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub struct ChildStdout {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
inner: AnonPipe,
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-28 13:28:06 +00:00
|
|
|
|
// In addition to the `impl`s here, `ChildStdout` also has `impl`s for
|
|
|
|
|
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
|
|
|
|
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
|
|
|
|
// `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and
|
|
|
|
|
// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.
|
|
|
|
|
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
impl Read for ChildStdout {
|
|
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
|
|
|
self.inner.read(buf)
|
|
|
|
|
}
|
std: Add `{read,write}_vectored` for more types
This commit implements the `{read,write}_vectored` methods on more types
in the standard library, namely:
* `std::fs::File`
* `std::process::ChildStd{in,out,err}`
* `std::io::Std{in,out,err}`
* `std::io::Std{in,out,err}Lock`
* `std::io::Std{in,out,err}Raw`
Where supported the OS implementations hook up to native support,
otherwise it falls back to the already-defaulted implementation.
2019-04-10 19:51:25 +00:00
|
|
|
|
|
2019-04-27 15:34:08 +00:00
|
|
|
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
std: Add `{read,write}_vectored` for more types
This commit implements the `{read,write}_vectored` methods on more types
in the standard library, namely:
* `std::fs::File`
* `std::process::ChildStd{in,out,err}`
* `std::io::Std{in,out,err}`
* `std::io::Std{in,out,err}Lock`
* `std::io::Std{in,out,err}Raw`
Where supported the OS implementations hook up to native support,
otherwise it falls back to the already-defaulted implementation.
2019-04-10 19:51:25 +00:00
|
|
|
|
self.inner.read_vectored(bufs)
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-03 19:26:05 +00:00
|
|
|
|
#[inline]
|
2020-03-12 01:02:52 +00:00
|
|
|
|
fn is_read_vectored(&self) -> bool {
|
|
|
|
|
self.inner.is_read_vectored()
|
2020-01-03 19:26:05 +00:00
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-12 18:03:49 +00:00
|
|
|
|
impl AsInner<AnonPipe> for ChildStdout {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn as_inner(&self) -> &AnonPipe {
|
|
|
|
|
&self.inner
|
|
|
|
|
}
|
2015-05-12 18:03:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-16 06:31:24 +00:00
|
|
|
|
impl IntoInner<AnonPipe> for ChildStdout {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn into_inner(self) -> AnonPipe {
|
|
|
|
|
self.inner
|
|
|
|
|
}
|
2015-07-16 06:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-04 19:10:37 +00:00
|
|
|
|
impl FromInner<AnonPipe> for ChildStdout {
|
|
|
|
|
fn from_inner(pipe: AnonPipe) -> ChildStdout {
|
|
|
|
|
ChildStdout { inner: pipe }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-29 13:31:47 +00:00
|
|
|
|
#[stable(feature = "std_debug", since = "1.16.0")]
|
2016-11-25 18:21:49 +00:00
|
|
|
|
impl fmt::Debug for ChildStdout {
|
2019-03-01 08:34:11 +00:00
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-04-05 11:31:11 +00:00
|
|
|
|
f.debug_struct("ChildStdout").finish_non_exhaustive()
|
2016-11-25 18:21:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-04 20:23:52 +00:00
|
|
|
|
/// A handle to a child process's stderr.
|
|
|
|
|
///
|
|
|
|
|
/// This struct is used in the [`stderr`] field on [`Child`].
|
2016-07-09 15:47:12 +00:00
|
|
|
|
///
|
2017-09-16 02:57:12 +00:00
|
|
|
|
/// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s
|
|
|
|
|
/// underlying file handle will be closed.
|
|
|
|
|
///
|
2020-08-12 03:10:41 +00:00
|
|
|
|
/// [`stderr`]: Child::stderr
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [dropped]: Drop
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub struct ChildStderr {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
inner: AnonPipe,
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-28 13:28:06 +00:00
|
|
|
|
// In addition to the `impl`s here, `ChildStderr` also has `impl`s for
|
|
|
|
|
// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
|
|
|
|
|
// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
|
|
|
|
|
// `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and
|
|
|
|
|
// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.
|
|
|
|
|
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
impl Read for ChildStderr {
|
|
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
|
|
|
self.inner.read(buf)
|
|
|
|
|
}
|
std: Add `{read,write}_vectored` for more types
This commit implements the `{read,write}_vectored` methods on more types
in the standard library, namely:
* `std::fs::File`
* `std::process::ChildStd{in,out,err}`
* `std::io::Std{in,out,err}`
* `std::io::Std{in,out,err}Lock`
* `std::io::Std{in,out,err}Raw`
Where supported the OS implementations hook up to native support,
otherwise it falls back to the already-defaulted implementation.
2019-04-10 19:51:25 +00:00
|
|
|
|
|
2019-04-27 15:34:08 +00:00
|
|
|
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
std: Add `{read,write}_vectored` for more types
This commit implements the `{read,write}_vectored` methods on more types
in the standard library, namely:
* `std::fs::File`
* `std::process::ChildStd{in,out,err}`
* `std::io::Std{in,out,err}`
* `std::io::Std{in,out,err}Lock`
* `std::io::Std{in,out,err}Raw`
Where supported the OS implementations hook up to native support,
otherwise it falls back to the already-defaulted implementation.
2019-04-10 19:51:25 +00:00
|
|
|
|
self.inner.read_vectored(bufs)
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-03 19:26:05 +00:00
|
|
|
|
#[inline]
|
2020-03-12 01:02:52 +00:00
|
|
|
|
fn is_read_vectored(&self) -> bool {
|
|
|
|
|
self.inner.is_read_vectored()
|
2020-01-03 19:26:05 +00:00
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-12 18:03:49 +00:00
|
|
|
|
impl AsInner<AnonPipe> for ChildStderr {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn as_inner(&self) -> &AnonPipe {
|
|
|
|
|
&self.inner
|
|
|
|
|
}
|
2015-05-12 18:03:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-16 06:31:24 +00:00
|
|
|
|
impl IntoInner<AnonPipe> for ChildStderr {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn into_inner(self) -> AnonPipe {
|
|
|
|
|
self.inner
|
|
|
|
|
}
|
2015-07-16 06:31:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-04 19:10:37 +00:00
|
|
|
|
impl FromInner<AnonPipe> for ChildStderr {
|
|
|
|
|
fn from_inner(pipe: AnonPipe) -> ChildStderr {
|
|
|
|
|
ChildStderr { inner: pipe }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-29 13:31:47 +00:00
|
|
|
|
#[stable(feature = "std_debug", since = "1.16.0")]
|
2016-11-25 18:21:49 +00:00
|
|
|
|
impl fmt::Debug for ChildStderr {
|
2019-03-01 08:34:11 +00:00
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-04-05 11:31:11 +00:00
|
|
|
|
f.debug_struct("ChildStderr").finish_non_exhaustive()
|
2016-11-25 18:21:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-09 21:23:08 +00:00
|
|
|
|
/// A process builder, providing fine-grained control
|
|
|
|
|
/// over how a new process should be spawned.
|
|
|
|
|
///
|
|
|
|
|
/// A default configuration can be
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// generated using `Command::new(program)`, where `program` gives a path to the
|
|
|
|
|
/// program to be executed. Additional builder methods allow the configuration
|
|
|
|
|
/// to be changed (for example, by adding arguments) prior to spawning:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
2017-01-04 09:09:16 +00:00
|
|
|
|
/// let output = if cfg!(target_os = "windows") {
|
2017-01-03 12:20:30 +00:00
|
|
|
|
/// Command::new("cmd")
|
2021-07-02 09:10:00 +00:00
|
|
|
|
/// .args(["/C", "echo hello"])
|
2017-01-03 12:20:30 +00:00
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("failed to execute process")
|
|
|
|
|
/// } else {
|
|
|
|
|
/// Command::new("sh")
|
|
|
|
|
/// .arg("-c")
|
|
|
|
|
/// .arg("echo hello")
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("failed to execute process")
|
|
|
|
|
/// };
|
2016-03-21 13:17:17 +00:00
|
|
|
|
///
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// let hello = output.stdout;
|
|
|
|
|
/// ```
|
2018-08-11 10:13:29 +00:00
|
|
|
|
///
|
|
|
|
|
/// `Command` can be reused to spawn multiple processes. The builder methods
|
|
|
|
|
/// change the command without needing to immediately spawn the process.
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let mut echo_hello = Command::new("sh");
|
|
|
|
|
/// echo_hello.arg("-c")
|
2018-08-11 20:02:49 +00:00
|
|
|
|
/// .arg("echo hello");
|
2018-08-11 10:13:29 +00:00
|
|
|
|
/// let hello_1 = echo_hello.output().expect("failed to execute process");
|
|
|
|
|
/// let hello_2 = echo_hello.output().expect("failed to execute process");
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// Similarly, you can call builder methods after spawning a process and then
|
|
|
|
|
/// spawn a new process with the modified settings.
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let mut list_dir = Command::new("ls");
|
|
|
|
|
///
|
|
|
|
|
/// // Execute `ls` in the current directory of the program.
|
|
|
|
|
/// list_dir.status().expect("process failed to execute");
|
|
|
|
|
///
|
2019-09-13 09:36:35 +00:00
|
|
|
|
/// println!();
|
2018-08-11 10:13:29 +00:00
|
|
|
|
///
|
|
|
|
|
/// // Change `ls` to execute in the root directory.
|
|
|
|
|
/// list_dir.current_dir("/");
|
|
|
|
|
///
|
|
|
|
|
/// // And then execute `ls` again but in the root directory.
|
|
|
|
|
/// list_dir.status().expect("process failed to execute");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub struct Command {
|
2015-05-12 18:03:49 +00:00
|
|
|
|
inner: imp::Command,
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-10 21:30:30 +00:00
|
|
|
|
/// Allows extension traits within `std`.
|
|
|
|
|
#[unstable(feature = "sealed", issue = "none")]
|
|
|
|
|
impl crate::sealed::Sealed for Command {}
|
|
|
|
|
|
2015-02-06 17:42:57 +00:00
|
|
|
|
impl Command {
|
|
|
|
|
/// Constructs a new `Command` for launching the program at
|
|
|
|
|
/// path `program`, with the following default configuration:
|
|
|
|
|
///
|
|
|
|
|
/// * No arguments to the program
|
|
|
|
|
/// * Inherit the current process's environment
|
|
|
|
|
/// * Inherit the current process's working directory
|
2022-03-25 13:41:37 +00:00
|
|
|
|
/// * Inherit stdin/stdout/stderr for [`spawn`] or [`status`], but create pipes for [`output`]
|
|
|
|
|
///
|
|
|
|
|
/// [`spawn`]: Self::spawn
|
|
|
|
|
/// [`status`]: Self::status
|
|
|
|
|
/// [`output`]: Self::output
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
|
|
|
|
/// Builder methods are provided to change these defaults and
|
|
|
|
|
/// otherwise configure the process.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
2016-11-26 17:15:33 +00:00
|
|
|
|
/// If `program` is not an absolute path, the `PATH` will be searched in
|
|
|
|
|
/// an OS-defined way.
|
|
|
|
|
///
|
|
|
|
|
/// The search path to be used may be controlled by setting the
|
|
|
|
|
/// `PATH` environment variable on the Command,
|
|
|
|
|
/// but this has some implementation limitations on Windows
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// (see issue #37519).
|
2016-11-26 17:15:33 +00:00
|
|
|
|
///
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("sh")
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("sh command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-03-30 18:00:05 +00:00
|
|
|
|
pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
|
2016-02-04 19:10:37 +00:00
|
|
|
|
Command { inner: imp::Command::new(program.as_ref()) }
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// Adds an argument to pass to the program.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
2017-03-08 04:04:59 +00:00
|
|
|
|
/// Only one argument can be passed per use. So instead of:
|
|
|
|
|
///
|
2017-06-20 07:15:16 +00:00
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # std::process::Command::new("sh")
|
2017-03-08 04:04:59 +00:00
|
|
|
|
/// .arg("-C /path/to/repo")
|
2017-06-20 07:15:16 +00:00
|
|
|
|
/// # ;
|
2017-03-08 04:04:59 +00:00
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// usage would be:
|
|
|
|
|
///
|
2017-06-20 07:15:16 +00:00
|
|
|
|
/// ```no_run
|
|
|
|
|
/// # std::process::Command::new("sh")
|
2017-03-08 04:04:59 +00:00
|
|
|
|
/// .arg("-C")
|
|
|
|
|
/// .arg("/path/to/repo")
|
2017-06-20 07:15:16 +00:00
|
|
|
|
/// # ;
|
2017-03-08 04:04:59 +00:00
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// To pass multiple arguments see [`args`].
|
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`args`]: Command::args
|
2017-03-08 04:04:59 +00:00
|
|
|
|
///
|
2020-10-31 16:28:44 +00:00
|
|
|
|
/// Note that the argument is not passed through a shell, but given
|
|
|
|
|
/// literally to the program. This means that shell syntax like quotes,
|
|
|
|
|
/// escaped characters, word splitting, glob patterns, substitution, etc.
|
|
|
|
|
/// have no effect.
|
2020-10-31 13:40:36 +00:00
|
|
|
|
///
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
|
|
|
|
/// .arg("-l")
|
|
|
|
|
/// .arg("-a")
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-03-30 18:00:05 +00:00
|
|
|
|
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
|
|
|
|
|
self.inner.arg(arg.as_ref());
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// Adds multiple arguments to pass to the program.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
2017-03-08 04:04:59 +00:00
|
|
|
|
/// To pass a single argument see [`arg`].
|
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`arg`]: Command::arg
|
2017-03-08 04:04:59 +00:00
|
|
|
|
///
|
2020-10-31 16:28:44 +00:00
|
|
|
|
/// Note that the arguments are not passed through a shell, but given
|
|
|
|
|
/// literally to the program. This means that shell syntax like quotes,
|
|
|
|
|
/// escaped characters, word splitting, glob patterns, substitution, etc.
|
|
|
|
|
/// have no effect.
|
2020-10-31 13:40:36 +00:00
|
|
|
|
///
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
2021-07-02 09:10:00 +00:00
|
|
|
|
/// .args(["-l", "-a"])
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2017-01-21 16:01:11 +00:00
|
|
|
|
pub fn args<I, S>(&mut self, args: I) -> &mut Command
|
2019-11-27 18:29:00 +00:00
|
|
|
|
where
|
|
|
|
|
I: IntoIterator<Item = S>,
|
|
|
|
|
S: AsRef<OsStr>,
|
2017-01-21 16:01:11 +00:00
|
|
|
|
{
|
2015-10-31 18:09:43 +00:00
|
|
|
|
for arg in args {
|
|
|
|
|
self.arg(arg.as_ref());
|
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Inserts or updates an environment variable mapping.
|
|
|
|
|
///
|
|
|
|
|
/// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
|
|
|
|
|
/// and case-sensitive on all other platforms.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
|
|
|
|
/// .env("PATH", "/bin")
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-03-12 19:59:53 +00:00
|
|
|
|
pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
|
2019-11-27 18:29:00 +00:00
|
|
|
|
where
|
|
|
|
|
K: AsRef<OsStr>,
|
|
|
|
|
V: AsRef<OsStr>,
|
2015-02-06 17:42:57 +00:00
|
|
|
|
{
|
2017-12-17 15:21:47 +00:00
|
|
|
|
self.inner.env_mut().set(key.as_ref(), val.as_ref());
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// Adds or updates multiple environment variable mappings.
|
2017-01-05 20:51:45 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
2017-03-24 08:42:21 +00:00
|
|
|
|
///
|
2017-01-05 20:51:45 +00:00
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
/// use std::env;
|
2017-01-21 16:01:11 +00:00
|
|
|
|
/// use std::collections::HashMap;
|
2017-01-05 20:51:45 +00:00
|
|
|
|
///
|
2017-01-21 16:01:11 +00:00
|
|
|
|
/// let filtered_env : HashMap<String, String> =
|
2017-01-05 20:51:45 +00:00
|
|
|
|
/// env::vars().filter(|&(ref k, _)|
|
|
|
|
|
/// k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH"
|
|
|
|
|
/// ).collect();
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("printenv")
|
|
|
|
|
/// .stdin(Stdio::null())
|
|
|
|
|
/// .stdout(Stdio::inherit())
|
|
|
|
|
/// .env_clear()
|
|
|
|
|
/// .envs(&filtered_env)
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("printenv failed to start");
|
|
|
|
|
/// ```
|
2017-06-08 15:31:25 +00:00
|
|
|
|
#[stable(feature = "command_envs", since = "1.19.0")]
|
2017-01-21 16:01:11 +00:00
|
|
|
|
pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
|
2019-11-27 18:29:00 +00:00
|
|
|
|
where
|
|
|
|
|
I: IntoIterator<Item = (K, V)>,
|
|
|
|
|
K: AsRef<OsStr>,
|
|
|
|
|
V: AsRef<OsStr>,
|
2017-01-05 20:51:45 +00:00
|
|
|
|
{
|
2017-01-21 16:01:11 +00:00
|
|
|
|
for (ref key, ref val) in vars {
|
2017-12-17 15:21:47 +00:00
|
|
|
|
self.inner.env_mut().set(key.as_ref(), val.as_ref());
|
2017-01-05 20:51:45 +00:00
|
|
|
|
}
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// Removes an environment variable mapping.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
|
|
|
|
/// .env_remove("PATH")
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-03-30 18:00:05 +00:00
|
|
|
|
pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
|
2017-12-17 15:21:47 +00:00
|
|
|
|
self.inner.env_mut().remove(key.as_ref());
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Clears the entire environment map for the child process.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
|
|
|
|
/// .env_clear()
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub fn env_clear(&mut self) -> &mut Command {
|
2017-12-17 15:21:47 +00:00
|
|
|
|
self.inner.env_mut().clear();
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 14:21:32 +00:00
|
|
|
|
/// Sets the working directory for the child process.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
2018-08-15 18:07:44 +00:00
|
|
|
|
/// # Platform-specific behavior
|
|
|
|
|
///
|
2018-11-27 02:59:49 +00:00
|
|
|
|
/// If the program path is relative (e.g., `"./script.sh"`), it's ambiguous
|
2018-08-15 18:07:44 +00:00
|
|
|
|
/// whether it should be interpreted relative to the parent's working
|
|
|
|
|
/// directory or relative to `current_dir`. The behavior in this case is
|
|
|
|
|
/// platform specific and unstable, and it's recommended to use
|
|
|
|
|
/// [`canonicalize`] to get an absolute program path instead.
|
|
|
|
|
///
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
|
|
|
|
/// .current_dir("/bin")
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2018-08-15 18:07:44 +00:00
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`canonicalize`]: crate::fs::canonicalize
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2016-02-04 02:09:35 +00:00
|
|
|
|
pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
|
2015-03-30 18:00:05 +00:00
|
|
|
|
self.inner.cwd(dir.as_ref().as_ref());
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-22 01:01:51 +00:00
|
|
|
|
/// Configuration for the child process's standard input (stdin) handle.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
2022-03-25 13:41:37 +00:00
|
|
|
|
/// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and
|
|
|
|
|
/// defaults to [`piped`] when used with [`output`].
|
2017-10-09 18:20:07 +00:00
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`inherit`]: Stdio::inherit
|
|
|
|
|
/// [`piped`]: Stdio::piped
|
2022-03-25 13:41:37 +00:00
|
|
|
|
/// [`spawn`]: Self::spawn
|
|
|
|
|
/// [`status`]: Self::status
|
|
|
|
|
/// [`output`]: Self::output
|
2017-10-09 18:20:07 +00:00
|
|
|
|
///
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
|
|
|
|
/// .stdin(Stdio::null())
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2017-06-06 22:42:55 +00:00
|
|
|
|
pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
|
|
|
|
|
self.inner.stdin(cfg.into().0);
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-22 01:01:51 +00:00
|
|
|
|
/// Configuration for the child process's standard output (stdout) handle.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
2022-03-25 13:41:37 +00:00
|
|
|
|
/// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and
|
|
|
|
|
/// defaults to [`piped`] when used with [`output`].
|
2017-10-09 18:20:07 +00:00
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`inherit`]: Stdio::inherit
|
|
|
|
|
/// [`piped`]: Stdio::piped
|
2022-03-25 13:41:37 +00:00
|
|
|
|
/// [`spawn`]: Self::spawn
|
|
|
|
|
/// [`status`]: Self::status
|
|
|
|
|
/// [`output`]: Self::output
|
2017-10-09 18:20:07 +00:00
|
|
|
|
///
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
|
|
|
|
/// .stdout(Stdio::null())
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2017-06-06 22:42:55 +00:00
|
|
|
|
pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
|
|
|
|
|
self.inner.stdout(cfg.into().0);
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-22 01:01:51 +00:00
|
|
|
|
/// Configuration for the child process's standard error (stderr) handle.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
2022-03-25 13:41:37 +00:00
|
|
|
|
/// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and
|
|
|
|
|
/// defaults to [`piped`] when used with [`output`].
|
2017-10-09 18:20:07 +00:00
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`inherit`]: Stdio::inherit
|
|
|
|
|
/// [`piped`]: Stdio::piped
|
2022-03-25 13:41:37 +00:00
|
|
|
|
/// [`spawn`]: Self::spawn
|
|
|
|
|
/// [`status`]: Self::status
|
|
|
|
|
/// [`output`]: Self::output
|
2017-10-09 18:20:07 +00:00
|
|
|
|
///
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
|
|
|
|
/// .stderr(Stdio::null())
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2017-06-06 22:42:55 +00:00
|
|
|
|
pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
|
|
|
|
|
self.inner.stderr(cfg.into().0);
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Executes the command as a child process, returning a handle to it.
|
|
|
|
|
///
|
2015-06-06 00:27:04 +00:00
|
|
|
|
/// By default, stdin, stdout and stderr are inherited from the parent.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// Command::new("ls")
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("ls command failed to start");
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub fn spawn(&mut self) -> io::Result<Child> {
|
2016-02-12 18:28:03 +00:00
|
|
|
|
self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Executes the command as a child process, waiting for it to finish and
|
|
|
|
|
/// collecting all of its output.
|
|
|
|
|
///
|
2017-11-23 01:47:31 +00:00
|
|
|
|
/// By default, stdout and stderr are captured (and used to provide the
|
|
|
|
|
/// resulting output). Stdin is not inherited from the parent and any
|
|
|
|
|
/// attempt by the child process to read from the stdin stream will result
|
|
|
|
|
/// in the stream immediately closing.
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
2015-03-08 16:07:58 +00:00
|
|
|
|
/// # Examples
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
2016-03-21 13:17:17 +00:00
|
|
|
|
/// ```should_panic
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// use std::process::Command;
|
2018-11-10 17:16:04 +00:00
|
|
|
|
/// use std::io::{self, Write};
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// let output = Command::new("/bin/cat")
|
|
|
|
|
/// .arg("file.txt")
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("failed to execute process");
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
|
|
|
|
/// println!("status: {}", output.status);
|
2018-11-10 17:16:04 +00:00
|
|
|
|
/// io::stdout().write_all(&output.stdout).unwrap();
|
|
|
|
|
/// io::stderr().write_all(&output.stderr).unwrap();
|
2016-03-22 14:19:24 +00:00
|
|
|
|
///
|
|
|
|
|
/// assert!(output.status.success());
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub fn output(&mut self) -> io::Result<Output> {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
self.inner
|
|
|
|
|
.spawn(imp::Stdio::MakePipe, false)
|
|
|
|
|
.map(Child::from_inner)
|
2016-02-04 19:10:37 +00:00
|
|
|
|
.and_then(|p| p.wait_with_output())
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Executes a command as a child process, waiting for it to finish and
|
2021-02-22 15:26:19 +00:00
|
|
|
|
/// collecting its status.
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
2015-06-06 00:32:34 +00:00
|
|
|
|
/// By default, stdin, stdout and stderr are inherited from the parent.
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
2015-03-12 01:11:40 +00:00
|
|
|
|
/// # Examples
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
2016-03-21 13:17:17 +00:00
|
|
|
|
/// ```should_panic
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// let status = Command::new("/bin/cat")
|
|
|
|
|
/// .arg("file.txt")
|
|
|
|
|
/// .status()
|
|
|
|
|
/// .expect("failed to execute process");
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
2022-02-12 19:16:17 +00:00
|
|
|
|
/// println!("process finished with: {status}");
|
2016-03-22 14:19:24 +00:00
|
|
|
|
///
|
|
|
|
|
/// assert!(status.success());
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub fn status(&mut self) -> io::Result<ExitStatus> {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
self.inner
|
|
|
|
|
.spawn(imp::Stdio::Inherit, true)
|
|
|
|
|
.map(Child::from_inner)
|
|
|
|
|
.and_then(|mut p| p.wait())
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
2020-09-21 18:32:06 +00:00
|
|
|
|
|
|
|
|
|
/// Returns the path to the program that was given to [`Command::new`].
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let cmd = Command::new("echo");
|
|
|
|
|
/// assert_eq!(cmd.get_program(), "echo");
|
|
|
|
|
/// ```
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2021-10-05 22:09:11 +00:00
|
|
|
|
#[stable(feature = "command_access", since = "1.57.0")]
|
2020-09-21 18:32:06 +00:00
|
|
|
|
pub fn get_program(&self) -> &OsStr {
|
|
|
|
|
self.inner.get_program()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns an iterator of the arguments that will be passed to the program.
|
|
|
|
|
///
|
|
|
|
|
/// This does not include the path to the program as the first argument;
|
|
|
|
|
/// it only includes the arguments specified with [`Command::arg`] and
|
|
|
|
|
/// [`Command::args`].
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// use std::ffi::OsStr;
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let mut cmd = Command::new("echo");
|
|
|
|
|
/// cmd.arg("first").arg("second");
|
|
|
|
|
/// let args: Vec<&OsStr> = cmd.get_args().collect();
|
|
|
|
|
/// assert_eq!(args, &["first", "second"]);
|
|
|
|
|
/// ```
|
2021-10-05 22:09:11 +00:00
|
|
|
|
#[stable(feature = "command_access", since = "1.57.0")]
|
2020-09-21 18:32:06 +00:00
|
|
|
|
pub fn get_args(&self) -> CommandArgs<'_> {
|
|
|
|
|
CommandArgs { inner: self.inner.get_args() }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns an iterator of the environment variables that will be set when
|
|
|
|
|
/// the process is spawned.
|
|
|
|
|
///
|
|
|
|
|
/// Each element is a tuple `(&OsStr, Option<&OsStr>)`, where the first
|
|
|
|
|
/// value is the key, and the second is the value, which is [`None`] if
|
|
|
|
|
/// the environment variable is to be explicitly removed.
|
|
|
|
|
///
|
|
|
|
|
/// This only includes environment variables explicitly set with
|
|
|
|
|
/// [`Command::env`], [`Command::envs`], and [`Command::env_remove`]. It
|
|
|
|
|
/// does not include environment variables that will be inherited by the
|
|
|
|
|
/// child process.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// use std::ffi::OsStr;
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let mut cmd = Command::new("ls");
|
|
|
|
|
/// cmd.env("TERM", "dumb").env_remove("TZ");
|
|
|
|
|
/// let envs: Vec<(&OsStr, Option<&OsStr>)> = cmd.get_envs().collect();
|
|
|
|
|
/// assert_eq!(envs, &[
|
|
|
|
|
/// (OsStr::new("TERM"), Some(OsStr::new("dumb"))),
|
|
|
|
|
/// (OsStr::new("TZ"), None)
|
|
|
|
|
/// ]);
|
|
|
|
|
/// ```
|
2021-10-05 22:09:11 +00:00
|
|
|
|
#[stable(feature = "command_access", since = "1.57.0")]
|
2020-09-21 18:32:06 +00:00
|
|
|
|
pub fn get_envs(&self) -> CommandEnvs<'_> {
|
|
|
|
|
self.inner.get_envs()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the working directory for the child process.
|
|
|
|
|
///
|
|
|
|
|
/// This returns [`None`] if the working directory will not be changed.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// use std::path::Path;
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let mut cmd = Command::new("ls");
|
|
|
|
|
/// assert_eq!(cmd.get_current_dir(), None);
|
|
|
|
|
/// cmd.current_dir("/bin");
|
|
|
|
|
/// assert_eq!(cmd.get_current_dir(), Some(Path::new("/bin")));
|
|
|
|
|
/// ```
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2021-10-05 22:09:11 +00:00
|
|
|
|
#[stable(feature = "command_access", since = "1.57.0")]
|
2020-09-21 18:32:06 +00:00
|
|
|
|
pub fn get_current_dir(&self) -> Option<&Path> {
|
|
|
|
|
self.inner.get_current_dir()
|
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
impl fmt::Debug for Command {
|
|
|
|
|
/// Format the program and arguments of a Command for display. Any
|
|
|
|
|
/// non-utf8 data is lossily converted using the utf8 replacement
|
|
|
|
|
/// character.
|
2019-03-01 08:34:11 +00:00
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2016-01-15 20:29:45 +00:00
|
|
|
|
self.inner.fmt(f)
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-12 18:03:49 +00:00
|
|
|
|
impl AsInner<imp::Command> for Command {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn as_inner(&self) -> &imp::Command {
|
|
|
|
|
&self.inner
|
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-12 18:03:49 +00:00
|
|
|
|
impl AsInnerMut<imp::Command> for Command {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn as_inner_mut(&mut self) -> &mut imp::Command {
|
|
|
|
|
&mut self.inner
|
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 18:32:06 +00:00
|
|
|
|
/// An iterator over the command arguments.
|
|
|
|
|
///
|
|
|
|
|
/// This struct is created by [`Command::get_args`]. See its documentation for
|
|
|
|
|
/// more.
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
2021-10-05 22:09:11 +00:00
|
|
|
|
#[stable(feature = "command_access", since = "1.57.0")]
|
2020-09-21 18:32:06 +00:00
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct CommandArgs<'a> {
|
|
|
|
|
inner: imp::CommandArgs<'a>,
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-05 22:09:11 +00:00
|
|
|
|
#[stable(feature = "command_access", since = "1.57.0")]
|
2020-09-21 18:32:06 +00:00
|
|
|
|
impl<'a> Iterator for CommandArgs<'a> {
|
|
|
|
|
type Item = &'a OsStr;
|
|
|
|
|
fn next(&mut self) -> Option<&'a OsStr> {
|
|
|
|
|
self.inner.next()
|
|
|
|
|
}
|
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
|
self.inner.size_hint()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-05 22:09:11 +00:00
|
|
|
|
#[stable(feature = "command_access", since = "1.57.0")]
|
2020-09-21 18:32:06 +00:00
|
|
|
|
impl<'a> ExactSizeIterator for CommandArgs<'a> {
|
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
|
self.inner.len()
|
|
|
|
|
}
|
|
|
|
|
fn is_empty(&self) -> bool {
|
|
|
|
|
self.inner.is_empty()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// The output of a finished process.
|
2017-10-13 17:18:09 +00:00
|
|
|
|
///
|
|
|
|
|
/// This is returned in a Result by either the [`output`] method of a
|
|
|
|
|
/// [`Command`], or the [`wait_with_output`] method of a [`Child`]
|
|
|
|
|
/// process.
|
2017-10-08 21:11:20 +00:00
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`output`]: Command::output
|
|
|
|
|
/// [`wait_with_output`]: Child::wait_with_output
|
2015-02-06 17:42:57 +00:00
|
|
|
|
#[derive(PartialEq, Eq, Clone)]
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub struct Output {
|
|
|
|
|
/// The status (exit code) of the process.
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub status: ExitStatus,
|
|
|
|
|
/// The data that the process wrote to stdout.
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub stdout: Vec<u8>,
|
|
|
|
|
/// The data that the process wrote to stderr.
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub stderr: Vec<u8>,
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 20:28:54 +00:00
|
|
|
|
// If either stderr or stdout are valid utf8 strings it prints the valid
|
|
|
|
|
// strings, otherwise it prints the byte sequence instead
|
|
|
|
|
#[stable(feature = "process_output_debug", since = "1.7.0")]
|
|
|
|
|
impl fmt::Debug for Output {
|
2019-03-01 08:34:11 +00:00
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2015-12-16 20:28:54 +00:00
|
|
|
|
let stdout_utf8 = str::from_utf8(&self.stdout);
|
2018-07-10 18:35:36 +00:00
|
|
|
|
let stdout_debug: &dyn fmt::Debug = match stdout_utf8 {
|
2015-12-16 20:28:54 +00:00
|
|
|
|
Ok(ref str) => str,
|
2019-11-27 18:29:00 +00:00
|
|
|
|
Err(_) => &self.stdout,
|
2015-12-16 20:28:54 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let stderr_utf8 = str::from_utf8(&self.stderr);
|
2018-07-10 18:35:36 +00:00
|
|
|
|
let stderr_debug: &dyn fmt::Debug = match stderr_utf8 {
|
2015-12-16 20:28:54 +00:00
|
|
|
|
Ok(ref str) => str,
|
2019-11-27 18:29:00 +00:00
|
|
|
|
Err(_) => &self.stderr,
|
2015-12-16 20:28:54 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
fmt.debug_struct("Output")
|
|
|
|
|
.field("status", &self.status)
|
|
|
|
|
.field("stdout", stdout_debug)
|
|
|
|
|
.field("stderr", stderr_debug)
|
|
|
|
|
.finish()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-08 16:12:14 +00:00
|
|
|
|
/// Describes what to do with a standard I/O stream for a child process when
|
|
|
|
|
/// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`].
|
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`stdin`]: Command::stdin
|
|
|
|
|
/// [`stdout`]: Command::stdout
|
|
|
|
|
/// [`stderr`]: Command::stderr
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2016-02-04 19:10:37 +00:00
|
|
|
|
pub struct Stdio(imp::Stdio);
|
2015-02-06 17:42:57 +00:00
|
|
|
|
|
|
|
|
|
impl Stdio {
|
2015-02-28 00:23:21 +00:00
|
|
|
|
/// A new pipe should be arranged to connect the parent and child processes.
|
2017-10-08 16:12:14 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// With stdout:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// let output = Command::new("echo")
|
|
|
|
|
/// .arg("Hello, world!")
|
|
|
|
|
/// .stdout(Stdio::piped())
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("Failed to execute command");
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(String::from_utf8_lossy(&output.stdout), "Hello, world!\n");
|
|
|
|
|
/// // Nothing echoed to console
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// With stdin:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::io::Write;
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// let mut child = Command::new("rev")
|
|
|
|
|
/// .stdin(Stdio::piped())
|
|
|
|
|
/// .stdout(Stdio::piped())
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("Failed to spawn child process");
|
2017-10-08 18:09:16 +00:00
|
|
|
|
///
|
2021-03-09 18:30:39 +00:00
|
|
|
|
/// let mut stdin = child.stdin.take().expect("Failed to open stdin");
|
|
|
|
|
/// std::thread::spawn(move || {
|
2017-10-08 16:12:14 +00:00
|
|
|
|
/// stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin");
|
2021-03-09 18:30:39 +00:00
|
|
|
|
/// });
|
2017-10-08 18:09:16 +00:00
|
|
|
|
///
|
2017-10-08 16:12:14 +00:00
|
|
|
|
/// let output = child.wait_with_output().expect("Failed to read stdout");
|
2019-09-08 21:03:09 +00:00
|
|
|
|
/// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH");
|
2017-10-08 16:12:14 +00:00
|
|
|
|
/// ```
|
2021-03-09 18:30:39 +00:00
|
|
|
|
///
|
|
|
|
|
/// Writing more than a pipe buffer's worth of input to stdin without also reading
|
|
|
|
|
/// stdout and stderr at the same time may cause a deadlock.
|
|
|
|
|
/// This is an issue when running any program that doesn't guarantee that it reads
|
|
|
|
|
/// its entire stdin before writing more than a pipe buffer's worth of output.
|
|
|
|
|
/// The size of a pipe buffer varies on different targets.
|
|
|
|
|
///
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2019-11-27 18:29:00 +00:00
|
|
|
|
pub fn piped() -> Stdio {
|
|
|
|
|
Stdio(imp::Stdio::MakePipe)
|
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
|
|
|
|
|
/// The child inherits from the corresponding parent descriptor.
|
2017-10-08 16:12:14 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// With stdout:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// let output = Command::new("echo")
|
|
|
|
|
/// .arg("Hello, world!")
|
|
|
|
|
/// .stdout(Stdio::inherit())
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("Failed to execute command");
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
|
|
|
|
|
/// // "Hello, world!" echoed to console
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// With stdin:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
2018-11-10 17:16:04 +00:00
|
|
|
|
/// use std::io::{self, Write};
|
2017-10-08 18:09:16 +00:00
|
|
|
|
///
|
2017-10-08 16:12:14 +00:00
|
|
|
|
/// let output = Command::new("rev")
|
|
|
|
|
/// .stdin(Stdio::inherit())
|
|
|
|
|
/// .stdout(Stdio::piped())
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("Failed to execute command");
|
2017-10-08 18:09:16 +00:00
|
|
|
|
///
|
2018-11-10 17:16:04 +00:00
|
|
|
|
/// print!("You piped in the reverse of: ");
|
|
|
|
|
/// io::stdout().write_all(&output.stdout).unwrap();
|
2017-10-08 16:12:14 +00:00
|
|
|
|
/// ```
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2019-11-27 18:29:00 +00:00
|
|
|
|
pub fn inherit() -> Stdio {
|
|
|
|
|
Stdio(imp::Stdio::Inherit)
|
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
|
|
|
|
|
/// This stream will be ignored. This is the equivalent of attaching the
|
2020-10-19 06:03:16 +00:00
|
|
|
|
/// stream to `/dev/null`.
|
2017-10-08 16:12:14 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// With stdout:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// let output = Command::new("echo")
|
|
|
|
|
/// .arg("Hello, world!")
|
|
|
|
|
/// .stdout(Stdio::null())
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("Failed to execute command");
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
|
|
|
|
|
/// // Nothing echoed to console
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// With stdin:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
2017-10-08 18:09:16 +00:00
|
|
|
|
///
|
2017-10-08 16:12:14 +00:00
|
|
|
|
/// let output = Command::new("rev")
|
|
|
|
|
/// .stdin(Stdio::null())
|
|
|
|
|
/// .stdout(Stdio::piped())
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("Failed to execute command");
|
2017-10-08 18:09:16 +00:00
|
|
|
|
///
|
2017-10-08 16:12:14 +00:00
|
|
|
|
/// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
|
|
|
|
|
/// // Ignores any piped-in input
|
|
|
|
|
/// ```
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2019-11-27 18:29:00 +00:00
|
|
|
|
pub fn null() -> Stdio {
|
|
|
|
|
Stdio(imp::Stdio::Null)
|
|
|
|
|
}
|
2015-05-12 18:03:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-04 19:10:37 +00:00
|
|
|
|
impl FromInner<imp::Stdio> for Stdio {
|
|
|
|
|
fn from_inner(inner: imp::Stdio) -> Stdio {
|
|
|
|
|
Stdio(inner)
|
2015-05-12 18:03:49 +00:00
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-29 13:31:47 +00:00
|
|
|
|
#[stable(feature = "std_debug", since = "1.16.0")]
|
2016-11-25 18:21:49 +00:00
|
|
|
|
impl fmt::Debug for Stdio {
|
2019-03-01 08:34:11 +00:00
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-04-05 11:31:11 +00:00
|
|
|
|
f.debug_struct("Stdio").finish_non_exhaustive()
|
2016-11-25 18:21:49 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-06 22:42:55 +00:00
|
|
|
|
#[stable(feature = "stdio_from", since = "1.20.0")]
|
|
|
|
|
impl From<ChildStdin> for Stdio {
|
2021-10-13 15:46:34 +00:00
|
|
|
|
/// Converts a [`ChildStdin`] into a [`Stdio`].
|
2018-10-19 10:00:45 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// `ChildStdin` will be converted to `Stdio` using `Stdio::from` under the hood.
|
|
|
|
|
///
|
2019-02-26 03:49:49 +00:00
|
|
|
|
/// ```rust,no_run
|
2018-10-19 10:00:45 +00:00
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// let reverse = Command::new("rev")
|
|
|
|
|
/// .stdin(Stdio::piped())
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("failed reverse command");
|
|
|
|
|
///
|
|
|
|
|
/// let _echo = Command::new("echo")
|
|
|
|
|
/// .arg("Hello, world!")
|
|
|
|
|
/// .stdout(reverse.stdin.unwrap()) // Converted into a Stdio here
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("failed echo command");
|
|
|
|
|
///
|
|
|
|
|
/// // "!dlrow ,olleH" echoed to console
|
|
|
|
|
/// ```
|
2017-06-06 22:42:55 +00:00
|
|
|
|
fn from(child: ChildStdin) -> Stdio {
|
|
|
|
|
Stdio::from_inner(child.into_inner().into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[stable(feature = "stdio_from", since = "1.20.0")]
|
|
|
|
|
impl From<ChildStdout> for Stdio {
|
2021-10-13 15:46:34 +00:00
|
|
|
|
/// Converts a [`ChildStdout`] into a [`Stdio`].
|
2018-10-19 10:00:45 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// `ChildStdout` will be converted to `Stdio` using `Stdio::from` under the hood.
|
|
|
|
|
///
|
2019-02-26 03:49:49 +00:00
|
|
|
|
/// ```rust,no_run
|
2018-10-19 10:00:45 +00:00
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// let hello = Command::new("echo")
|
|
|
|
|
/// .arg("Hello, world!")
|
|
|
|
|
/// .stdout(Stdio::piped())
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("failed echo command");
|
|
|
|
|
///
|
|
|
|
|
/// let reverse = Command::new("rev")
|
|
|
|
|
/// .stdin(hello.stdout.unwrap()) // Converted into a Stdio here
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("failed reverse command");
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(reverse.stdout, b"!dlrow ,olleH\n");
|
|
|
|
|
/// ```
|
2017-06-06 22:42:55 +00:00
|
|
|
|
fn from(child: ChildStdout) -> Stdio {
|
|
|
|
|
Stdio::from_inner(child.into_inner().into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[stable(feature = "stdio_from", since = "1.20.0")]
|
|
|
|
|
impl From<ChildStderr> for Stdio {
|
2021-10-13 15:46:34 +00:00
|
|
|
|
/// Converts a [`ChildStderr`] into a [`Stdio`].
|
2018-10-19 10:00:45 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust,no_run
|
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
|
|
|
|
/// let reverse = Command::new("rev")
|
|
|
|
|
/// .arg("non_existing_file.txt")
|
|
|
|
|
/// .stderr(Stdio::piped())
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("failed reverse command");
|
|
|
|
|
///
|
|
|
|
|
/// let cat = Command::new("cat")
|
|
|
|
|
/// .arg("-")
|
|
|
|
|
/// .stdin(reverse.stderr.unwrap()) // Converted into a Stdio here
|
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("failed echo command");
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(
|
|
|
|
|
/// String::from_utf8_lossy(&cat.stdout),
|
|
|
|
|
/// "rev: cannot open non_existing_file.txt: No such file or directory\n"
|
|
|
|
|
/// );
|
|
|
|
|
/// ```
|
2017-06-06 22:42:55 +00:00
|
|
|
|
fn from(child: ChildStderr) -> Stdio {
|
|
|
|
|
Stdio::from_inner(child.into_inner().into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[stable(feature = "stdio_from", since = "1.20.0")]
|
|
|
|
|
impl From<fs::File> for Stdio {
|
2021-10-13 15:46:34 +00:00
|
|
|
|
/// Converts a [`File`](fs::File) into a [`Stdio`].
|
2018-10-19 10:00:45 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// `File` will be converted to `Stdio` using `Stdio::from` under the hood.
|
|
|
|
|
///
|
|
|
|
|
/// ```rust,no_run
|
|
|
|
|
/// use std::fs::File;
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// // With the `foo.txt` file containing `Hello, world!"
|
|
|
|
|
/// let file = File::open("foo.txt").unwrap();
|
|
|
|
|
///
|
|
|
|
|
/// let reverse = Command::new("rev")
|
2018-11-12 18:05:20 +00:00
|
|
|
|
/// .stdin(file) // Implicit File conversion into a Stdio
|
2018-10-19 10:00:45 +00:00
|
|
|
|
/// .output()
|
|
|
|
|
/// .expect("failed reverse command");
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(reverse.stdout, b"!dlrow ,olleH");
|
|
|
|
|
/// ```
|
2017-06-06 22:42:55 +00:00
|
|
|
|
fn from(file: fs::File) -> Stdio {
|
|
|
|
|
Stdio::from_inner(file.into_inner().into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// Describes the result of a process after it has terminated.
|
2017-05-11 15:49:16 +00:00
|
|
|
|
///
|
2021-02-22 15:26:19 +00:00
|
|
|
|
/// This `struct` is used to represent the exit status or other termination of a child process.
|
2017-05-11 15:49:16 +00:00
|
|
|
|
/// Child processes are created via the [`Command`] struct and their exit
|
2019-06-05 07:58:39 +00:00
|
|
|
|
/// status is exposed through the [`status`] method, or the [`wait`] method
|
2019-06-05 06:41:37 +00:00
|
|
|
|
/// of a [`Child`] process.
|
2017-05-11 15:49:16 +00:00
|
|
|
|
///
|
2021-02-22 15:26:19 +00:00
|
|
|
|
/// An `ExitStatus` represents every possible disposition of a process. On Unix this
|
|
|
|
|
/// is the **wait status**. It is *not* simply an *exit status* (a value passed to `exit`).
|
|
|
|
|
///
|
2021-03-03 12:17:16 +00:00
|
|
|
|
/// For proper error reporting of failed processes, print the value of `ExitStatus` or
|
|
|
|
|
/// `ExitStatusError` using their implementations of [`Display`](crate::fmt::Display).
|
2021-02-22 15:26:19 +00:00
|
|
|
|
///
|
2022-02-09 23:12:17 +00:00
|
|
|
|
/// # Differences from `ExitStatus`
|
|
|
|
|
///
|
|
|
|
|
/// `ExitCode` is intended for terminating the currently running process, via
|
|
|
|
|
/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the
|
|
|
|
|
/// termination of a child process. These APIs are separate due to platform
|
|
|
|
|
/// compatibility differences and their expected usage; it is not generally
|
|
|
|
|
/// possible to exactly reproduce an ExitStatus from a child for the current
|
|
|
|
|
/// process after the fact.
|
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`status`]: Command::status
|
|
|
|
|
/// [`wait`]: Child::wait
|
2021-11-08 17:38:53 +00:00
|
|
|
|
//
|
|
|
|
|
// We speak slightly loosely (here and in various other places in the stdlib docs) about `exit`
|
|
|
|
|
// vs `_exit`. Naming of Unix system calls is not standardised across Unices, so terminology is a
|
|
|
|
|
// matter of convention and tradition. For clarity we usually speak of `exit`, even when we might
|
|
|
|
|
// mean an underlying system call such as `_exit`.
|
2015-02-06 17:42:57 +00:00
|
|
|
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-05-12 18:03:49 +00:00
|
|
|
|
pub struct ExitStatus(imp::ExitStatus);
|
2015-02-06 17:42:57 +00:00
|
|
|
|
|
2021-02-10 21:30:30 +00:00
|
|
|
|
/// Allows extension traits within `std`.
|
|
|
|
|
#[unstable(feature = "sealed", issue = "none")]
|
|
|
|
|
impl crate::sealed::Sealed for ExitStatus {}
|
|
|
|
|
|
2015-02-06 17:42:57 +00:00
|
|
|
|
impl ExitStatus {
|
2021-03-03 12:17:16 +00:00
|
|
|
|
/// Was termination successful? Returns a `Result`.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// #![feature(exit_status_error)]
|
|
|
|
|
/// # if cfg!(unix) {
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let status = Command::new("ls")
|
|
|
|
|
/// .arg("/dev/nonexistent")
|
|
|
|
|
/// .status()
|
|
|
|
|
/// .expect("ls could not be executed");
|
|
|
|
|
///
|
2022-02-12 19:16:17 +00:00
|
|
|
|
/// println!("ls: {status}");
|
2021-03-03 12:17:16 +00:00
|
|
|
|
/// status.exit_ok().expect_err("/dev/nonexistent could be listed!");
|
|
|
|
|
/// # } // cfg!(unix)
|
|
|
|
|
/// ```
|
|
|
|
|
#[unstable(feature = "exit_status_error", issue = "84908")]
|
|
|
|
|
pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
|
|
|
|
|
self.0.exit_ok().map_err(ExitStatusError)
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 06:44:53 +00:00
|
|
|
|
/// Was termination successful? Signal termination is not considered a
|
|
|
|
|
/// success, and success is defined as a zero exit status.
|
2016-07-12 23:52:44 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust,no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let status = Command::new("mkdir")
|
|
|
|
|
/// .arg("projects")
|
|
|
|
|
/// .status()
|
|
|
|
|
/// .expect("failed to execute mkdir");
|
|
|
|
|
///
|
|
|
|
|
/// if status.success() {
|
|
|
|
|
/// println!("'projects/' directory created");
|
|
|
|
|
/// } else {
|
2022-02-12 19:16:17 +00:00
|
|
|
|
/// println!("failed to create 'projects/' directory: {status}");
|
2016-07-12 23:52:44 +00:00
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub fn success(&self) -> bool {
|
2021-03-03 12:17:16 +00:00
|
|
|
|
self.0.exit_ok().is_ok()
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 14:21:32 +00:00
|
|
|
|
/// Returns the exit code of the process, if any.
|
2015-02-06 17:42:57 +00:00
|
|
|
|
///
|
2021-02-22 15:26:19 +00:00
|
|
|
|
/// In Unix terms the return value is the **exit status**: the value passed to `exit`, if the
|
|
|
|
|
/// process finished by calling `exit`. Note that on Unix the exit status is truncated to 8
|
2021-08-04 21:04:58 +00:00
|
|
|
|
/// bits, and that values that didn't come from a program's call to `exit` may be invented by the
|
2021-02-22 15:26:19 +00:00
|
|
|
|
/// runtime system (often, for example, 255, 254, 127 or 126).
|
|
|
|
|
///
|
|
|
|
|
/// On Unix, this will return `None` if the process was terminated by a signal.
|
|
|
|
|
/// [`ExitStatusExt`](crate::os::unix::process::ExitStatusExt) is an
|
|
|
|
|
/// extension trait for extracting any such signal, and other details, from the `ExitStatus`.
|
2017-05-11 15:49:16 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let status = Command::new("mkdir")
|
|
|
|
|
/// .arg("projects")
|
|
|
|
|
/// .status()
|
|
|
|
|
/// .expect("failed to execute mkdir");
|
|
|
|
|
///
|
|
|
|
|
/// match status.code() {
|
2022-02-12 19:16:17 +00:00
|
|
|
|
/// Some(code) => println!("Exited with status code: {code}"),
|
2017-05-11 15:49:16 +00:00
|
|
|
|
/// None => println!("Process terminated by signal")
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub fn code(&self) -> Option<i32> {
|
|
|
|
|
self.0.code()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-12 18:03:49 +00:00
|
|
|
|
impl AsInner<imp::ExitStatus> for ExitStatus {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
fn as_inner(&self) -> &imp::ExitStatus {
|
|
|
|
|
&self.0
|
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-26 22:23:46 +00:00
|
|
|
|
impl FromInner<imp::ExitStatus> for ExitStatus {
|
|
|
|
|
fn from_inner(s: imp::ExitStatus) -> ExitStatus {
|
|
|
|
|
ExitStatus(s)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
impl fmt::Display for ExitStatus {
|
2019-03-01 08:34:11 +00:00
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2015-02-06 17:42:57 +00:00
|
|
|
|
self.0.fmt(f)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-24 14:52:16 +00:00
|
|
|
|
/// Allows extension traits within `std`.
|
|
|
|
|
#[unstable(feature = "sealed", issue = "none")]
|
|
|
|
|
impl crate::sealed::Sealed for ExitStatusError {}
|
|
|
|
|
|
2021-03-03 12:17:16 +00:00
|
|
|
|
/// Describes the result of a process after it has failed
|
|
|
|
|
///
|
|
|
|
|
/// Produced by the [`.exit_ok`](ExitStatus::exit_ok) method on [`ExitStatus`].
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// #![feature(exit_status_error)]
|
|
|
|
|
/// # if cfg!(unix) {
|
|
|
|
|
/// use std::process::{Command, ExitStatusError};
|
|
|
|
|
///
|
|
|
|
|
/// fn run(cmd: &str) -> Result<(),ExitStatusError> {
|
|
|
|
|
/// Command::new(cmd).status().unwrap().exit_ok()?;
|
|
|
|
|
/// Ok(())
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// run("true").unwrap();
|
|
|
|
|
/// run("false").unwrap_err();
|
|
|
|
|
/// # } // cfg!(unix)
|
|
|
|
|
/// ```
|
|
|
|
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
|
|
|
|
#[unstable(feature = "exit_status_error", issue = "84908")]
|
|
|
|
|
// The definition of imp::ExitStatusError should ideally be such that
|
|
|
|
|
// Result<(), imp::ExitStatusError> has an identical representation to imp::ExitStatus.
|
|
|
|
|
pub struct ExitStatusError(imp::ExitStatusError);
|
|
|
|
|
|
|
|
|
|
#[unstable(feature = "exit_status_error", issue = "84908")]
|
|
|
|
|
impl ExitStatusError {
|
|
|
|
|
/// Reports the exit code, if applicable, from an `ExitStatusError`.
|
|
|
|
|
///
|
|
|
|
|
/// In Unix terms the return value is the **exit status**: the value passed to `exit`, if the
|
|
|
|
|
/// process finished by calling `exit`. Note that on Unix the exit status is truncated to 8
|
2021-03-16 15:17:27 +00:00
|
|
|
|
/// bits, and that values that didn't come from a program's call to `exit` may be invented by the
|
2021-03-03 12:17:16 +00:00
|
|
|
|
/// runtime system (often, for example, 255, 254, 127 or 126).
|
|
|
|
|
///
|
|
|
|
|
/// On Unix, this will return `None` if the process was terminated by a signal. If you want to
|
2021-02-24 14:52:16 +00:00
|
|
|
|
/// handle such situations specially, consider using methods from
|
|
|
|
|
/// [`ExitStatusExt`](crate::os::unix::process::ExitStatusExt).
|
2021-03-03 12:17:16 +00:00
|
|
|
|
///
|
|
|
|
|
/// If the process finished by calling `exit` with a nonzero value, this will return
|
|
|
|
|
/// that exit status.
|
|
|
|
|
///
|
|
|
|
|
/// If the error was something else, it will return `None`.
|
|
|
|
|
///
|
|
|
|
|
/// If the process exited successfully (ie, by calling `exit(0)`), there is no
|
|
|
|
|
/// `ExitStatusError`. So the return value from `ExitStatusError::code()` is always nonzero.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// #![feature(exit_status_error)]
|
|
|
|
|
/// # #[cfg(unix)] {
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err();
|
|
|
|
|
/// assert_eq!(bad.code(), Some(1));
|
|
|
|
|
/// # } // #[cfg(unix)]
|
|
|
|
|
/// ```
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2021-03-03 12:17:16 +00:00
|
|
|
|
pub fn code(&self) -> Option<i32> {
|
|
|
|
|
self.code_nonzero().map(Into::into)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Reports the exit code, if applicable, from an `ExitStatusError`, as a `NonZero`
|
|
|
|
|
///
|
2021-06-25 20:18:56 +00:00
|
|
|
|
/// This is exactly like [`code()`](Self::code), except that it returns a `NonZeroI32`.
|
2021-03-03 12:17:16 +00:00
|
|
|
|
///
|
|
|
|
|
/// Plain `code`, returning a plain integer, is provided because is is often more convenient.
|
|
|
|
|
/// The returned value from `code()` is indeed also nonzero; use `code_nonzero()` when you want
|
|
|
|
|
/// a type-level guarantee of nonzeroness.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// #![feature(exit_status_error)]
|
|
|
|
|
/// # if cfg!(unix) {
|
|
|
|
|
/// use std::num::NonZeroI32;
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err();
|
|
|
|
|
/// assert_eq!(bad.code_nonzero().unwrap(), NonZeroI32::try_from(1).unwrap());
|
|
|
|
|
/// # } // cfg!(unix)
|
|
|
|
|
/// ```
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2021-03-03 12:17:16 +00:00
|
|
|
|
pub fn code_nonzero(&self) -> Option<NonZeroI32> {
|
|
|
|
|
self.0.code()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Converts an `ExitStatusError` (back) to an `ExitStatus`.
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2021-03-03 12:17:16 +00:00
|
|
|
|
pub fn into_status(&self) -> ExitStatus {
|
|
|
|
|
ExitStatus(self.0.into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unstable(feature = "exit_status_error", issue = "84908")]
|
|
|
|
|
impl Into<ExitStatus> for ExitStatusError {
|
|
|
|
|
fn into(self) -> ExitStatus {
|
|
|
|
|
ExitStatus(self.0.into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unstable(feature = "exit_status_error", issue = "84908")]
|
|
|
|
|
impl fmt::Display for ExitStatusError {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-05-04 13:31:48 +00:00
|
|
|
|
write!(f, "process exited unsuccessfully: {}", self.into_status())
|
2021-03-03 12:17:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-05 00:29:52 +00:00
|
|
|
|
#[unstable(feature = "exit_status_error", issue = "84908")]
|
|
|
|
|
impl crate::error::Error for ExitStatusError {}
|
|
|
|
|
|
2022-02-09 23:12:17 +00:00
|
|
|
|
/// This type represents the status code the current process can return
|
|
|
|
|
/// to its parent under normal termination.
|
|
|
|
|
///
|
2022-03-27 23:38:01 +00:00
|
|
|
|
/// `ExitCode` is intended to be consumed only by the standard library (via
|
|
|
|
|
/// [`Termination::report()`]), and intentionally does not provide accessors like
|
2022-02-09 23:12:17 +00:00
|
|
|
|
/// `PartialEq`, `Eq`, or `Hash`. Instead the standard library provides the
|
|
|
|
|
/// canonical `SUCCESS` and `FAILURE` exit codes as well as `From<u8> for
|
|
|
|
|
/// ExitCode` for constructing other arbitrary exit codes.
|
|
|
|
|
///
|
|
|
|
|
/// # Portability
|
2018-02-27 18:31:17 +00:00
|
|
|
|
///
|
|
|
|
|
/// Numeric values used in this type don't have portable meanings, and
|
|
|
|
|
/// different platforms may mask different amounts of them.
|
|
|
|
|
///
|
|
|
|
|
/// For the platform's canonical successful and unsuccessful codes, see
|
|
|
|
|
/// the [`SUCCESS`] and [`FAILURE`] associated items.
|
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`SUCCESS`]: ExitCode::SUCCESS
|
|
|
|
|
/// [`FAILURE`]: ExitCode::FAILURE
|
2018-02-27 18:31:17 +00:00
|
|
|
|
///
|
2022-02-09 23:12:17 +00:00
|
|
|
|
/// # Differences from `ExitStatus`
|
2018-02-27 18:31:17 +00:00
|
|
|
|
///
|
2022-02-09 23:12:17 +00:00
|
|
|
|
/// `ExitCode` is intended for terminating the currently running process, via
|
|
|
|
|
/// the `Termination` trait, in contrast to [`ExitStatus`], which represents the
|
|
|
|
|
/// termination of a child process. These APIs are separate due to platform
|
|
|
|
|
/// compatibility differences and their expected usage; it is not generally
|
|
|
|
|
/// possible to exactly reproduce an ExitStatus from a child for the current
|
|
|
|
|
/// process after the fact.
|
2022-03-27 23:38:01 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// `ExitCode` can be returned from the `main` function of a crate, as it implements
|
|
|
|
|
/// [`Termination`]:
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// use std::process::ExitCode;
|
|
|
|
|
/// # fn check_foo() -> bool { true }
|
2018-02-27 18:31:17 +00:00
|
|
|
|
///
|
2022-03-27 23:38:01 +00:00
|
|
|
|
/// fn main() -> ExitCode {
|
|
|
|
|
/// if !check_foo() {
|
|
|
|
|
/// return ExitCode::from(42);
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// ExitCode::SUCCESS
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2018-02-24 08:31:33 +00:00
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
2018-03-04 02:29:30 +00:00
|
|
|
|
pub struct ExitCode(imp::ExitCode);
|
2018-02-24 08:31:33 +00:00
|
|
|
|
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
2018-02-27 18:31:17 +00:00
|
|
|
|
impl ExitCode {
|
2022-03-27 23:38:01 +00:00
|
|
|
|
/// The canonical `ExitCode` for successful termination on this platform.
|
2018-02-27 18:31:17 +00:00
|
|
|
|
///
|
|
|
|
|
/// Note that a `()`-returning `main` implicitly results in a successful
|
|
|
|
|
/// termination, so there's no need to return this from `main` unless
|
|
|
|
|
/// you're also returning other possible codes.
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
2018-03-04 02:29:30 +00:00
|
|
|
|
pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS);
|
2018-02-27 18:31:17 +00:00
|
|
|
|
|
2022-03-27 23:38:01 +00:00
|
|
|
|
/// The canonical `ExitCode` for unsuccessful termination on this platform.
|
2018-02-27 18:31:17 +00:00
|
|
|
|
///
|
|
|
|
|
/// If you're only returning this and `SUCCESS` from `main`, consider
|
|
|
|
|
/// instead returning `Err(_)` and `Ok(())` respectively, which will
|
|
|
|
|
/// return the same codes (but will also `eprintln!` the error).
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
2018-03-04 02:29:30 +00:00
|
|
|
|
pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
|
2022-03-27 05:50:24 +00:00
|
|
|
|
|
|
|
|
|
/// Exit the current process with the given `ExitCode`.
|
|
|
|
|
///
|
|
|
|
|
/// Note that this has the same caveats as [`process::exit()`][exit], namely that this function
|
|
|
|
|
/// terminates the process immediately, so no destructors on the current stack or any other
|
|
|
|
|
/// thread's stack will be run. If a clean shutdown is needed, it is recommended to simply
|
|
|
|
|
/// return this ExitCode from the `main` function, as demonstrated in the [type
|
|
|
|
|
/// documentation](#examples).
|
|
|
|
|
///
|
|
|
|
|
/// # Differences from `process::exit()`
|
|
|
|
|
///
|
|
|
|
|
/// `process::exit()` accepts any `i32` value as the exit code for the process; however, there
|
|
|
|
|
/// are platforms that only use a subset of that value (see [`process::exit` platform-specific
|
|
|
|
|
/// behavior][exit#platform-specific-behavior]). `ExitCode` exists because of this; only
|
|
|
|
|
/// `ExitCode`s that are valid on all platforms can be created, so those problems don't exist
|
|
|
|
|
/// with this method.
|
|
|
|
|
#[unstable(feature = "exitcode_exit_method", issue = "none")]
|
|
|
|
|
pub fn exit_process(self) -> ! {
|
|
|
|
|
exit(self.to_i32())
|
|
|
|
|
}
|
2018-02-27 18:31:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-28 20:53:36 +00:00
|
|
|
|
impl ExitCode {
|
2022-03-27 23:38:01 +00:00
|
|
|
|
// This is private/perma-unstable because ExitCode is opaque; we don't know that i32 will serve
|
2022-01-28 20:53:36 +00:00
|
|
|
|
// all usecases, for example windows seems to use u32, unix uses the 8-15th bits of an i32, we
|
|
|
|
|
// likely want to isolate users anything that could restrict the platform specific
|
|
|
|
|
// representation of an ExitCode
|
|
|
|
|
//
|
|
|
|
|
// More info: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426
|
2022-03-27 23:38:01 +00:00
|
|
|
|
/// Convert an `ExitCode` into an i32
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[unstable(
|
|
|
|
|
feature = "process_exitcode_internals",
|
|
|
|
|
reason = "exposed only for libstd",
|
|
|
|
|
issue = "none"
|
|
|
|
|
)]
|
2022-01-31 19:57:17 +00:00
|
|
|
|
#[inline]
|
2022-03-27 23:38:01 +00:00
|
|
|
|
#[doc(hidden)]
|
2022-01-28 20:53:36 +00:00
|
|
|
|
pub fn to_i32(self) -> i32 {
|
|
|
|
|
self.0.as_i32()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "process_exitcode", since = "1.60.0")]
|
2022-01-28 22:07:27 +00:00
|
|
|
|
impl From<u8> for ExitCode {
|
2022-03-27 23:38:01 +00:00
|
|
|
|
/// Construct an `ExitCode` from an arbitrary u8 value.
|
2022-01-28 22:07:27 +00:00
|
|
|
|
fn from(code: u8) -> Self {
|
|
|
|
|
ExitCode(imp::ExitCode::from(code))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 17:42:57 +00:00
|
|
|
|
impl Child {
|
2018-04-17 07:00:48 +00:00
|
|
|
|
/// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
|
2018-03-29 17:10:40 +00:00
|
|
|
|
/// error is returned.
|
|
|
|
|
///
|
2021-05-27 12:03:35 +00:00
|
|
|
|
/// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function.
|
2018-03-28 17:54:34 +00:00
|
|
|
|
///
|
|
|
|
|
/// This is equivalent to sending a SIGKILL on Unix platforms.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let mut command = Command::new("yes");
|
|
|
|
|
/// if let Ok(mut child) = command.spawn() {
|
|
|
|
|
/// child.kill().expect("command wasn't running");
|
|
|
|
|
/// } else {
|
|
|
|
|
/// println!("yes command didn't start");
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2018-03-28 22:05:51 +00:00
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [`ErrorKind`]: io::ErrorKind
|
|
|
|
|
/// [`InvalidInput`]: io::ErrorKind::InvalidInput
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub fn kill(&mut self) -> io::Result<()> {
|
2016-02-04 02:09:35 +00:00
|
|
|
|
self.handle.kill()
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 16:44:05 +00:00
|
|
|
|
/// Returns the OS-assigned process identifier associated with this child.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let mut command = Command::new("ls");
|
|
|
|
|
/// if let Ok(child) = command.spawn() {
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// println!("Child's ID is {}", child.id());
|
2016-04-28 10:42:42 +00:00
|
|
|
|
/// } else {
|
|
|
|
|
/// println!("ls command didn't start");
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2015-07-28 22:44:30 +00:00
|
|
|
|
#[stable(feature = "process_id", since = "1.3.0")]
|
2015-04-16 16:44:05 +00:00
|
|
|
|
pub fn id(&self) -> u32 {
|
|
|
|
|
self.handle.id()
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 14:21:32 +00:00
|
|
|
|
/// Waits for the child to exit completely, returning the status that it
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// exited with. This function will continue to have the same return value
|
|
|
|
|
/// after it has been called at least once.
|
|
|
|
|
///
|
|
|
|
|
/// The stdin handle to the child process, if any, will be closed
|
|
|
|
|
/// before waiting. This helps avoid deadlock: it ensures that the
|
|
|
|
|
/// child does not block waiting for input from the parent, while
|
|
|
|
|
/// the parent waits for the child to exit.
|
2016-04-28 10:42:42 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let mut command = Command::new("ls");
|
|
|
|
|
/// if let Ok(mut child) = command.spawn() {
|
|
|
|
|
/// child.wait().expect("command wasn't running");
|
|
|
|
|
/// println!("Child has finished its execution!");
|
|
|
|
|
/// } else {
|
|
|
|
|
/// println!("ls command didn't start");
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
|
|
|
|
drop(self.stdin.take());
|
2016-02-04 02:09:35 +00:00
|
|
|
|
self.handle.wait().map(ExitStatus)
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-01-06 06:47:09 +00:00
|
|
|
|
/// Attempts to collect the exit status of the child if it has already
|
|
|
|
|
/// exited.
|
|
|
|
|
///
|
2018-11-12 18:05:20 +00:00
|
|
|
|
/// This function will not block the calling thread and will only
|
2017-01-06 06:47:09 +00:00
|
|
|
|
/// check to see if the child process has exited or not. If the child has
|
2019-02-09 22:16:58 +00:00
|
|
|
|
/// exited then on Unix the process ID is reaped. This function is
|
2017-01-06 06:47:09 +00:00
|
|
|
|
/// guaranteed to repeatedly return a successful exit status so long as the
|
|
|
|
|
/// child has already exited.
|
|
|
|
|
///
|
2017-02-03 22:39:41 +00:00
|
|
|
|
/// If the child has exited, then `Ok(Some(status))` is returned. If the
|
|
|
|
|
/// exit status is not available at this time then `Ok(None)` is returned.
|
|
|
|
|
/// If an error occurs, then that error is returned.
|
2017-01-06 06:47:09 +00:00
|
|
|
|
///
|
|
|
|
|
/// Note that unlike `wait`, this function will not attempt to drop stdin.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process::Command;
|
|
|
|
|
///
|
|
|
|
|
/// let mut child = Command::new("ls").spawn().unwrap();
|
|
|
|
|
///
|
|
|
|
|
/// match child.try_wait() {
|
2022-02-12 19:16:17 +00:00
|
|
|
|
/// Ok(Some(status)) => println!("exited with: {status}"),
|
2017-02-03 22:39:41 +00:00
|
|
|
|
/// Ok(None) => {
|
2017-01-06 06:47:09 +00:00
|
|
|
|
/// println!("status not ready yet, let's really wait");
|
|
|
|
|
/// let res = child.wait();
|
2022-02-12 19:16:17 +00:00
|
|
|
|
/// println!("result: {res:?}");
|
2017-01-06 06:47:09 +00:00
|
|
|
|
/// }
|
2022-02-12 19:16:17 +00:00
|
|
|
|
/// Err(e) => println!("error attempting to wait: {e}"),
|
2017-01-06 06:47:09 +00:00
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2017-05-11 04:17:24 +00:00
|
|
|
|
#[stable(feature = "process_try_wait", since = "1.18.0")]
|
2017-02-03 22:39:41 +00:00
|
|
|
|
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
|
|
|
|
|
Ok(self.handle.try_wait()?.map(ExitStatus))
|
2017-01-06 06:47:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-13 14:21:32 +00:00
|
|
|
|
/// Simultaneously waits for the child to exit and collect all remaining
|
2015-12-02 04:12:01 +00:00
|
|
|
|
/// output on the stdout/stderr handles, returning an `Output`
|
2015-02-06 17:42:57 +00:00
|
|
|
|
/// instance.
|
|
|
|
|
///
|
|
|
|
|
/// The stdin handle to the child process, if any, will be closed
|
|
|
|
|
/// before waiting. This helps avoid deadlock: it ensures that the
|
|
|
|
|
/// child does not block waiting for input from the parent, while
|
|
|
|
|
/// the parent waits for the child to exit.
|
2016-03-18 15:11:37 +00:00
|
|
|
|
///
|
|
|
|
|
/// By default, stdin, stdout and stderr are inherited from the parent.
|
|
|
|
|
/// In order to capture the output into this `Result<Output>` it is
|
|
|
|
|
/// necessary to create new pipes between parent and child. Use
|
2016-03-19 20:07:47 +00:00
|
|
|
|
/// `stdout(Stdio::piped())` or `stderr(Stdio::piped())`, respectively.
|
2016-03-18 15:11:37 +00:00
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
2016-03-19 09:41:13 +00:00
|
|
|
|
/// ```should_panic
|
2016-03-18 15:11:37 +00:00
|
|
|
|
/// use std::process::{Command, Stdio};
|
|
|
|
|
///
|
2016-06-16 21:20:22 +00:00
|
|
|
|
/// let child = Command::new("/bin/cat")
|
|
|
|
|
/// .arg("file.txt")
|
|
|
|
|
/// .stdout(Stdio::piped())
|
|
|
|
|
/// .spawn()
|
|
|
|
|
/// .expect("failed to execute child");
|
2016-03-18 15:11:37 +00:00
|
|
|
|
///
|
2016-06-16 21:20:22 +00:00
|
|
|
|
/// let output = child
|
|
|
|
|
/// .wait_with_output()
|
|
|
|
|
/// .expect("failed to wait on child");
|
2016-03-18 15:11:37 +00:00
|
|
|
|
///
|
2016-06-16 21:20:22 +00:00
|
|
|
|
/// assert!(output.status.success());
|
2016-03-18 15:11:37 +00:00
|
|
|
|
/// ```
|
|
|
|
|
///
|
2015-02-28 00:23:21 +00:00
|
|
|
|
#[stable(feature = "process", since = "1.0.0")]
|
2015-02-06 17:42:57 +00:00
|
|
|
|
pub fn wait_with_output(mut self) -> io::Result<Output> {
|
|
|
|
|
drop(self.stdin.take());
|
2016-02-12 18:29:25 +00:00
|
|
|
|
|
|
|
|
|
let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
|
|
|
|
|
match (self.stdout.take(), self.stderr.take()) {
|
|
|
|
|
(None, None) => {}
|
|
|
|
|
(Some(mut out), None) => {
|
|
|
|
|
let res = out.read_to_end(&mut stdout);
|
|
|
|
|
res.unwrap();
|
|
|
|
|
}
|
|
|
|
|
(None, Some(mut err)) => {
|
|
|
|
|
let res = err.read_to_end(&mut stderr);
|
|
|
|
|
res.unwrap();
|
|
|
|
|
}
|
|
|
|
|
(Some(out), Some(err)) => {
|
|
|
|
|
let res = read2(out.inner, &mut stdout, err.inner, &mut stderr);
|
|
|
|
|
res.unwrap();
|
|
|
|
|
}
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-23 03:01:37 +00:00
|
|
|
|
let status = self.wait()?;
|
2019-11-27 18:29:00 +00:00
|
|
|
|
Ok(Output { status, stdout, stderr })
|
2015-02-06 17:42:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-31 21:41:59 +00:00
|
|
|
|
/// Terminates the current process with the specified exit code.
|
|
|
|
|
///
|
|
|
|
|
/// This function will never return and will immediately terminate the current
|
|
|
|
|
/// process. The exit code is passed through to the underlying OS and will be
|
|
|
|
|
/// available for consumption by another process.
|
|
|
|
|
///
|
|
|
|
|
/// Note that because this function never returns, and that it terminates the
|
|
|
|
|
/// process, no destructors on the current stack or any other thread's stack
|
|
|
|
|
/// will be run. If a clean shutdown is needed it is recommended to only call
|
|
|
|
|
/// this function at a known point where there are no more destructors left
|
|
|
|
|
/// to run.
|
2016-12-03 23:46:28 +00:00
|
|
|
|
///
|
2016-12-15 21:07:37 +00:00
|
|
|
|
/// ## Platform-specific behavior
|
|
|
|
|
///
|
|
|
|
|
/// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit`
|
|
|
|
|
/// will be visible to a parent process inspecting the exit code. On most
|
|
|
|
|
/// Unix-like platforms, only the eight least-significant bits are considered.
|
|
|
|
|
///
|
2016-12-03 23:46:28 +00:00
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
2016-12-21 19:42:07 +00:00
|
|
|
|
/// Due to this function’s behavior regarding destructors, a conventional way
|
|
|
|
|
/// to use the function is to extract the actual computation to another
|
|
|
|
|
/// function and compute the exit code from its return value:
|
|
|
|
|
///
|
2016-12-03 23:46:28 +00:00
|
|
|
|
/// ```
|
2016-12-21 19:42:07 +00:00
|
|
|
|
/// fn run_app() -> Result<(), ()> {
|
|
|
|
|
/// // Application logic here
|
|
|
|
|
/// Ok(())
|
|
|
|
|
/// }
|
2016-12-03 23:46:28 +00:00
|
|
|
|
///
|
2016-12-21 19:42:07 +00:00
|
|
|
|
/// fn main() {
|
2019-10-20 18:13:47 +00:00
|
|
|
|
/// std::process::exit(match run_app() {
|
|
|
|
|
/// Ok(_) => 0,
|
|
|
|
|
/// Err(err) => {
|
2022-02-12 19:16:17 +00:00
|
|
|
|
/// eprintln!("error: {err:?}");
|
2019-10-20 18:13:47 +00:00
|
|
|
|
/// 1
|
|
|
|
|
/// }
|
2016-12-21 19:42:07 +00:00
|
|
|
|
/// });
|
|
|
|
|
/// }
|
2016-12-03 23:46:28 +00:00
|
|
|
|
/// ```
|
2016-12-15 21:07:37 +00:00
|
|
|
|
///
|
|
|
|
|
/// Due to [platform-specific behavior], the exit code for this example will be
|
|
|
|
|
/// `0` on Linux, but `256` on Windows:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process;
|
|
|
|
|
///
|
2017-05-02 00:38:59 +00:00
|
|
|
|
/// process::exit(0x0100);
|
2016-12-15 21:07:37 +00:00
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// [platform-specific behavior]: #platform-specific-behavior
|
2015-03-31 21:41:59 +00:00
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
|
pub fn exit(code: i32) -> ! {
|
2021-09-16 12:28:21 +00:00
|
|
|
|
crate::rt::cleanup();
|
2019-02-10 19:23:21 +00:00
|
|
|
|
crate::sys::os::exit(code)
|
2015-03-31 21:41:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-11-17 17:31:14 +00:00
|
|
|
|
/// Terminates the process in an abnormal fashion.
|
|
|
|
|
///
|
|
|
|
|
/// The function will never return and will immediately terminate the current
|
|
|
|
|
/// process in a platform specific "abnormal" manner.
|
|
|
|
|
///
|
|
|
|
|
/// Note that because this function never returns, and that it terminates the
|
|
|
|
|
/// process, no destructors on the current stack or any other thread's stack
|
2017-09-27 21:47:21 +00:00
|
|
|
|
/// will be run.
|
|
|
|
|
///
|
2021-05-17 14:29:47 +00:00
|
|
|
|
/// Rust IO buffers (eg, from `BufWriter`) will not be flushed.
|
|
|
|
|
/// Likewise, C stdio buffers will (on most platforms) not be flushed.
|
|
|
|
|
///
|
2017-09-27 21:47:21 +00:00
|
|
|
|
/// This is in contrast to the default behaviour of [`panic!`] which unwinds
|
|
|
|
|
/// the current thread's stack and calls all destructors.
|
|
|
|
|
/// When `panic="abort"` is set, either as an argument to `rustc` or in a
|
2017-10-02 18:59:50 +00:00
|
|
|
|
/// crate's Cargo.toml, [`panic!`] and `abort` are similar. However,
|
|
|
|
|
/// [`panic!`] will still call the [panic hook] while `abort` will not.
|
2017-09-27 21:47:21 +00:00
|
|
|
|
///
|
|
|
|
|
/// If a clean shutdown is needed it is recommended to only call
|
2016-11-17 17:31:14 +00:00
|
|
|
|
/// this function at a known point where there are no more destructors left
|
|
|
|
|
/// to run.
|
2017-03-29 13:59:22 +00:00
|
|
|
|
///
|
2021-05-13 17:59:41 +00:00
|
|
|
|
/// The process's termination will be similar to that from the C `abort()`
|
2021-07-05 10:43:45 +00:00
|
|
|
|
/// function. On Unix, the process will terminate with signal `SIGABRT`, which
|
2021-05-13 17:59:41 +00:00
|
|
|
|
/// typically means that the shell prints "Aborted".
|
|
|
|
|
///
|
2017-03-29 13:59:22 +00:00
|
|
|
|
/// # Examples
|
2017-03-29 14:19:23 +00:00
|
|
|
|
///
|
2017-03-30 07:55:44 +00:00
|
|
|
|
/// ```no_run
|
2017-03-29 13:59:22 +00:00
|
|
|
|
/// use std::process;
|
2017-03-29 14:30:39 +00:00
|
|
|
|
///
|
2017-03-29 13:59:22 +00:00
|
|
|
|
/// fn main() {
|
|
|
|
|
/// println!("aborting");
|
2017-03-29 14:30:39 +00:00
|
|
|
|
///
|
2017-03-29 13:59:22 +00:00
|
|
|
|
/// process::abort();
|
2017-03-29 14:30:39 +00:00
|
|
|
|
///
|
2017-03-29 13:59:22 +00:00
|
|
|
|
/// // execution never gets here
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2017-04-05 18:41:43 +00:00
|
|
|
|
///
|
2017-09-27 20:13:07 +00:00
|
|
|
|
/// The `abort` function terminates the process, so the destructor will not
|
2017-04-06 08:17:32 +00:00
|
|
|
|
/// get run on the example below:
|
2017-04-05 18:41:43 +00:00
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
|
|
|
|
/// use std::process;
|
|
|
|
|
///
|
|
|
|
|
/// struct HasDrop;
|
|
|
|
|
///
|
|
|
|
|
/// impl Drop for HasDrop {
|
|
|
|
|
/// fn drop(&mut self) {
|
|
|
|
|
/// println!("This will never be printed!");
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// fn main() {
|
|
|
|
|
/// let _x = HasDrop;
|
|
|
|
|
/// process::abort();
|
|
|
|
|
/// // the destructor implemented for HasDrop will never get run
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
2017-09-27 21:47:21 +00:00
|
|
|
|
///
|
2020-08-12 01:02:24 +00:00
|
|
|
|
/// [panic hook]: crate::panic::set_hook
|
2017-03-15 03:52:20 +00:00
|
|
|
|
#[stable(feature = "process_abort", since = "1.17.0")]
|
2020-11-18 17:15:03 +00:00
|
|
|
|
#[cold]
|
2016-11-17 17:31:14 +00:00
|
|
|
|
pub fn abort() -> ! {
|
2020-05-17 17:37:44 +00:00
|
|
|
|
crate::sys::abort_internal();
|
2016-11-17 17:31:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-06 05:49:36 +00:00
|
|
|
|
/// Returns the OS-assigned process identifier associated with this process.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// Basic usage:
|
|
|
|
|
///
|
|
|
|
|
/// ```no_run
|
2017-10-08 02:59:58 +00:00
|
|
|
|
/// use std::process;
|
2017-10-06 05:49:36 +00:00
|
|
|
|
///
|
2017-10-08 02:59:58 +00:00
|
|
|
|
/// println!("My pid is {}", process::id());
|
2017-10-06 05:49:36 +00:00
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
///
|
2021-10-31 03:37:32 +00:00
|
|
|
|
#[must_use]
|
2018-04-03 01:34:06 +00:00
|
|
|
|
#[stable(feature = "getpid", since = "1.26.0")]
|
2017-10-08 02:59:58 +00:00
|
|
|
|
pub fn id() -> u32 {
|
2019-02-10 19:23:21 +00:00
|
|
|
|
crate::sys::os::getpid()
|
2017-10-06 05:49:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-02-22 22:36:55 +00:00
|
|
|
|
/// A trait for implementing arbitrary return types in the `main` function.
|
|
|
|
|
///
|
2019-09-05 16:15:28 +00:00
|
|
|
|
/// The C-main function only supports to return integers as return type.
|
2018-02-22 22:36:55 +00:00
|
|
|
|
/// So, every type implementing the `Termination` trait has to be converted
|
|
|
|
|
/// to an integer.
|
|
|
|
|
///
|
|
|
|
|
/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
|
|
|
|
|
/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
|
2022-03-22 14:37:17 +00:00
|
|
|
|
///
|
2022-03-22 15:33:08 +00:00
|
|
|
|
/// Because different runtimes have different specifications on the return value
|
|
|
|
|
/// of the `main` function, this trait is likely to be available only on
|
|
|
|
|
/// standard library's runtime for convenience. Other runtimes are not required
|
|
|
|
|
/// to provide similar functionality.
|
2018-02-22 22:36:55 +00:00
|
|
|
|
#[cfg_attr(not(test), lang = "termination")]
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
2018-03-22 04:28:48 +00:00
|
|
|
|
#[rustc_on_unimplemented(
|
2019-11-27 18:29:00 +00:00
|
|
|
|
message = "`main` has invalid return type `{Self}`",
|
|
|
|
|
label = "`main` can only return types that implement `{Termination}`"
|
|
|
|
|
)]
|
2018-02-22 22:36:55 +00:00
|
|
|
|
pub trait Termination {
|
|
|
|
|
/// Is called to get the representation of the value as status code.
|
|
|
|
|
/// This status code is returned to the operating system.
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
2022-01-28 20:53:36 +00:00
|
|
|
|
fn report(self) -> ExitCode;
|
2018-02-22 22:36:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
2018-02-22 22:36:55 +00:00
|
|
|
|
impl Termination for () {
|
2018-04-05 18:07:19 +00:00
|
|
|
|
#[inline]
|
2022-01-28 20:53:36 +00:00
|
|
|
|
fn report(self) -> ExitCode {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
ExitCode::SUCCESS.report()
|
|
|
|
|
}
|
2018-02-22 22:36:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
2018-02-24 08:31:33 +00:00
|
|
|
|
impl<E: fmt::Debug> Termination for Result<(), E> {
|
2022-01-28 20:53:36 +00:00
|
|
|
|
fn report(self) -> ExitCode {
|
2018-02-22 22:36:55 +00:00
|
|
|
|
match self {
|
2018-02-27 18:31:17 +00:00
|
|
|
|
Ok(()) => ().report(),
|
|
|
|
|
Err(err) => Err::<!, _>(err).report(),
|
2018-02-22 22:36:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
2018-02-22 22:36:55 +00:00
|
|
|
|
impl Termination for ! {
|
2022-01-28 20:53:36 +00:00
|
|
|
|
fn report(self) -> ExitCode {
|
2019-11-27 18:29:00 +00:00
|
|
|
|
self
|
|
|
|
|
}
|
2018-02-22 22:36:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
2018-02-24 08:31:33 +00:00
|
|
|
|
impl<E: fmt::Debug> Termination for Result<!, E> {
|
2022-01-28 20:53:36 +00:00
|
|
|
|
fn report(self) -> ExitCode {
|
2018-02-24 08:31:33 +00:00
|
|
|
|
let Err(err) = self;
|
2022-02-12 19:16:17 +00:00
|
|
|
|
eprintln!("Error: {err:?}");
|
2018-02-27 18:31:17 +00:00
|
|
|
|
ExitCode::FAILURE.report()
|
2018-02-22 22:36:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
2021-09-02 20:03:41 +00:00
|
|
|
|
impl<E: fmt::Debug> Termination for Result<Infallible, E> {
|
2022-01-28 20:53:36 +00:00
|
|
|
|
fn report(self) -> ExitCode {
|
2021-09-02 20:03:41 +00:00
|
|
|
|
let Err(err) = self;
|
2021-09-03 15:24:25 +00:00
|
|
|
|
Err::<!, _>(err).report()
|
2021-09-02 20:03:41 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 23:12:17 +00:00
|
|
|
|
#[stable(feature = "termination_trait_lib", since = "1.60.0")]
|
2018-02-24 08:31:33 +00:00
|
|
|
|
impl Termination for ExitCode {
|
2018-04-05 18:07:19 +00:00
|
|
|
|
#[inline]
|
2022-01-28 20:53:36 +00:00
|
|
|
|
fn report(self) -> ExitCode {
|
|
|
|
|
self
|
2018-02-22 22:36:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|