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 //! A module for working with processes.
15 //! Basic usage where we try to execute the `cat` shell command:
18 //! use std::process::Command;
20 //! let mut child = Command::new("/bin/cat")
23 //! .expect("failed to execute child");
25 //! let ecode = child.wait()
26 //! .expect("failed to wait on child");
28 //! assert!(ecode.success());
31 #![stable(feature = "process", since = "1.0.0")]
40 use sys::pipe::{read2, AnonPipe};
41 use sys::process as imp;
42 use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
44 /// Representation of a running or exited child process.
46 /// This structure is used to represent and manage child processes. A child
47 /// process is created via the [`Command`] struct, which configures the
48 /// spawning process and can itself be constructed using a builder-style
54 /// use std::process::Command;
56 /// let mut child = Command::new("/bin/cat")
59 /// .expect("failed to execute child");
61 /// let ecode = child.wait()
62 /// .expect("failed to wait on child");
64 /// assert!(ecode.success());
69 /// Take note that there is no implementation of [`Drop`] for child processes,
70 /// so if you do not ensure the `Child` has exited then it will continue to
71 /// run, even after the `Child` handle to the child process has gone out of
74 /// Calling [`wait`][`wait`] (or other functions that wrap around it) will make
75 /// the parent process wait until the child has actually exited before
78 /// [`Command`]: struct.Command.html
79 /// [`Drop`]: ../../core/ops/trait.Drop.html
80 /// [`wait`]: #method.wait
81 #[stable(feature = "process", since = "1.0.0")]
85 /// The handle for writing to the child's stdin, if it has been captured
86 #[stable(feature = "process", since = "1.0.0")]
87 pub stdin: Option<ChildStdin>,
89 /// The handle for reading from the child's stdout, if it has been captured
90 #[stable(feature = "process", since = "1.0.0")]
91 pub stdout: Option<ChildStdout>,
93 /// The handle for reading from the child's stderr, if it has been captured
94 #[stable(feature = "process", since = "1.0.0")]
95 pub stderr: Option<ChildStderr>,
98 impl AsInner<imp::Process> for Child {
99 fn as_inner(&self) -> &imp::Process { &self.handle }
102 impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
103 fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child {
106 stdin: io.stdin.map(ChildStdin::from_inner),
107 stdout: io.stdout.map(ChildStdout::from_inner),
108 stderr: io.stderr.map(ChildStderr::from_inner),
113 impl IntoInner<imp::Process> for Child {
114 fn into_inner(self) -> imp::Process { self.handle }
117 /// A handle to a child process's stdin. This struct is used in the [`stdin`]
118 /// field on [`Child`].
120 /// [`Child`]: struct.Child.html
121 /// [`stdin`]: struct.Child.html#structfield.stdin
122 #[stable(feature = "process", since = "1.0.0")]
123 pub struct ChildStdin {
127 #[stable(feature = "process", since = "1.0.0")]
128 impl Write for ChildStdin {
129 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
130 self.inner.write(buf)
133 fn flush(&mut self) -> io::Result<()> {
138 impl AsInner<AnonPipe> for ChildStdin {
139 fn as_inner(&self) -> &AnonPipe { &self.inner }
142 impl IntoInner<AnonPipe> for ChildStdin {
143 fn into_inner(self) -> AnonPipe { self.inner }
146 impl FromInner<AnonPipe> for ChildStdin {
147 fn from_inner(pipe: AnonPipe) -> ChildStdin {
148 ChildStdin { inner: pipe }
152 /// A handle to a child process's stdout. This struct is used in the [`stdout`]
153 /// field on [`Child`].
155 /// [`Child`]: struct.Child.html
156 /// [`stdout`]: struct.Child.html#structfield.stdout
157 #[stable(feature = "process", since = "1.0.0")]
158 pub struct ChildStdout {
162 #[stable(feature = "process", since = "1.0.0")]
163 impl Read for ChildStdout {
164 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
167 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
168 self.inner.read_to_end(buf)
172 impl AsInner<AnonPipe> for ChildStdout {
173 fn as_inner(&self) -> &AnonPipe { &self.inner }
176 impl IntoInner<AnonPipe> for ChildStdout {
177 fn into_inner(self) -> AnonPipe { self.inner }
180 impl FromInner<AnonPipe> for ChildStdout {
181 fn from_inner(pipe: AnonPipe) -> ChildStdout {
182 ChildStdout { inner: pipe }
186 /// A handle to a child process's stderr. This struct is used in the [`stderr`]
187 /// field on [`Child`].
189 /// [`Child`]: struct.Child.html
190 /// [`stderr`]: struct.Child.html#structfield.stderr
191 #[stable(feature = "process", since = "1.0.0")]
192 pub struct ChildStderr {
196 #[stable(feature = "process", since = "1.0.0")]
197 impl Read for ChildStderr {
198 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
201 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
202 self.inner.read_to_end(buf)
206 impl AsInner<AnonPipe> for ChildStderr {
207 fn as_inner(&self) -> &AnonPipe { &self.inner }
210 impl IntoInner<AnonPipe> for ChildStderr {
211 fn into_inner(self) -> AnonPipe { self.inner }
214 impl FromInner<AnonPipe> for ChildStderr {
215 fn from_inner(pipe: AnonPipe) -> ChildStderr {
216 ChildStderr { inner: pipe }
220 /// A process builder, providing fine-grained control
221 /// over how a new process should be spawned.
223 /// A default configuration can be
224 /// generated using `Command::new(program)`, where `program` gives a path to the
225 /// program to be executed. Additional builder methods allow the configuration
226 /// to be changed (for example, by adding arguments) prior to spawning:
229 /// use std::process::Command;
231 /// let output = Command::new("sh")
233 /// .arg("echo hello")
235 /// .expect("failed to execute process");
237 /// let hello = output.stdout;
239 #[stable(feature = "process", since = "1.0.0")]
245 /// Constructs a new `Command` for launching the program at
246 /// path `program`, with the following default configuration:
248 /// * No arguments to the program
249 /// * Inherit the current process's environment
250 /// * Inherit the current process's working directory
251 /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
253 /// Builder methods are provided to change these defaults and
254 /// otherwise configure the process.
256 /// If `program` is not an absolute path, the `PATH` will be searched in
257 /// an OS-defined way.
259 /// The search path to be used may be controlled by setting the
260 /// `PATH` environment variable on the Command,
261 /// but this has some implementation limitations on Windows
262 /// (see https://github.com/rust-lang/rust/issues/37519).
269 /// use std::process::Command;
271 /// Command::new("sh")
273 /// .expect("sh command failed to start");
275 #[stable(feature = "process", since = "1.0.0")]
276 pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
277 Command { inner: imp::Command::new(program.as_ref()) }
280 /// Add an argument to pass to the program.
287 /// use std::process::Command;
289 /// Command::new("ls")
293 /// .expect("ls command failed to start");
295 #[stable(feature = "process", since = "1.0.0")]
296 pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
297 self.inner.arg(arg.as_ref());
301 /// Add multiple arguments to pass to the program.
308 /// use std::process::Command;
310 /// Command::new("ls")
311 /// .args(&["-l", "-a"])
313 /// .expect("ls command failed to start");
315 #[stable(feature = "process", since = "1.0.0")]
316 pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut Command {
318 self.arg(arg.as_ref());
323 /// Inserts or updates an environment variable mapping.
325 /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
326 /// and case-sensitive on all other platforms.
333 /// use std::process::Command;
335 /// Command::new("ls")
336 /// .env("PATH", "/bin")
338 /// .expect("ls command failed to start");
340 #[stable(feature = "process", since = "1.0.0")]
341 pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
342 where K: AsRef<OsStr>, V: AsRef<OsStr>
344 self.inner.env(key.as_ref(), val.as_ref());
348 /// Removes an environment variable mapping.
355 /// use std::process::Command;
357 /// Command::new("ls")
358 /// .env_remove("PATH")
360 /// .expect("ls command failed to start");
362 #[stable(feature = "process", since = "1.0.0")]
363 pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
364 self.inner.env_remove(key.as_ref());
368 /// Clears the entire environment map for the child process.
375 /// use std::process::Command;
377 /// Command::new("ls")
380 /// .expect("ls command failed to start");
382 #[stable(feature = "process", since = "1.0.0")]
383 pub fn env_clear(&mut self) -> &mut Command {
384 self.inner.env_clear();
388 /// Sets the working directory for the child process.
395 /// use std::process::Command;
397 /// Command::new("ls")
398 /// .current_dir("/bin")
400 /// .expect("ls command failed to start");
402 #[stable(feature = "process", since = "1.0.0")]
403 pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
404 self.inner.cwd(dir.as_ref().as_ref());
408 /// Configuration for the child process's stdin handle (file descriptor 0).
415 /// use std::process::{Command, Stdio};
417 /// Command::new("ls")
418 /// .stdin(Stdio::null())
420 /// .expect("ls command failed to start");
422 #[stable(feature = "process", since = "1.0.0")]
423 pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
424 self.inner.stdin(cfg.0);
428 /// Configuration for the child process's stdout handle (file descriptor 1).
435 /// use std::process::{Command, Stdio};
437 /// Command::new("ls")
438 /// .stdout(Stdio::null())
440 /// .expect("ls command failed to start");
442 #[stable(feature = "process", since = "1.0.0")]
443 pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
444 self.inner.stdout(cfg.0);
448 /// Configuration for the child process's stderr handle (file descriptor 2).
455 /// use std::process::{Command, Stdio};
457 /// Command::new("ls")
458 /// .stderr(Stdio::null())
460 /// .expect("ls command failed to start");
462 #[stable(feature = "process", since = "1.0.0")]
463 pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
464 self.inner.stderr(cfg.0);
468 /// Executes the command as a child process, returning a handle to it.
470 /// By default, stdin, stdout and stderr are inherited from the parent.
477 /// use std::process::Command;
479 /// Command::new("ls")
481 /// .expect("ls command failed to start");
483 #[stable(feature = "process", since = "1.0.0")]
484 pub fn spawn(&mut self) -> io::Result<Child> {
485 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
488 /// Executes the command as a child process, waiting for it to finish and
489 /// collecting all of its output.
491 /// By default, stdin, stdout and stderr are captured (and used to
492 /// provide the resulting output).
497 /// use std::process::Command;
498 /// let output = Command::new("/bin/cat")
501 /// .expect("failed to execute process");
503 /// println!("status: {}", output.status);
504 /// println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
505 /// println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
507 /// assert!(output.status.success());
509 #[stable(feature = "process", since = "1.0.0")]
510 pub fn output(&mut self) -> io::Result<Output> {
511 self.inner.spawn(imp::Stdio::MakePipe, false).map(Child::from_inner)
512 .and_then(|p| p.wait_with_output())
515 /// Executes a command as a child process, waiting for it to finish and
516 /// collecting its exit status.
518 /// By default, stdin, stdout and stderr are inherited from the parent.
523 /// use std::process::Command;
525 /// let status = Command::new("/bin/cat")
528 /// .expect("failed to execute process");
530 /// println!("process exited with: {}", status);
532 /// assert!(status.success());
534 #[stable(feature = "process", since = "1.0.0")]
535 pub fn status(&mut self) -> io::Result<ExitStatus> {
536 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
537 .and_then(|mut p| p.wait())
541 #[stable(feature = "rust1", since = "1.0.0")]
542 impl fmt::Debug for Command {
543 /// Format the program and arguments of a Command for display. Any
544 /// non-utf8 data is lossily converted using the utf8 replacement
546 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
551 impl AsInner<imp::Command> for Command {
552 fn as_inner(&self) -> &imp::Command { &self.inner }
555 impl AsInnerMut<imp::Command> for Command {
556 fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner }
559 /// The output of a finished process.
560 #[derive(PartialEq, Eq, Clone)]
561 #[stable(feature = "process", since = "1.0.0")]
563 /// The status (exit code) of the process.
564 #[stable(feature = "process", since = "1.0.0")]
565 pub status: ExitStatus,
566 /// The data that the process wrote to stdout.
567 #[stable(feature = "process", since = "1.0.0")]
569 /// The data that the process wrote to stderr.
570 #[stable(feature = "process", since = "1.0.0")]
574 // If either stderr or stdout are valid utf8 strings it prints the valid
575 // strings, otherwise it prints the byte sequence instead
576 #[stable(feature = "process_output_debug", since = "1.7.0")]
577 impl fmt::Debug for Output {
578 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
580 let stdout_utf8 = str::from_utf8(&self.stdout);
581 let stdout_debug: &fmt::Debug = match stdout_utf8 {
583 Err(_) => &self.stdout
586 let stderr_utf8 = str::from_utf8(&self.stderr);
587 let stderr_debug: &fmt::Debug = match stderr_utf8 {
589 Err(_) => &self.stderr
592 fmt.debug_struct("Output")
593 .field("status", &self.status)
594 .field("stdout", stdout_debug)
595 .field("stderr", stderr_debug)
600 /// Describes what to do with a standard I/O stream for a child process.
601 #[stable(feature = "process", since = "1.0.0")]
602 pub struct Stdio(imp::Stdio);
605 /// A new pipe should be arranged to connect the parent and child processes.
606 #[stable(feature = "process", since = "1.0.0")]
607 pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) }
609 /// The child inherits from the corresponding parent descriptor.
610 #[stable(feature = "process", since = "1.0.0")]
611 pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) }
613 /// This stream will be ignored. This is the equivalent of attaching the
614 /// stream to `/dev/null`
615 #[stable(feature = "process", since = "1.0.0")]
616 pub fn null() -> Stdio { Stdio(imp::Stdio::Null) }
619 impl FromInner<imp::Stdio> for Stdio {
620 fn from_inner(inner: imp::Stdio) -> Stdio {
625 /// Describes the result of a process after it has terminated.
626 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
627 #[stable(feature = "process", since = "1.0.0")]
628 pub struct ExitStatus(imp::ExitStatus);
631 /// Was termination successful? Signal termination not considered a success,
632 /// and success is defined as a zero exit status.
637 /// use std::process::Command;
639 /// let status = Command::new("mkdir")
642 /// .expect("failed to execute mkdir");
644 /// if status.success() {
645 /// println!("'projects/' directory created");
647 /// println!("failed to create 'projects/' directory");
650 #[stable(feature = "process", since = "1.0.0")]
651 pub fn success(&self) -> bool {
655 /// Returns the exit code of the process, if any.
657 /// On Unix, this will return `None` if the process was terminated
658 /// by a signal; `std::os::unix` provides an extension trait for
659 /// extracting the signal and other details from the `ExitStatus`.
660 #[stable(feature = "process", since = "1.0.0")]
661 pub fn code(&self) -> Option<i32> {
666 impl AsInner<imp::ExitStatus> for ExitStatus {
667 fn as_inner(&self) -> &imp::ExitStatus { &self.0 }
670 impl FromInner<imp::ExitStatus> for ExitStatus {
671 fn from_inner(s: imp::ExitStatus) -> ExitStatus {
676 #[stable(feature = "process", since = "1.0.0")]
677 impl fmt::Display for ExitStatus {
678 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
684 /// Forces the child to exit. This is equivalent to sending a
685 /// SIGKILL on unix platforms.
692 /// use std::process::Command;
694 /// let mut command = Command::new("yes");
695 /// if let Ok(mut child) = command.spawn() {
696 /// child.kill().expect("command wasn't running");
698 /// println!("yes command didn't start");
701 #[stable(feature = "process", since = "1.0.0")]
702 pub fn kill(&mut self) -> io::Result<()> {
706 /// Returns the OS-assigned process identifier associated with this child.
713 /// use std::process::Command;
715 /// let mut command = Command::new("ls");
716 /// if let Ok(child) = command.spawn() {
717 /// println!("Child's id is {}", child.id());
719 /// println!("ls command didn't start");
722 #[stable(feature = "process_id", since = "1.3.0")]
723 pub fn id(&self) -> u32 {
727 /// Waits for the child to exit completely, returning the status that it
728 /// exited with. This function will continue to have the same return value
729 /// after it has been called at least once.
731 /// The stdin handle to the child process, if any, will be closed
732 /// before waiting. This helps avoid deadlock: it ensures that the
733 /// child does not block waiting for input from the parent, while
734 /// the parent waits for the child to exit.
741 /// use std::process::Command;
743 /// let mut command = Command::new("ls");
744 /// if let Ok(mut child) = command.spawn() {
745 /// child.wait().expect("command wasn't running");
746 /// println!("Child has finished its execution!");
748 /// println!("ls command didn't start");
751 #[stable(feature = "process", since = "1.0.0")]
752 pub fn wait(&mut self) -> io::Result<ExitStatus> {
753 drop(self.stdin.take());
754 self.handle.wait().map(ExitStatus)
757 /// Simultaneously waits for the child to exit and collect all remaining
758 /// output on the stdout/stderr handles, returning an `Output`
761 /// The stdin handle to the child process, if any, will be closed
762 /// before waiting. This helps avoid deadlock: it ensures that the
763 /// child does not block waiting for input from the parent, while
764 /// the parent waits for the child to exit.
766 /// By default, stdin, stdout and stderr are inherited from the parent.
767 /// In order to capture the output into this `Result<Output>` it is
768 /// necessary to create new pipes between parent and child. Use
769 /// `stdout(Stdio::piped())` or `stderr(Stdio::piped())`, respectively.
774 /// use std::process::{Command, Stdio};
776 /// let child = Command::new("/bin/cat")
778 /// .stdout(Stdio::piped())
780 /// .expect("failed to execute child");
782 /// let output = child
783 /// .wait_with_output()
784 /// .expect("failed to wait on child");
786 /// assert!(output.status.success());
789 #[stable(feature = "process", since = "1.0.0")]
790 pub fn wait_with_output(mut self) -> io::Result<Output> {
791 drop(self.stdin.take());
793 let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
794 match (self.stdout.take(), self.stderr.take()) {
796 (Some(mut out), None) => {
797 let res = out.read_to_end(&mut stdout);
800 (None, Some(mut err)) => {
801 let res = err.read_to_end(&mut stderr);
804 (Some(out), Some(err)) => {
805 let res = read2(out.inner, &mut stdout, err.inner, &mut stderr);
810 let status = self.wait()?;
819 /// Terminates the current process with the specified exit code.
821 /// This function will never return and will immediately terminate the current
822 /// process. The exit code is passed through to the underlying OS and will be
823 /// available for consumption by another process.
825 /// Note that because this function never returns, and that it terminates the
826 /// process, no destructors on the current stack or any other thread's stack
827 /// will be run. If a clean shutdown is needed it is recommended to only call
828 /// this function at a known point where there are no more destructors left
834 /// use std::process;
836 /// process::exit(0);
838 #[stable(feature = "rust1", since = "1.0.0")]
839 pub fn exit(code: i32) -> ! {
840 ::sys_common::cleanup();
841 ::sys::os::exit(code)
844 /// Terminates the process in an abnormal fashion.
846 /// The function will never return and will immediately terminate the current
847 /// process in a platform specific "abnormal" manner.
849 /// Note that because this function never returns, and that it terminates the
850 /// process, no destructors on the current stack or any other thread's stack
851 /// will be run. If a clean shutdown is needed it is recommended to only call
852 /// this function at a known point where there are no more destructors left
854 #[unstable(feature = "process_abort", issue = "37838")]
855 pub fn abort() -> ! {
856 unsafe { ::sys::abort_internal() };
859 #[cfg(all(test, not(target_os = "emscripten")))]
865 use super::{Command, Output, Stdio};
867 // FIXME(#10380) these tests should not all be ignored on android.
870 #[cfg_attr(target_os = "android", ignore)]
872 let p = Command::new("true").spawn();
874 let mut p = p.unwrap();
875 assert!(p.wait().unwrap().success());
879 #[cfg_attr(target_os = "android", ignore)]
881 match Command::new("if-this-is-a-binary-then-the-world-has-ended").spawn() {
888 #[cfg_attr(target_os = "android", ignore)]
889 fn exit_reported_right() {
890 let p = Command::new("false").spawn();
892 let mut p = p.unwrap();
893 assert!(p.wait().unwrap().code() == Some(1));
899 #[cfg_attr(target_os = "android", ignore)]
900 fn signal_reported_right() {
901 use os::unix::process::ExitStatusExt;
903 let mut p = Command::new("/bin/sh")
904 .arg("-c").arg("read a")
905 .stdin(Stdio::piped())
908 match p.wait().unwrap().signal() {
910 result => panic!("not terminated by signal 9 (instead, {:?})",
915 pub fn run_output(mut cmd: Command) -> String {
918 let mut p = p.unwrap();
919 assert!(p.stdout.is_some());
920 let mut ret = String::new();
921 p.stdout.as_mut().unwrap().read_to_string(&mut ret).unwrap();
922 assert!(p.wait().unwrap().success());
927 #[cfg_attr(target_os = "android", ignore)]
929 let mut cmd = Command::new("echo");
930 cmd.arg("foobar").stdout(Stdio::piped());
931 assert_eq!(run_output(cmd), "foobar\n");
935 #[cfg_attr(any(windows, target_os = "android"), ignore)]
936 fn set_current_dir_works() {
937 let mut cmd = Command::new("/bin/sh");
938 cmd.arg("-c").arg("pwd")
940 .stdout(Stdio::piped());
941 assert_eq!(run_output(cmd), "/\n");
945 #[cfg_attr(any(windows, target_os = "android"), ignore)]
947 let mut p = Command::new("/bin/sh")
948 .arg("-c").arg("read line; echo $line")
949 .stdin(Stdio::piped())
950 .stdout(Stdio::piped())
952 p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap();
953 drop(p.stdin.take());
954 let mut out = String::new();
955 p.stdout.as_mut().unwrap().read_to_string(&mut out).unwrap();
956 assert!(p.wait().unwrap().success());
957 assert_eq!(out, "foobar\n");
962 #[cfg_attr(target_os = "android", ignore)]
965 use os::unix::prelude::*;
967 let mut p = Command::new("/bin/sh")
968 .arg("-c").arg("true")
969 .uid(unsafe { libc::getuid() })
970 .gid(unsafe { libc::getgid() })
972 assert!(p.wait().unwrap().success());
976 #[cfg_attr(target_os = "android", ignore)]
978 fn uid_to_root_fails() {
979 use os::unix::prelude::*;
982 // if we're already root, this isn't a valid test. Most of the bots run
983 // as non-root though (android is an exception).
984 if unsafe { libc::getuid() == 0 } { return }
985 assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
989 #[cfg_attr(target_os = "android", ignore)]
990 fn test_process_status() {
991 let mut status = Command::new("false").status().unwrap();
992 assert!(status.code() == Some(1));
994 status = Command::new("true").status().unwrap();
995 assert!(status.success());
999 fn test_process_output_fail_to_start() {
1000 match Command::new("/no-binary-by-this-name-should-exist").output() {
1001 Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
1007 #[cfg_attr(target_os = "android", ignore)]
1008 fn test_process_output_output() {
1009 let Output {status, stdout, stderr}
1010 = Command::new("echo").arg("hello").output().unwrap();
1011 let output_str = str::from_utf8(&stdout).unwrap();
1013 assert!(status.success());
1014 assert_eq!(output_str.trim().to_string(), "hello");
1015 assert_eq!(stderr, Vec::new());
1019 #[cfg_attr(target_os = "android", ignore)]
1020 fn test_process_output_error() {
1021 let Output {status, stdout, stderr}
1022 = Command::new("mkdir").arg(".").output().unwrap();
1024 assert!(status.code() == Some(1));
1025 assert_eq!(stdout, Vec::new());
1026 assert!(!stderr.is_empty());
1030 #[cfg_attr(target_os = "android", ignore)]
1031 fn test_finish_once() {
1032 let mut prog = Command::new("false").spawn().unwrap();
1033 assert!(prog.wait().unwrap().code() == Some(1));
1037 #[cfg_attr(target_os = "android", ignore)]
1038 fn test_finish_twice() {
1039 let mut prog = Command::new("false").spawn().unwrap();
1040 assert!(prog.wait().unwrap().code() == Some(1));
1041 assert!(prog.wait().unwrap().code() == Some(1));
1045 #[cfg_attr(target_os = "android", ignore)]
1046 fn test_wait_with_output_once() {
1047 let prog = Command::new("echo").arg("hello").stdout(Stdio::piped())
1049 let Output {status, stdout, stderr} = prog.wait_with_output().unwrap();
1050 let output_str = str::from_utf8(&stdout).unwrap();
1052 assert!(status.success());
1053 assert_eq!(output_str.trim().to_string(), "hello");
1054 assert_eq!(stderr, Vec::new());
1057 #[cfg(all(unix, not(target_os="android")))]
1058 pub fn env_cmd() -> Command {
1061 #[cfg(target_os="android")]
1062 pub fn env_cmd() -> Command {
1063 let mut cmd = Command::new("/system/bin/sh");
1064 cmd.arg("-c").arg("set");
1069 pub fn env_cmd() -> Command {
1070 let mut cmd = Command::new("cmd");
1071 cmd.arg("/c").arg("set");
1076 fn test_inherit_env() {
1079 let result = env_cmd().output().unwrap();
1080 let output = String::from_utf8(result.stdout).unwrap();
1082 for (ref k, ref v) in env::vars() {
1083 // don't check android RANDOM variables
1084 if cfg!(target_os = "android") && *k == "RANDOM" {
1088 // Windows has hidden environment variables whose names start with
1089 // equals signs (`=`). Those do not show up in the output of the
1091 assert!((cfg!(windows) && k.starts_with("=")) ||
1092 k.starts_with("DYLD") ||
1093 output.contains(&format!("{}={}", *k, *v)) ||
1094 output.contains(&format!("{}='{}'", *k, *v)),
1095 "output doesn't contain `{}={}`\n{}",
1101 fn test_override_env() {
1104 // In some build environments (such as chrooted Nix builds), `env` can
1105 // only be found in the explicitly-provided PATH env variable, not in
1106 // default places such as /bin or /usr/bin. So we need to pass through
1107 // PATH to our sub-process.
1108 let mut cmd = env_cmd();
1109 cmd.env_clear().env("RUN_TEST_NEW_ENV", "123");
1110 if let Some(p) = env::var_os("PATH") {
1111 cmd.env("PATH", &p);
1113 let result = cmd.output().unwrap();
1114 let output = String::from_utf8_lossy(&result.stdout).to_string();
1116 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1117 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1121 fn test_add_to_env() {
1122 let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
1123 let output = String::from_utf8_lossy(&result.stdout).to_string();
1125 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1126 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1129 // Regression tests for #30858.
1131 fn test_interior_nul_in_progname_is_error() {
1132 match Command::new("has-some-\0\0s-inside").spawn() {
1133 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1139 fn test_interior_nul_in_arg_is_error() {
1140 match Command::new("echo").arg("has-some-\0\0s-inside").spawn() {
1141 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1147 fn test_interior_nul_in_args_is_error() {
1148 match Command::new("echo").args(&["has-some-\0\0s-inside"]).spawn() {
1149 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1155 fn test_interior_nul_in_current_dir_is_error() {
1156 match Command::new("echo").current_dir("has-some-\0\0s-inside").spawn() {
1157 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1162 // Regression tests for #30862.
1164 fn test_interior_nul_in_env_key_is_error() {
1165 match env_cmd().env("has-some-\0\0s-inside", "value").spawn() {
1166 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1172 fn test_interior_nul_in_env_value_is_error() {
1173 match env_cmd().env("key", "has-some-\0\0s-inside").spawn() {
1174 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1179 /// Test that process creation flags work by debugging a process.
1180 /// Other creation flags make it hard or impossible to detect
1181 /// behavioral changes in the process.
1184 fn test_creation_flags() {
1185 use os::windows::process::CommandExt;
1186 use sys::c::{BOOL, DWORD, INFINITE};
1188 struct DEBUG_EVENT {
1189 pub event_code: DWORD,
1190 pub process_id: DWORD,
1191 pub thread_id: DWORD,
1192 // This is a union in the real struct, but we don't
1193 // need this data for the purposes of this test.
1194 pub _junk: [u8; 164],
1198 fn WaitForDebugEvent(lpDebugEvent: *mut DEBUG_EVENT, dwMilliseconds: DWORD) -> BOOL;
1199 fn ContinueDebugEvent(dwProcessId: DWORD, dwThreadId: DWORD,
1200 dwContinueStatus: DWORD) -> BOOL;
1203 const DEBUG_PROCESS: DWORD = 1;
1204 const EXIT_PROCESS_DEBUG_EVENT: DWORD = 5;
1205 const DBG_EXCEPTION_NOT_HANDLED: DWORD = 0x80010001;
1207 let mut child = Command::new("cmd")
1208 .creation_flags(DEBUG_PROCESS)
1209 .stdin(Stdio::piped()).spawn().unwrap();
1210 child.stdin.take().unwrap().write_all(b"exit\r\n").unwrap();
1212 let mut event = DEBUG_EVENT {
1219 if unsafe { WaitForDebugEvent(&mut event as *mut DEBUG_EVENT, INFINITE) } == 0 {
1220 panic!("WaitForDebugEvent failed!");
1224 if event.event_code == EXIT_PROCESS_DEBUG_EVENT {
1228 if unsafe { ContinueDebugEvent(event.process_id,
1230 DBG_EXCEPTION_NOT_HANDLED) } == 0 {
1231 panic!("ContinueDebugEvent failed!");
1234 assert!(events > 0);