#![stable(feature = "process", since = "1.0.0")]
#![deny(unsafe_op_in_unsafe_fn)]
#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
mod tests;
use crate::io::prelude::*;
use crate::convert::Infallible;
use crate::ffi::OsStr;
use crate::fmt;
use crate::fs;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::num::NonZeroI32;
use crate::path::Path;
use crate::str;
use crate::sys::pipe::{read2, AnonPipe};
use crate::sys::process as imp;
#[stable(feature = "command_access", since = "1.57.0")]
pub use crate::sys_common::process::CommandEnvs;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
#[stable(feature = "process", since = "1.0.0")]
pub struct Child {
pub(crate) handle: imp::Process,
#[stable(feature = "process", since = "1.0.0")]
pub stdin: Option<ChildStdin>,
#[stable(feature = "process", since = "1.0.0")]
pub stdout: Option<ChildStdout>,
#[stable(feature = "process", since = "1.0.0")]
pub stderr: Option<ChildStderr>,
}
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for Child {}
impl AsInner<imp::Process> for Child {
fn as_inner(&self) -> &imp::Process {
&self.handle
}
}
impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child {
Child {
handle,
stdin: io.stdin.map(ChildStdin::from_inner),
stdout: io.stdout.map(ChildStdout::from_inner),
stderr: io.stderr.map(ChildStderr::from_inner),
}
}
}
impl IntoInner<imp::Process> for Child {
fn into_inner(self) -> imp::Process {
self.handle
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Child {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Child")
.field("stdin", &self.stdin)
.field("stdout", &self.stdout)
.field("stderr", &self.stderr)
.finish_non_exhaustive()
}
}
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdin {
inner: AnonPipe,
}
#[stable(feature = "process", since = "1.0.0")]
impl Write for ChildStdin {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
(&*self).write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
(&*self).write_vectored(bufs)
}
fn is_write_vectored(&self) -> bool {
io::Write::is_write_vectored(&&*self)
}
fn flush(&mut self) -> io::Result<()> {
(&*self).flush()
}
}
#[stable(feature = "write_mt", since = "1.48.0")]
impl Write for &ChildStdin {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf)
}
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.inner.write_vectored(bufs)
}
fn is_write_vectored(&self) -> bool {
self.inner.is_write_vectored()
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl AsInner<AnonPipe> for ChildStdin {
fn as_inner(&self) -> &AnonPipe {
&self.inner
}
}
impl IntoInner<AnonPipe> for ChildStdin {
fn into_inner(self) -> AnonPipe {
self.inner
}
}
impl FromInner<AnonPipe> for ChildStdin {
fn from_inner(pipe: AnonPipe) -> ChildStdin {
ChildStdin { inner: pipe }
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for ChildStdin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ChildStdin").finish_non_exhaustive()
}
}
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdout {
inner: AnonPipe,
}
#[stable(feature = "process", since = "1.0.0")]
impl Read for ChildStdout {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
self.inner.read_buf(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.read_vectored(bufs)
}
#[inline]
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
}
impl AsInner<AnonPipe> for ChildStdout {
fn as_inner(&self) -> &AnonPipe {
&self.inner
}
}
impl IntoInner<AnonPipe> for ChildStdout {
fn into_inner(self) -> AnonPipe {
self.inner
}
}
impl FromInner<AnonPipe> for ChildStdout {
fn from_inner(pipe: AnonPipe) -> ChildStdout {
ChildStdout { inner: pipe }
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for ChildStdout {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ChildStdout").finish_non_exhaustive()
}
}
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStderr {
inner: AnonPipe,
}
#[stable(feature = "process", since = "1.0.0")]
impl Read for ChildStderr {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
self.inner.read_buf(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.read_vectored(bufs)
}
#[inline]
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}
}
impl AsInner<AnonPipe> for ChildStderr {
fn as_inner(&self) -> &AnonPipe {
&self.inner
}
}
impl IntoInner<AnonPipe> for ChildStderr {
fn into_inner(self) -> AnonPipe {
self.inner
}
}
impl FromInner<AnonPipe> for ChildStderr {
fn from_inner(pipe: AnonPipe) -> ChildStderr {
ChildStderr { inner: pipe }
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for ChildStderr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ChildStderr").finish_non_exhaustive()
}
}
#[stable(feature = "process", since = "1.0.0")]
pub struct Command {
inner: imp::Command,
}
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for Command {}
impl Command {
#[stable(feature = "process", since = "1.0.0")]
pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
Command { inner: imp::Command::new(program.as_ref()) }
}
#[stable(feature = "process", since = "1.0.0")]
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
self.inner.arg(arg.as_ref());
self
}
#[stable(feature = "process", since = "1.0.0")]
pub fn args<I, S>(&mut self, args: I) -> &mut Command
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
for arg in args {
self.arg(arg.as_ref());
}
self
}
#[stable(feature = "process", since = "1.0.0")]
pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
where
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
self.inner.env_mut().set(key.as_ref(), val.as_ref());
self
}
#[stable(feature = "command_envs", since = "1.19.0")]
pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
where
I: IntoIterator<Item = (K, V)>,
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
for (ref key, ref val) in vars {
self.inner.env_mut().set(key.as_ref(), val.as_ref());
}
self
}
#[stable(feature = "process", since = "1.0.0")]
pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
self.inner.env_mut().remove(key.as_ref());
self
}
#[stable(feature = "process", since = "1.0.0")]
pub fn env_clear(&mut self) -> &mut Command {
self.inner.env_mut().clear();
self
}
#[stable(feature = "process", since = "1.0.0")]
pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
self.inner.cwd(dir.as_ref().as_ref());
self
}
#[stable(feature = "process", since = "1.0.0")]
pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
self.inner.stdin(cfg.into().0);
self
}
#[stable(feature = "process", since = "1.0.0")]
pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
self.inner.stdout(cfg.into().0);
self
}
#[stable(feature = "process", since = "1.0.0")]
pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
self.inner.stderr(cfg.into().0);
self
}
#[stable(feature = "process", since = "1.0.0")]
pub fn spawn(&mut self) -> io::Result<Child> {
self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
}
#[stable(feature = "process", since = "1.0.0")]
pub fn output(&mut self) -> io::Result<Output> {
let (status, stdout, stderr) = self.inner.output()?;
Ok(Output { status: ExitStatus(status), stdout, stderr })
}
#[stable(feature = "process", since = "1.0.0")]
pub fn status(&mut self) -> io::Result<ExitStatus> {
self.inner
.spawn(imp::Stdio::Inherit, true)
.map(Child::from_inner)
.and_then(|mut p| p.wait())
}
#[must_use]
#[stable(feature = "command_access", since = "1.57.0")]
pub fn get_program(&self) -> &OsStr {
self.inner.get_program()
}
#[stable(feature = "command_access", since = "1.57.0")]
pub fn get_args(&self) -> CommandArgs<'_> {
CommandArgs { inner: self.inner.get_args() }
}
#[stable(feature = "command_access", since = "1.57.0")]
pub fn get_envs(&self) -> CommandEnvs<'_> {
self.inner.get_envs()
}
#[must_use]
#[stable(feature = "command_access", since = "1.57.0")]
pub fn get_current_dir(&self) -> Option<&Path> {
self.inner.get_current_dir()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Command {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl AsInner<imp::Command> for Command {
fn as_inner(&self) -> &imp::Command {
&self.inner
}
}
impl AsInnerMut<imp::Command> for Command {
fn as_inner_mut(&mut self) -> &mut imp::Command {
&mut self.inner
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "command_access", since = "1.57.0")]
#[derive(Debug)]
pub struct CommandArgs<'a> {
inner: imp::CommandArgs<'a>,
}
#[stable(feature = "command_access", since = "1.57.0")]
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()
}
}
#[stable(feature = "command_access", since = "1.57.0")]
impl<'a> ExactSizeIterator for CommandArgs<'a> {
fn len(&self) -> usize {
self.inner.len()
}
fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
#[derive(PartialEq, Eq, Clone)]
#[stable(feature = "process", since = "1.0.0")]
pub struct Output {
#[stable(feature = "process", since = "1.0.0")]
pub status: ExitStatus,
#[stable(feature = "process", since = "1.0.0")]
pub stdout: Vec<u8>,
#[stable(feature = "process", since = "1.0.0")]
pub stderr: Vec<u8>,
}
#[stable(feature = "process_output_debug", since = "1.7.0")]
impl fmt::Debug for Output {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let stdout_utf8 = str::from_utf8(&self.stdout);
let stdout_debug: &dyn fmt::Debug = match stdout_utf8 {
Ok(ref str) => str,
Err(_) => &self.stdout,
};
let stderr_utf8 = str::from_utf8(&self.stderr);
let stderr_debug: &dyn fmt::Debug = match stderr_utf8 {
Ok(ref str) => str,
Err(_) => &self.stderr,
};
fmt.debug_struct("Output")
.field("status", &self.status)
.field("stdout", stdout_debug)
.field("stderr", stderr_debug)
.finish()
}
}
#[stable(feature = "process", since = "1.0.0")]
pub struct Stdio(imp::Stdio);
impl Stdio {
#[must_use]
#[stable(feature = "process", since = "1.0.0")]
pub fn piped() -> Stdio {
Stdio(imp::Stdio::MakePipe)
}
#[must_use]
#[stable(feature = "process", since = "1.0.0")]
pub fn inherit() -> Stdio {
Stdio(imp::Stdio::Inherit)
}
#[must_use]
#[stable(feature = "process", since = "1.0.0")]
pub fn null() -> Stdio {
Stdio(imp::Stdio::Null)
}
#[unstable(feature = "stdio_makes_pipe", issue = "98288")]
pub fn makes_pipe(&self) -> bool {
matches!(self.0, imp::Stdio::MakePipe)
}
}
impl FromInner<imp::Stdio> for Stdio {
fn from_inner(inner: imp::Stdio) -> Stdio {
Stdio(inner)
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stdio {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Stdio").finish_non_exhaustive()
}
}
#[stable(feature = "stdio_from", since = "1.20.0")]
impl From<ChildStdin> for Stdio {
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 {
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 {
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 {
fn from(file: fs::File) -> Stdio {
Stdio::from_inner(file.into_inner().into())
}
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[stable(feature = "process", since = "1.0.0")]
pub struct ExitStatus(imp::ExitStatus);
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for ExitStatus {}
impl ExitStatus {
#[unstable(feature = "exit_status_error", issue = "84908")]
pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
self.0.exit_ok().map_err(ExitStatusError)
}
#[must_use]
#[stable(feature = "process", since = "1.0.0")]
pub fn success(&self) -> bool {
self.0.exit_ok().is_ok()
}
#[must_use]
#[stable(feature = "process", since = "1.0.0")]
pub fn code(&self) -> Option<i32> {
self.0.code()
}
}
impl AsInner<imp::ExitStatus> for ExitStatus {
fn as_inner(&self) -> &imp::ExitStatus {
&self.0
}
}
impl FromInner<imp::ExitStatus> for ExitStatus {
fn from_inner(s: imp::ExitStatus) -> ExitStatus {
ExitStatus(s)
}
}
#[stable(feature = "process", since = "1.0.0")]
impl fmt::Display for ExitStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for ExitStatusError {}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[unstable(feature = "exit_status_error", issue = "84908")]
pub struct ExitStatusError(imp::ExitStatusError);
#[unstable(feature = "exit_status_error", issue = "84908")]
impl ExitStatusError {
#[must_use]
pub fn code(&self) -> Option<i32> {
self.code_nonzero().map(Into::into)
}
#[must_use]
pub fn code_nonzero(&self) -> Option<NonZeroI32> {
self.0.code()
}
#[must_use]
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 {
write!(f, "process exited unsuccessfully: {}", self.into_status())
}
}
#[unstable(feature = "exit_status_error", issue = "84908")]
impl crate::error::Error for ExitStatusError {}
#[derive(Clone, Copy, Debug)]
#[stable(feature = "process_exitcode", since = "1.61.0")]
pub struct ExitCode(imp::ExitCode);
#[unstable(feature = "sealed", issue = "none")]
impl crate::sealed::Sealed for ExitCode {}
#[stable(feature = "process_exitcode", since = "1.61.0")]
impl ExitCode {
#[stable(feature = "process_exitcode", since = "1.61.0")]
pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS);
#[stable(feature = "process_exitcode", since = "1.61.0")]
pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
#[unstable(feature = "exitcode_exit_method", issue = "97100")]
pub fn exit_process(self) -> ! {
exit(self.to_i32())
}
}
impl ExitCode {
#[unstable(
feature = "process_exitcode_internals",
reason = "exposed only for libstd",
issue = "none"
)]
#[inline]
#[doc(hidden)]
pub fn to_i32(self) -> i32 {
self.0.as_i32()
}
}
#[stable(feature = "process_exitcode", since = "1.61.0")]
impl From<u8> for ExitCode {
fn from(code: u8) -> Self {
ExitCode(imp::ExitCode::from(code))
}
}
impl AsInner<imp::ExitCode> for ExitCode {
fn as_inner(&self) -> &imp::ExitCode {
&self.0
}
}
impl FromInner<imp::ExitCode> for ExitCode {
fn from_inner(s: imp::ExitCode) -> ExitCode {
ExitCode(s)
}
}
impl Child {
#[stable(feature = "process", since = "1.0.0")]
pub fn kill(&mut self) -> io::Result<()> {
self.handle.kill()
}
#[must_use]
#[stable(feature = "process_id", since = "1.3.0")]
pub fn id(&self) -> u32 {
self.handle.id()
}
#[stable(feature = "process", since = "1.0.0")]
pub fn wait(&mut self) -> io::Result<ExitStatus> {
drop(self.stdin.take());
self.handle.wait().map(ExitStatus)
}
#[stable(feature = "process_try_wait", since = "1.18.0")]
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
Ok(self.handle.try_wait()?.map(ExitStatus))
}
#[stable(feature = "process", since = "1.0.0")]
pub fn wait_with_output(mut self) -> io::Result<Output> {
drop(self.stdin.take());
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();
}
}
let status = self.wait()?;
Ok(Output { status, stdout, stderr })
}
}
#[stable(feature = "rust1", since = "1.0.0")]
pub fn exit(code: i32) -> ! {
crate::rt::cleanup();
crate::sys::os::exit(code)
}
#[stable(feature = "process_abort", since = "1.17.0")]
#[cold]
pub fn abort() -> ! {
crate::sys::abort_internal();
}
#[must_use]
#[stable(feature = "getpid", since = "1.26.0")]
pub fn id() -> u32 {
crate::sys::os::getpid()
}
#[cfg_attr(not(test), lang = "termination")]
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
#[rustc_on_unimplemented(on(
cause = "MainFunctionType",
message = "`main` has invalid return type `{Self}`",
label = "`main` can only return types that implement `{Termination}`"
))]
pub trait Termination {
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
fn report(self) -> ExitCode;
}
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
impl Termination for () {
#[inline]
fn report(self) -> ExitCode {
ExitCode::SUCCESS
}
}
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
impl Termination for ! {
fn report(self) -> ExitCode {
self
}
}
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
impl Termination for Infallible {
fn report(self) -> ExitCode {
match self {}
}
}
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
impl Termination for ExitCode {
#[inline]
fn report(self) -> ExitCode {
self
}
}
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
impl<T: Termination, E: fmt::Debug> Termination for Result<T, E> {
fn report(self) -> ExitCode {
match self {
Ok(val) => val.report(),
Err(err) => {
io::attempt_print_to_stderr(format_args_nl!("Error: {err:?}"));
ExitCode::FAILURE
}
}
}
}