1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Working with processes.
13 #![stable(feature = "process", since = "1.0.0")]
22 use sys::pipe::{read2, AnonPipe};
23 use sys::process as imp;
24 use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
26 /// Representation of a running or exited child process.
28 /// This structure is used to represent and manage child processes. A child
29 /// process is created via the [`Command`] struct, which configures the
30 /// spawning process and can itself be constructed using a builder-style
36 /// use std::process::Command;
38 /// let mut child = Command::new("/bin/cat")
41 /// .expect("failed to execute child");
43 /// let ecode = child.wait()
44 /// .expect("failed to wait on child");
46 /// assert!(ecode.success());
51 /// Take note that there is no implementation of [`Drop`] for child processes,
52 /// so if you do not ensure the `Child` has exited then it will continue to
53 /// run, even after the `Child` handle to the child process has gone out of
56 /// Calling [`wait`][`wait`] (or other functions that wrap around it) will make
57 /// the parent process wait until the child has actually exited before
60 /// [`Command`]: struct.Command.html
61 /// [`Drop`]: ../../core/ops/trait.Drop.html
62 /// [`wait`]: #method.wait
63 #[stable(feature = "process", since = "1.0.0")]
67 /// The handle for writing to the child's stdin, if it has been captured
68 #[stable(feature = "process", since = "1.0.0")]
69 pub stdin: Option<ChildStdin>,
71 /// The handle for reading from the child's stdout, if it has been captured
72 #[stable(feature = "process", since = "1.0.0")]
73 pub stdout: Option<ChildStdout>,
75 /// The handle for reading from the child's stderr, if it has been captured
76 #[stable(feature = "process", since = "1.0.0")]
77 pub stderr: Option<ChildStderr>,
80 impl AsInner<imp::Process> for Child {
81 fn as_inner(&self) -> &imp::Process { &self.handle }
84 impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
85 fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child {
88 stdin: io.stdin.map(ChildStdin::from_inner),
89 stdout: io.stdout.map(ChildStdout::from_inner),
90 stderr: io.stderr.map(ChildStderr::from_inner),
95 impl IntoInner<imp::Process> for Child {
96 fn into_inner(self) -> imp::Process { self.handle }
99 /// A handle to a child process's stdin. This struct is used in the [`stdin`]
100 /// field on [`Child`].
102 /// [`Child`]: struct.Child.html
103 /// [`stdin`]: struct.Child.html#structfield.stdin
104 #[stable(feature = "process", since = "1.0.0")]
105 pub struct ChildStdin {
109 #[stable(feature = "process", since = "1.0.0")]
110 impl Write for ChildStdin {
111 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
112 self.inner.write(buf)
115 fn flush(&mut self) -> io::Result<()> {
120 impl AsInner<AnonPipe> for ChildStdin {
121 fn as_inner(&self) -> &AnonPipe { &self.inner }
124 impl IntoInner<AnonPipe> for ChildStdin {
125 fn into_inner(self) -> AnonPipe { self.inner }
128 impl FromInner<AnonPipe> for ChildStdin {
129 fn from_inner(pipe: AnonPipe) -> ChildStdin {
130 ChildStdin { inner: pipe }
134 /// A handle to a child process's stdout. This struct is used in the [`stdout`]
135 /// field on [`Child`].
137 /// [`Child`]: struct.Child.html
138 /// [`stdout`]: struct.Child.html#structfield.stdout
139 #[stable(feature = "process", since = "1.0.0")]
140 pub struct ChildStdout {
144 #[stable(feature = "process", since = "1.0.0")]
145 impl Read for ChildStdout {
146 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
149 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
150 self.inner.read_to_end(buf)
154 impl AsInner<AnonPipe> for ChildStdout {
155 fn as_inner(&self) -> &AnonPipe { &self.inner }
158 impl IntoInner<AnonPipe> for ChildStdout {
159 fn into_inner(self) -> AnonPipe { self.inner }
162 impl FromInner<AnonPipe> for ChildStdout {
163 fn from_inner(pipe: AnonPipe) -> ChildStdout {
164 ChildStdout { inner: pipe }
168 /// A handle to a child process's stderr. This struct is used in the [`stderr`]
169 /// field on [`Child`].
171 /// [`Child`]: struct.Child.html
172 /// [`stderr`]: struct.Child.html#structfield.stderr
173 #[stable(feature = "process", since = "1.0.0")]
174 pub struct ChildStderr {
178 #[stable(feature = "process", since = "1.0.0")]
179 impl Read for ChildStderr {
180 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
183 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
184 self.inner.read_to_end(buf)
188 impl AsInner<AnonPipe> for ChildStderr {
189 fn as_inner(&self) -> &AnonPipe { &self.inner }
192 impl IntoInner<AnonPipe> for ChildStderr {
193 fn into_inner(self) -> AnonPipe { self.inner }
196 impl FromInner<AnonPipe> for ChildStderr {
197 fn from_inner(pipe: AnonPipe) -> ChildStderr {
198 ChildStderr { inner: pipe }
202 /// A process builder, providing fine-grained control
203 /// over how a new process should be spawned.
205 /// A default configuration can be
206 /// generated using `Command::new(program)`, where `program` gives a path to the
207 /// program to be executed. Additional builder methods allow the configuration
208 /// to be changed (for example, by adding arguments) prior to spawning:
211 /// use std::process::Command;
213 /// let output = Command::new("sh")
215 /// .arg("echo hello")
217 /// .expect("failed to execute process");
219 /// let hello = output.stdout;
221 #[stable(feature = "process", since = "1.0.0")]
227 /// Constructs a new `Command` for launching the program at
228 /// path `program`, with the following default configuration:
230 /// * No arguments to the program
231 /// * Inherit the current process's environment
232 /// * Inherit the current process's working directory
233 /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
235 /// Builder methods are provided to change these defaults and
236 /// otherwise configure the process.
243 /// use std::process::Command;
245 /// Command::new("sh")
247 /// .expect("sh command failed to start");
249 #[stable(feature = "process", since = "1.0.0")]
250 pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
251 Command { inner: imp::Command::new(program.as_ref()) }
254 /// Add an argument to pass to the program.
261 /// use std::process::Command;
263 /// Command::new("ls")
267 /// .expect("ls command failed to start");
269 #[stable(feature = "process", since = "1.0.0")]
270 pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
271 self.inner.arg(arg.as_ref());
275 /// Add multiple arguments to pass to the program.
282 /// use std::process::Command;
284 /// Command::new("ls")
285 /// .args(&["-l", "-a"])
287 /// .expect("ls command failed to start");
289 #[stable(feature = "process", since = "1.0.0")]
290 pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut Command {
292 self.arg(arg.as_ref());
297 /// Inserts or updates an environment variable mapping.
299 /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
300 /// and case-sensitive on all other platforms.
307 /// use std::process::Command;
309 /// Command::new("ls")
310 /// .env("PATH", "/bin")
312 /// .expect("ls command failed to start");
314 #[stable(feature = "process", since = "1.0.0")]
315 pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
316 where K: AsRef<OsStr>, V: AsRef<OsStr>
318 self.inner.env(key.as_ref(), val.as_ref());
322 /// Removes an environment variable mapping.
329 /// use std::process::Command;
331 /// Command::new("ls")
332 /// .env_remove("PATH")
334 /// .expect("ls command failed to start");
336 #[stable(feature = "process", since = "1.0.0")]
337 pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
338 self.inner.env_remove(key.as_ref());
342 /// Clears the entire environment map for the child process.
349 /// use std::process::Command;
351 /// Command::new("ls")
354 /// .expect("ls command failed to start");
356 #[stable(feature = "process", since = "1.0.0")]
357 pub fn env_clear(&mut self) -> &mut Command {
358 self.inner.env_clear();
362 /// Sets the working directory for the child process.
369 /// use std::process::Command;
371 /// Command::new("ls")
372 /// .current_dir("/bin")
374 /// .expect("ls command failed to start");
376 #[stable(feature = "process", since = "1.0.0")]
377 pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
378 self.inner.cwd(dir.as_ref().as_ref());
382 /// Configuration for the child process's stdin handle (file descriptor 0).
389 /// use std::process::{Command, Stdio};
391 /// Command::new("ls")
392 /// .stdin(Stdio::null())
394 /// .expect("ls command failed to start");
396 #[stable(feature = "process", since = "1.0.0")]
397 pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
398 self.inner.stdin(cfg.0);
402 /// Configuration for the child process's stdout handle (file descriptor 1).
409 /// use std::process::{Command, Stdio};
411 /// Command::new("ls")
412 /// .stdout(Stdio::null())
414 /// .expect("ls command failed to start");
416 #[stable(feature = "process", since = "1.0.0")]
417 pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
418 self.inner.stdout(cfg.0);
422 /// Configuration for the child process's stderr handle (file descriptor 2).
429 /// use std::process::{Command, Stdio};
431 /// Command::new("ls")
432 /// .stderr(Stdio::null())
434 /// .expect("ls command failed to start");
436 #[stable(feature = "process", since = "1.0.0")]
437 pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
438 self.inner.stderr(cfg.0);
442 /// Executes the command as a child process, returning a handle to it.
444 /// By default, stdin, stdout and stderr are inherited from the parent.
451 /// use std::process::Command;
453 /// Command::new("ls")
455 /// .expect("ls command failed to start");
457 #[stable(feature = "process", since = "1.0.0")]
458 pub fn spawn(&mut self) -> io::Result<Child> {
459 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
462 /// Executes the command as a child process, waiting for it to finish and
463 /// collecting all of its output.
465 /// By default, stdin, stdout and stderr are captured (and used to
466 /// provide the resulting output).
471 /// use std::process::Command;
472 /// let output = Command::new("/bin/cat")
475 /// .expect("failed to execute process");
477 /// println!("status: {}", output.status);
478 /// println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
479 /// println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
481 /// assert!(output.status.success());
483 #[stable(feature = "process", since = "1.0.0")]
484 pub fn output(&mut self) -> io::Result<Output> {
485 self.inner.spawn(imp::Stdio::MakePipe, false).map(Child::from_inner)
486 .and_then(|p| p.wait_with_output())
489 /// Executes a command as a child process, waiting for it to finish and
490 /// collecting its exit status.
492 /// By default, stdin, stdout and stderr are inherited from the parent.
497 /// use std::process::Command;
499 /// let status = Command::new("/bin/cat")
502 /// .expect("failed to execute process");
504 /// println!("process exited with: {}", status);
506 /// assert!(status.success());
508 #[stable(feature = "process", since = "1.0.0")]
509 pub fn status(&mut self) -> io::Result<ExitStatus> {
510 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
511 .and_then(|mut p| p.wait())
515 #[stable(feature = "rust1", since = "1.0.0")]
516 impl fmt::Debug for Command {
517 /// Format the program and arguments of a Command for display. Any
518 /// non-utf8 data is lossily converted using the utf8 replacement
520 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
525 impl AsInner<imp::Command> for Command {
526 fn as_inner(&self) -> &imp::Command { &self.inner }
529 impl AsInnerMut<imp::Command> for Command {
530 fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner }
533 /// The output of a finished process.
534 #[derive(PartialEq, Eq, Clone)]
535 #[stable(feature = "process", since = "1.0.0")]
537 /// The status (exit code) of the process.
538 #[stable(feature = "process", since = "1.0.0")]
539 pub status: ExitStatus,
540 /// The data that the process wrote to stdout.
541 #[stable(feature = "process", since = "1.0.0")]
543 /// The data that the process wrote to stderr.
544 #[stable(feature = "process", since = "1.0.0")]
548 // If either stderr or stdout are valid utf8 strings it prints the valid
549 // strings, otherwise it prints the byte sequence instead
550 #[stable(feature = "process_output_debug", since = "1.7.0")]
551 impl fmt::Debug for Output {
552 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
554 let stdout_utf8 = str::from_utf8(&self.stdout);
555 let stdout_debug: &fmt::Debug = match stdout_utf8 {
557 Err(_) => &self.stdout
560 let stderr_utf8 = str::from_utf8(&self.stderr);
561 let stderr_debug: &fmt::Debug = match stderr_utf8 {
563 Err(_) => &self.stderr
566 fmt.debug_struct("Output")
567 .field("status", &self.status)
568 .field("stdout", stdout_debug)
569 .field("stderr", stderr_debug)
574 /// Describes what to do with a standard I/O stream for a child process.
575 #[stable(feature = "process", since = "1.0.0")]
576 pub struct Stdio(imp::Stdio);
579 /// A new pipe should be arranged to connect the parent and child processes.
580 #[stable(feature = "process", since = "1.0.0")]
581 pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) }
583 /// The child inherits from the corresponding parent descriptor.
584 #[stable(feature = "process", since = "1.0.0")]
585 pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) }
587 /// This stream will be ignored. This is the equivalent of attaching the
588 /// stream to `/dev/null`
589 #[stable(feature = "process", since = "1.0.0")]
590 pub fn null() -> Stdio { Stdio(imp::Stdio::Null) }
593 impl FromInner<imp::Stdio> for Stdio {
594 fn from_inner(inner: imp::Stdio) -> Stdio {
599 /// Describes the result of a process after it has terminated.
600 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
601 #[stable(feature = "process", since = "1.0.0")]
602 pub struct ExitStatus(imp::ExitStatus);
605 /// Was termination successful? Signal termination not considered a success,
606 /// and success is defined as a zero exit status.
611 /// use std::process::Command;
613 /// let status = Command::new("mkdir")
616 /// .expect("failed to execute mkdir");
618 /// if status.success() {
619 /// println!("'projects/' directory created");
621 /// println!("failed to create 'projects/' directory");
624 #[stable(feature = "process", since = "1.0.0")]
625 pub fn success(&self) -> bool {
629 /// Returns the exit code of the process, if any.
631 /// On Unix, this will return `None` if the process was terminated
632 /// by a signal; `std::os::unix` provides an extension trait for
633 /// extracting the signal and other details from the `ExitStatus`.
634 #[stable(feature = "process", since = "1.0.0")]
635 pub fn code(&self) -> Option<i32> {
640 impl AsInner<imp::ExitStatus> for ExitStatus {
641 fn as_inner(&self) -> &imp::ExitStatus { &self.0 }
644 impl FromInner<imp::ExitStatus> for ExitStatus {
645 fn from_inner(s: imp::ExitStatus) -> ExitStatus {
650 #[stable(feature = "process", since = "1.0.0")]
651 impl fmt::Display for ExitStatus {
652 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
658 /// Forces the child to exit. This is equivalent to sending a
659 /// SIGKILL on unix platforms.
666 /// use std::process::Command;
668 /// let mut command = Command::new("yes");
669 /// if let Ok(mut child) = command.spawn() {
670 /// child.kill().expect("command wasn't running");
672 /// println!("yes command didn't start");
675 #[stable(feature = "process", since = "1.0.0")]
676 pub fn kill(&mut self) -> io::Result<()> {
680 /// Returns the OS-assigned process identifier associated with this child.
687 /// use std::process::Command;
689 /// let mut command = Command::new("ls");
690 /// if let Ok(child) = command.spawn() {
691 /// println!("Child's id is {}", child.id());
693 /// println!("ls command didn't start");
696 #[stable(feature = "process_id", since = "1.3.0")]
697 pub fn id(&self) -> u32 {
701 /// Waits for the child to exit completely, returning the status that it
702 /// exited with. This function will continue to have the same return value
703 /// after it has been called at least once.
705 /// The stdin handle to the child process, if any, will be closed
706 /// before waiting. This helps avoid deadlock: it ensures that the
707 /// child does not block waiting for input from the parent, while
708 /// the parent waits for the child to exit.
715 /// use std::process::Command;
717 /// let mut command = Command::new("ls");
718 /// if let Ok(mut child) = command.spawn() {
719 /// child.wait().expect("command wasn't running");
720 /// println!("Child has finished its execution!");
722 /// println!("ls command didn't start");
725 #[stable(feature = "process", since = "1.0.0")]
726 pub fn wait(&mut self) -> io::Result<ExitStatus> {
727 drop(self.stdin.take());
728 self.handle.wait().map(ExitStatus)
731 /// Simultaneously waits for the child to exit and collect all remaining
732 /// output on the stdout/stderr handles, returning an `Output`
735 /// The stdin handle to the child process, if any, will be closed
736 /// before waiting. This helps avoid deadlock: it ensures that the
737 /// child does not block waiting for input from the parent, while
738 /// the parent waits for the child to exit.
740 /// By default, stdin, stdout and stderr are inherited from the parent.
741 /// In order to capture the output into this `Result<Output>` it is
742 /// necessary to create new pipes between parent and child. Use
743 /// `stdout(Stdio::piped())` or `stderr(Stdio::piped())`, respectively.
748 /// use std::process::{Command, Stdio};
750 /// let child = Command::new("/bin/cat")
752 /// .stdout(Stdio::piped())
754 /// .expect("failed to execute child");
756 /// let output = child
757 /// .wait_with_output()
758 /// .expect("failed to wait on child");
760 /// assert!(output.status.success());
763 #[stable(feature = "process", since = "1.0.0")]
764 pub fn wait_with_output(mut self) -> io::Result<Output> {
765 drop(self.stdin.take());
767 let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
768 match (self.stdout.take(), self.stderr.take()) {
770 (Some(mut out), None) => {
771 let res = out.read_to_end(&mut stdout);
774 (None, Some(mut err)) => {
775 let res = err.read_to_end(&mut stderr);
778 (Some(out), Some(err)) => {
779 let res = read2(out.inner, &mut stdout, err.inner, &mut stderr);
784 let status = self.wait()?;
793 /// Terminates the current process with the specified exit code.
795 /// This function will never return and will immediately terminate the current
796 /// process. The exit code is passed through to the underlying OS and will be
797 /// available for consumption by another process.
799 /// Note that because this function never returns, and that it terminates the
800 /// process, no destructors on the current stack or any other thread's stack
801 /// will be run. If a clean shutdown is needed it is recommended to only call
802 /// this function at a known point where there are no more destructors left
804 #[stable(feature = "rust1", since = "1.0.0")]
805 pub fn exit(code: i32) -> ! {
806 ::sys_common::cleanup();
807 ::sys::os::exit(code)
816 use super::{Command, Output, Stdio};
818 // FIXME(#10380) these tests should not all be ignored on android.
821 #[cfg_attr(target_os = "android", ignore)]
822 #[cfg_attr(target_os = "emscripten", ignore)]
824 let p = Command::new("true").spawn();
826 let mut p = p.unwrap();
827 assert!(p.wait().unwrap().success());
831 #[cfg_attr(target_os = "android", ignore)]
833 match Command::new("if-this-is-a-binary-then-the-world-has-ended").spawn() {
840 #[cfg_attr(target_os = "android", ignore)]
841 #[cfg_attr(target_os = "emscripten", ignore)]
842 fn exit_reported_right() {
843 let p = Command::new("false").spawn();
845 let mut p = p.unwrap();
846 assert!(p.wait().unwrap().code() == Some(1));
852 #[cfg_attr(target_os = "android", ignore)]
853 #[cfg_attr(target_os = "emscripten", ignore)]
854 fn signal_reported_right() {
855 use os::unix::process::ExitStatusExt;
857 let mut p = Command::new("/bin/sh")
858 .arg("-c").arg("read a")
859 .stdin(Stdio::piped())
862 match p.wait().unwrap().signal() {
864 result => panic!("not terminated by signal 9 (instead, {:?})",
869 pub fn run_output(mut cmd: Command) -> String {
872 let mut p = p.unwrap();
873 assert!(p.stdout.is_some());
874 let mut ret = String::new();
875 p.stdout.as_mut().unwrap().read_to_string(&mut ret).unwrap();
876 assert!(p.wait().unwrap().success());
881 #[cfg_attr(target_os = "android", ignore)]
882 #[cfg_attr(target_os = "emscripten", ignore)]
884 let mut cmd = Command::new("echo");
885 cmd.arg("foobar").stdout(Stdio::piped());
886 assert_eq!(run_output(cmd), "foobar\n");
890 #[cfg_attr(any(windows, target_os = "android"), ignore)]
891 #[cfg_attr(target_os = "emscripten", ignore)]
892 fn set_current_dir_works() {
893 let mut cmd = Command::new("/bin/sh");
894 cmd.arg("-c").arg("pwd")
896 .stdout(Stdio::piped());
897 assert_eq!(run_output(cmd), "/\n");
901 #[cfg_attr(any(windows, target_os = "android"), ignore)]
902 #[cfg_attr(target_os = "emscripten", ignore)]
904 let mut p = Command::new("/bin/sh")
905 .arg("-c").arg("read line; echo $line")
906 .stdin(Stdio::piped())
907 .stdout(Stdio::piped())
909 p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap();
910 drop(p.stdin.take());
911 let mut out = String::new();
912 p.stdout.as_mut().unwrap().read_to_string(&mut out).unwrap();
913 assert!(p.wait().unwrap().success());
914 assert_eq!(out, "foobar\n");
919 #[cfg_attr(target_os = "android", ignore)]
921 #[cfg_attr(target_os = "emscripten", ignore)]
923 use os::unix::prelude::*;
925 let mut p = Command::new("/bin/sh")
926 .arg("-c").arg("true")
927 .uid(unsafe { libc::getuid() })
928 .gid(unsafe { libc::getgid() })
930 assert!(p.wait().unwrap().success());
934 #[cfg_attr(target_os = "android", ignore)]
936 fn uid_to_root_fails() {
937 use os::unix::prelude::*;
940 // if we're already root, this isn't a valid test. Most of the bots run
941 // as non-root though (android is an exception).
942 if unsafe { libc::getuid() == 0 } { return }
943 assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
947 #[cfg_attr(target_os = "android", ignore)]
948 #[cfg_attr(target_os = "emscripten", ignore)]
949 fn test_process_status() {
950 let mut status = Command::new("false").status().unwrap();
951 assert!(status.code() == Some(1));
953 status = Command::new("true").status().unwrap();
954 assert!(status.success());
958 #[cfg_attr(target_os = "emscripten", ignore)]
959 fn test_process_output_fail_to_start() {
960 match Command::new("/no-binary-by-this-name-should-exist").output() {
961 Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
967 #[cfg_attr(target_os = "android", ignore)]
968 #[cfg_attr(target_os = "emscripten", ignore)]
969 fn test_process_output_output() {
970 let Output {status, stdout, stderr}
971 = Command::new("echo").arg("hello").output().unwrap();
972 let output_str = str::from_utf8(&stdout).unwrap();
974 assert!(status.success());
975 assert_eq!(output_str.trim().to_string(), "hello");
976 assert_eq!(stderr, Vec::new());
980 #[cfg_attr(target_os = "android", ignore)]
981 #[cfg_attr(target_os = "emscripten", ignore)]
982 fn test_process_output_error() {
983 let Output {status, stdout, stderr}
984 = Command::new("mkdir").arg(".").output().unwrap();
986 assert!(status.code() == Some(1));
987 assert_eq!(stdout, Vec::new());
988 assert!(!stderr.is_empty());
992 #[cfg_attr(target_os = "android", ignore)]
993 #[cfg_attr(target_os = "emscripten", ignore)]
994 fn test_finish_once() {
995 let mut prog = Command::new("false").spawn().unwrap();
996 assert!(prog.wait().unwrap().code() == Some(1));
1000 #[cfg_attr(target_os = "android", ignore)]
1001 #[cfg_attr(target_os = "emscripten", ignore)]
1002 fn test_finish_twice() {
1003 let mut prog = Command::new("false").spawn().unwrap();
1004 assert!(prog.wait().unwrap().code() == Some(1));
1005 assert!(prog.wait().unwrap().code() == Some(1));
1009 #[cfg_attr(target_os = "android", ignore)]
1010 #[cfg_attr(target_os = "emscripten", ignore)]
1011 fn test_wait_with_output_once() {
1012 let prog = Command::new("echo").arg("hello").stdout(Stdio::piped())
1014 let Output {status, stdout, stderr} = prog.wait_with_output().unwrap();
1015 let output_str = str::from_utf8(&stdout).unwrap();
1017 assert!(status.success());
1018 assert_eq!(output_str.trim().to_string(), "hello");
1019 assert_eq!(stderr, Vec::new());
1022 #[cfg(all(unix, not(target_os="android")))]
1023 pub fn env_cmd() -> Command {
1026 #[cfg(target_os="android")]
1027 pub fn env_cmd() -> Command {
1028 let mut cmd = Command::new("/system/bin/sh");
1029 cmd.arg("-c").arg("set");
1034 pub fn env_cmd() -> Command {
1035 let mut cmd = Command::new("cmd");
1036 cmd.arg("/c").arg("set");
1041 #[cfg_attr(target_os = "emscripten", ignore)]
1042 fn test_inherit_env() {
1045 let result = env_cmd().output().unwrap();
1046 let output = String::from_utf8(result.stdout).unwrap();
1048 for (ref k, ref v) in env::vars() {
1049 // don't check android RANDOM variables
1050 if cfg!(target_os = "android") && *k == "RANDOM" {
1054 // Windows has hidden environment variables whose names start with
1055 // equals signs (`=`). Those do not show up in the output of the
1057 assert!((cfg!(windows) && k.starts_with("=")) ||
1058 k.starts_with("DYLD") ||
1059 output.contains(&format!("{}={}", *k, *v)) ||
1060 output.contains(&format!("{}='{}'", *k, *v)),
1061 "output doesn't contain `{}={}`\n{}",
1067 #[cfg_attr(target_os = "emscripten", ignore)]
1068 fn test_override_env() {
1071 // In some build environments (such as chrooted Nix builds), `env` can
1072 // only be found in the explicitly-provided PATH env variable, not in
1073 // default places such as /bin or /usr/bin. So we need to pass through
1074 // PATH to our sub-process.
1075 let mut cmd = env_cmd();
1076 cmd.env_clear().env("RUN_TEST_NEW_ENV", "123");
1077 if let Some(p) = env::var_os("PATH") {
1078 cmd.env("PATH", &p);
1080 let result = cmd.output().unwrap();
1081 let output = String::from_utf8_lossy(&result.stdout).to_string();
1083 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1084 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1088 #[cfg_attr(target_os = "emscripten", ignore)]
1089 fn test_add_to_env() {
1090 let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
1091 let output = String::from_utf8_lossy(&result.stdout).to_string();
1093 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1094 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1097 // Regression tests for #30858.
1099 fn test_interior_nul_in_progname_is_error() {
1100 match Command::new("has-some-\0\0s-inside").spawn() {
1101 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1107 fn test_interior_nul_in_arg_is_error() {
1108 match Command::new("echo").arg("has-some-\0\0s-inside").spawn() {
1109 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1115 fn test_interior_nul_in_args_is_error() {
1116 match Command::new("echo").args(&["has-some-\0\0s-inside"]).spawn() {
1117 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1123 fn test_interior_nul_in_current_dir_is_error() {
1124 match Command::new("echo").current_dir("has-some-\0\0s-inside").spawn() {
1125 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1130 // Regression tests for #30862.
1132 fn test_interior_nul_in_env_key_is_error() {
1133 match env_cmd().env("has-some-\0\0s-inside", "value").spawn() {
1134 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1140 fn test_interior_nul_in_env_value_is_error() {
1141 match env_cmd().env("key", "has-some-\0\0s-inside").spawn() {
1142 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),