]> git.lizzy.rs Git - rust.git/blob - src/libstd/process.rs
Rollup merge of #25614 - parir:patch-2, r=alexcrichton
[rust.git] / src / libstd / process.rs
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.
4 //
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.
10
11 //! Working with processes.
12
13 #![stable(feature = "process", since = "1.0.0")]
14 #![allow(non_upper_case_globals)]
15
16 use prelude::v1::*;
17 use io::prelude::*;
18
19 use ffi::OsStr;
20 use fmt;
21 use io::{self, Error, ErrorKind};
22 use path;
23 use sync::mpsc::{channel, Receiver};
24 use sys::pipe::{self, AnonPipe};
25 use sys::process::Command as CommandImp;
26 use sys::process::Process as ProcessImp;
27 use sys::process::ExitStatus as ExitStatusImp;
28 use sys::process::Stdio as StdioImp2;
29 use sys_common::{AsInner, AsInnerMut};
30 use thread;
31
32 /// Representation of a running or exited child process.
33 ///
34 /// This structure is used to represent and manage child processes. A child
35 /// process is created via the `Command` struct, which configures the spawning
36 /// process and can itself be constructed using a builder-style interface.
37 ///
38 /// # Examples
39 ///
40 /// ```should_panic
41 /// use std::process::Command;
42 ///
43 /// let mut child = Command::new("/bin/cat")
44 ///                         .arg("file.txt")
45 ///                         .spawn()
46 ///                         .unwrap_or_else(|e| { panic!("failed to execute child: {}", e) });
47 ///
48 /// let ecode = child.wait()
49 ///                  .unwrap_or_else(|e| { panic!("failed to wait on child: {}", e) });
50 ///
51 /// assert!(ecode.success());
52 /// ```
53 #[stable(feature = "process", since = "1.0.0")]
54 pub struct Child {
55     handle: ProcessImp,
56
57     /// None until wait() or wait_with_output() is called.
58     status: Option<ExitStatusImp>,
59
60     /// The handle for writing to the child's stdin, if it has been captured
61     #[stable(feature = "process", since = "1.0.0")]
62     pub stdin: Option<ChildStdin>,
63
64     /// The handle for reading from the child's stdout, if it has been captured
65     #[stable(feature = "process", since = "1.0.0")]
66     pub stdout: Option<ChildStdout>,
67
68     /// The handle for reading from the child's stderr, if it has been captured
69     #[stable(feature = "process", since = "1.0.0")]
70     pub stderr: Option<ChildStderr>,
71 }
72
73 /// A handle to a child procesess's stdin
74 #[stable(feature = "process", since = "1.0.0")]
75 pub struct ChildStdin {
76     inner: AnonPipe
77 }
78
79 #[stable(feature = "process", since = "1.0.0")]
80 impl Write for ChildStdin {
81     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
82         self.inner.write(buf)
83     }
84
85     fn flush(&mut self) -> io::Result<()> {
86         Ok(())
87     }
88 }
89
90 /// A handle to a child procesess's stdout
91 #[stable(feature = "process", since = "1.0.0")]
92 pub struct ChildStdout {
93     inner: AnonPipe
94 }
95
96 #[stable(feature = "process", since = "1.0.0")]
97 impl Read for ChildStdout {
98     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
99         self.inner.read(buf)
100     }
101 }
102
103 /// A handle to a child procesess's stderr
104 #[stable(feature = "process", since = "1.0.0")]
105 pub struct ChildStderr {
106     inner: AnonPipe
107 }
108
109 #[stable(feature = "process", since = "1.0.0")]
110 impl Read for ChildStderr {
111     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
112         self.inner.read(buf)
113     }
114 }
115
116 /// The `Command` type acts as a process builder, providing fine-grained control
117 /// over how a new process should be spawned. A default configuration can be
118 /// generated using `Command::new(program)`, where `program` gives a path to the
119 /// program to be executed. Additional builder methods allow the configuration
120 /// to be changed (for example, by adding arguments) prior to spawning:
121 ///
122 /// ```
123 /// use std::process::Command;
124 ///
125 /// let output = Command::new("sh")
126 ///                      .arg("-c")
127 ///                      .arg("echo hello")
128 ///                      .output()
129 ///                      .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
130 /// let hello = output.stdout;
131 /// ```
132 #[stable(feature = "process", since = "1.0.0")]
133 pub struct Command {
134     inner: CommandImp,
135
136     // Details explained in the builder methods
137     stdin: Option<StdioImp>,
138     stdout: Option<StdioImp>,
139     stderr: Option<StdioImp>,
140 }
141
142 impl Command {
143     /// Constructs a new `Command` for launching the program at
144     /// path `program`, with the following default configuration:
145     ///
146     /// * No arguments to the program
147     /// * Inherit the current process's environment
148     /// * Inherit the current process's working directory
149     /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
150     ///
151     /// Builder methods are provided to change these defaults and
152     /// otherwise configure the process.
153     #[stable(feature = "process", since = "1.0.0")]
154     pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
155         Command {
156             inner: CommandImp::new(program.as_ref()),
157             stdin: None,
158             stdout: None,
159             stderr: None,
160         }
161     }
162
163     /// Add an argument to pass to the program.
164     #[stable(feature = "process", since = "1.0.0")]
165     pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
166         self.inner.arg(arg.as_ref());
167         self
168     }
169
170     /// Add multiple arguments to pass to the program.
171     #[stable(feature = "process", since = "1.0.0")]
172     pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut Command {
173         self.inner.args(args.iter().map(AsRef::as_ref));
174         self
175     }
176
177     /// Inserts or updates an environment variable mapping.
178     ///
179     /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
180     /// and case-sensitive on all other platforms.
181     #[stable(feature = "process", since = "1.0.0")]
182     pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
183         where K: AsRef<OsStr>, V: AsRef<OsStr>
184     {
185         self.inner.env(key.as_ref(), val.as_ref());
186         self
187     }
188
189     /// Removes an environment variable mapping.
190     #[stable(feature = "process", since = "1.0.0")]
191     pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
192         self.inner.env_remove(key.as_ref());
193         self
194     }
195
196     /// Clears the entire environment map for the child process.
197     #[stable(feature = "process", since = "1.0.0")]
198     pub fn env_clear(&mut self) -> &mut Command {
199         self.inner.env_clear();
200         self
201     }
202
203     /// Sets the working directory for the child process.
204     #[stable(feature = "process", since = "1.0.0")]
205     pub fn current_dir<P: AsRef<path::Path>>(&mut self, dir: P) -> &mut Command {
206         self.inner.cwd(dir.as_ref().as_ref());
207         self
208     }
209
210     /// Configuration for the child process's stdin handle (file descriptor 0).
211     #[stable(feature = "process", since = "1.0.0")]
212     pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
213         self.stdin = Some(cfg.0);
214         self
215     }
216
217     /// Configuration for the child process's stdout handle (file descriptor 1).
218     #[stable(feature = "process", since = "1.0.0")]
219     pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
220         self.stdout = Some(cfg.0);
221         self
222     }
223
224     /// Configuration for the child process's stderr handle (file descriptor 2).
225     #[stable(feature = "process", since = "1.0.0")]
226     pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
227         self.stderr = Some(cfg.0);
228         self
229     }
230
231     fn spawn_inner(&self, default_io: StdioImp) -> io::Result<Child> {
232         let (their_stdin, our_stdin) = try!(
233             setup_io(self.stdin.as_ref().unwrap_or(&default_io), true)
234         );
235         let (their_stdout, our_stdout) = try!(
236             setup_io(self.stdout.as_ref().unwrap_or(&default_io), false)
237         );
238         let (their_stderr, our_stderr) = try!(
239             setup_io(self.stderr.as_ref().unwrap_or(&default_io), false)
240         );
241
242         match ProcessImp::spawn(&self.inner, their_stdin, their_stdout, their_stderr) {
243             Err(e) => Err(e),
244             Ok(handle) => Ok(Child {
245                 handle: handle,
246                 status: None,
247                 stdin: our_stdin.map(|fd| ChildStdin { inner: fd }),
248                 stdout: our_stdout.map(|fd| ChildStdout { inner: fd }),
249                 stderr: our_stderr.map(|fd| ChildStderr { inner: fd }),
250             })
251         }
252     }
253
254     /// Executes the command as a child process, returning a handle to it.
255     ///
256     /// By default, stdin, stdout and stderr are inherited by the parent.
257     #[stable(feature = "process", since = "1.0.0")]
258     pub fn spawn(&mut self) -> io::Result<Child> {
259         self.spawn_inner(StdioImp::Inherit)
260     }
261
262     /// Executes the command as a child process, waiting for it to finish and
263     /// collecting all of its output.
264     ///
265     /// By default, stdin, stdout and stderr are captured (and used to
266     /// provide the resulting output).
267     ///
268     /// # Examples
269     ///
270     /// ```
271     /// use std::process::Command;
272     /// let output = Command::new("cat").arg("foo.txt").output().unwrap_or_else(|e| {
273     ///     panic!("failed to execute process: {}", e)
274     /// });
275     ///
276     /// println!("status: {}", output.status);
277     /// println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
278     /// println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
279     /// ```
280     #[stable(feature = "process", since = "1.0.0")]
281     pub fn output(&mut self) -> io::Result<Output> {
282         self.spawn_inner(StdioImp::Piped).and_then(|p| p.wait_with_output())
283     }
284
285     /// Executes a command as a child process, waiting for it to finish and
286     /// collecting its exit status.
287     ///
288     /// By default, stdin, stdout and stderr are inherited by the parent.
289     ///
290     /// # Examples
291     ///
292     /// ```
293     /// use std::process::Command;
294     ///
295     /// let status = Command::new("ls").status().unwrap_or_else(|e| {
296     ///     panic!("failed to execute process: {}", e)
297     /// });
298     ///
299     /// println!("process exited with: {}", status);
300     /// ```
301     #[stable(feature = "process", since = "1.0.0")]
302     pub fn status(&mut self) -> io::Result<ExitStatus> {
303         self.spawn().and_then(|mut p| p.wait())
304     }
305 }
306
307 #[stable(feature = "rust1", since = "1.0.0")]
308 impl fmt::Debug for Command {
309     /// Format the program and arguments of a Command for display. Any
310     /// non-utf8 data is lossily converted using the utf8 replacement
311     /// character.
312     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
313         try!(write!(f, "{:?}", self.inner.program));
314         for arg in &self.inner.args {
315             try!(write!(f, " {:?}", arg));
316         }
317         Ok(())
318     }
319 }
320
321 impl AsInner<CommandImp> for Command {
322     fn as_inner(&self) -> &CommandImp { &self.inner }
323 }
324
325 impl AsInnerMut<CommandImp> for Command {
326     fn as_inner_mut(&mut self) -> &mut CommandImp { &mut self.inner }
327 }
328
329 fn setup_io(io: &StdioImp, readable: bool)
330             -> io::Result<(StdioImp2, Option<AnonPipe>)>
331 {
332     use self::StdioImp::*;
333     Ok(match *io {
334         Null => (StdioImp2::None, None),
335         Inherit => (StdioImp2::Inherit, None),
336         Piped => {
337             let (reader, writer) = try!(pipe::anon_pipe());
338             if readable {
339                 (StdioImp2::Piped(reader), Some(writer))
340             } else {
341                 (StdioImp2::Piped(writer), Some(reader))
342             }
343         }
344     })
345 }
346
347 /// The output of a finished process.
348 #[derive(PartialEq, Eq, Clone)]
349 #[stable(feature = "process", since = "1.0.0")]
350 pub struct Output {
351     /// The status (exit code) of the process.
352     #[stable(feature = "process", since = "1.0.0")]
353     pub status: ExitStatus,
354     /// The data that the process wrote to stdout.
355     #[stable(feature = "process", since = "1.0.0")]
356     pub stdout: Vec<u8>,
357     /// The data that the process wrote to stderr.
358     #[stable(feature = "process", since = "1.0.0")]
359     pub stderr: Vec<u8>,
360 }
361
362 /// Describes what to do with a standard I/O stream for a child process.
363 #[stable(feature = "process", since = "1.0.0")]
364 pub struct Stdio(StdioImp);
365
366 // The internal enum for stdio setup; see below for descriptions.
367 #[derive(Clone)]
368 enum StdioImp {
369     Piped,
370     Inherit,
371     Null,
372 }
373
374 impl Stdio {
375     /// A new pipe should be arranged to connect the parent and child processes.
376     #[stable(feature = "process", since = "1.0.0")]
377     pub fn piped() -> Stdio { Stdio(StdioImp::Piped) }
378
379     /// The child inherits from the corresponding parent descriptor.
380     #[stable(feature = "process", since = "1.0.0")]
381     pub fn inherit() -> Stdio { Stdio(StdioImp::Inherit) }
382
383     /// This stream will be ignored. This is the equivalent of attaching the
384     /// stream to `/dev/null`
385     #[stable(feature = "process", since = "1.0.0")]
386     pub fn null() -> Stdio { Stdio(StdioImp::Null) }
387 }
388
389 /// Describes the result of a process after it has terminated.
390 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
391 #[stable(feature = "process", since = "1.0.0")]
392 pub struct ExitStatus(ExitStatusImp);
393
394 impl ExitStatus {
395     /// Was termination successful? Signal termination not considered a success,
396     /// and success is defined as a zero exit status.
397     #[stable(feature = "process", since = "1.0.0")]
398     pub fn success(&self) -> bool {
399         self.0.success()
400     }
401
402     /// Returns the exit code of the process, if any.
403     ///
404     /// On Unix, this will return `None` if the process was terminated
405     /// by a signal; `std::os::unix` provides an extension trait for
406     /// extracting the signal and other details from the `ExitStatus`.
407     #[stable(feature = "process", since = "1.0.0")]
408     pub fn code(&self) -> Option<i32> {
409         self.0.code()
410     }
411 }
412
413 impl AsInner<ExitStatusImp> for ExitStatus {
414     fn as_inner(&self) -> &ExitStatusImp { &self.0 }
415 }
416
417 #[stable(feature = "process", since = "1.0.0")]
418 impl fmt::Display for ExitStatus {
419     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
420         self.0.fmt(f)
421     }
422 }
423
424 impl Child {
425     /// Forces the child to exit. This is equivalent to sending a
426     /// SIGKILL on unix platforms.
427     #[stable(feature = "process", since = "1.0.0")]
428     pub fn kill(&mut self) -> io::Result<()> {
429         #[cfg(unix)] fn collect_status(p: &mut Child) {
430             // On Linux (and possibly other unices), a process that has exited will
431             // continue to accept signals because it is "defunct". The delivery of
432             // signals will only fail once the child has been reaped. For this
433             // reason, if the process hasn't exited yet, then we attempt to collect
434             // their status with WNOHANG.
435             if p.status.is_none() {
436                 match p.handle.try_wait() {
437                     Some(status) => { p.status = Some(status); }
438                     None => {}
439                 }
440             }
441         }
442         #[cfg(windows)] fn collect_status(_p: &mut Child) {}
443
444         collect_status(self);
445
446         // if the process has finished, and therefore had waitpid called,
447         // and we kill it, then on unix we might ending up killing a
448         // newer process that happens to have the same (re-used) id
449         if self.status.is_some() {
450             return Err(Error::new(
451                 ErrorKind::InvalidInput,
452                 "invalid argument: can't kill an exited process",
453             ))
454         }
455
456         unsafe { self.handle.kill() }
457     }
458
459     /// Returns the OS-assigned process identifier associated with this child.
460     #[unstable(feature = "process_id", reason = "api recently added")]
461     pub fn id(&self) -> u32 {
462         self.handle.id()
463     }
464
465     /// Waits for the child to exit completely, returning the status that it
466     /// exited with. This function will continue to have the same return value
467     /// after it has been called at least once.
468     ///
469     /// The stdin handle to the child process, if any, will be closed
470     /// before waiting. This helps avoid deadlock: it ensures that the
471     /// child does not block waiting for input from the parent, while
472     /// the parent waits for the child to exit.
473     #[stable(feature = "process", since = "1.0.0")]
474     pub fn wait(&mut self) -> io::Result<ExitStatus> {
475         drop(self.stdin.take());
476         match self.status {
477             Some(code) => Ok(ExitStatus(code)),
478             None => {
479                 let status = try!(self.handle.wait());
480                 self.status = Some(status);
481                 Ok(ExitStatus(status))
482             }
483         }
484     }
485
486     /// Simultaneously waits for the child to exit and collect all remaining
487     /// output on the stdout/stderr handles, returning a `Output`
488     /// instance.
489     ///
490     /// The stdin handle to the child process, if any, will be closed
491     /// before waiting. This helps avoid deadlock: it ensures that the
492     /// child does not block waiting for input from the parent, while
493     /// the parent waits for the child to exit.
494     #[stable(feature = "process", since = "1.0.0")]
495     pub fn wait_with_output(mut self) -> io::Result<Output> {
496         drop(self.stdin.take());
497         fn read<T: Read + Send + 'static>(stream: Option<T>) -> Receiver<io::Result<Vec<u8>>> {
498             let (tx, rx) = channel();
499             match stream {
500                 Some(stream) => {
501                     thread::spawn(move || {
502                         let mut stream = stream;
503                         let mut ret = Vec::new();
504                         let res = stream.read_to_end(&mut ret);
505                         tx.send(res.map(|_| ret)).unwrap();
506                     });
507                 }
508                 None => tx.send(Ok(Vec::new())).unwrap()
509             }
510             rx
511         }
512         let stdout = read(self.stdout.take());
513         let stderr = read(self.stderr.take());
514         let status = try!(self.wait());
515
516         Ok(Output {
517             status: status,
518             stdout: stdout.recv().unwrap().unwrap_or(Vec::new()),
519             stderr:  stderr.recv().unwrap().unwrap_or(Vec::new()),
520         })
521     }
522 }
523
524 /// Terminates the current process with the specified exit code.
525 ///
526 /// This function will never return and will immediately terminate the current
527 /// process. The exit code is passed through to the underlying OS and will be
528 /// available for consumption by another process.
529 ///
530 /// Note that because this function never returns, and that it terminates the
531 /// process, no destructors on the current stack or any other thread's stack
532 /// will be run. If a clean shutdown is needed it is recommended to only call
533 /// this function at a known point where there are no more destructors left
534 /// to run.
535 #[stable(feature = "rust1", since = "1.0.0")]
536 pub fn exit(code: i32) -> ! {
537     ::sys::os::exit(code)
538 }
539
540 #[cfg(test)]
541 mod tests {
542     use prelude::v1::*;
543     use io::prelude::*;
544
545     use io::ErrorKind;
546     use rt::running_on_valgrind;
547     use str;
548     use super::{Command, Output, Stdio};
549
550     // FIXME(#10380) these tests should not all be ignored on android.
551
552     #[cfg(not(target_os="android"))]
553     #[test]
554     fn smoke() {
555         let p = Command::new("true").spawn();
556         assert!(p.is_ok());
557         let mut p = p.unwrap();
558         assert!(p.wait().unwrap().success());
559     }
560
561     #[cfg(not(target_os="android"))]
562     #[test]
563     fn smoke_failure() {
564         match Command::new("if-this-is-a-binary-then-the-world-has-ended").spawn() {
565             Ok(..) => panic!(),
566             Err(..) => {}
567         }
568     }
569
570     #[cfg(not(target_os="android"))]
571     #[test]
572     fn exit_reported_right() {
573         let p = Command::new("false").spawn();
574         assert!(p.is_ok());
575         let mut p = p.unwrap();
576         assert!(p.wait().unwrap().code() == Some(1));
577         drop(p.wait());
578     }
579
580     #[cfg(all(unix, not(target_os="android")))]
581     #[test]
582     fn signal_reported_right() {
583         use os::unix::process::ExitStatusExt;
584
585         let p = Command::new("/bin/sh").arg("-c").arg("kill -9 $$").spawn();
586         assert!(p.is_ok());
587         let mut p = p.unwrap();
588         match p.wait().unwrap().signal() {
589             Some(9) => {},
590             result => panic!("not terminated by signal 9 (instead, {:?})", result),
591         }
592     }
593
594     pub fn run_output(mut cmd: Command) -> String {
595         let p = cmd.spawn();
596         assert!(p.is_ok());
597         let mut p = p.unwrap();
598         assert!(p.stdout.is_some());
599         let mut ret = String::new();
600         p.stdout.as_mut().unwrap().read_to_string(&mut ret).unwrap();
601         assert!(p.wait().unwrap().success());
602         return ret;
603     }
604
605     #[cfg(not(target_os="android"))]
606     #[test]
607     fn stdout_works() {
608         let mut cmd = Command::new("echo");
609         cmd.arg("foobar").stdout(Stdio::piped());
610         assert_eq!(run_output(cmd), "foobar\n");
611     }
612
613     #[cfg(all(unix, not(target_os="android")))]
614     #[test]
615     fn set_current_dir_works() {
616         let mut cmd = Command::new("/bin/sh");
617         cmd.arg("-c").arg("pwd")
618            .current_dir("/")
619            .stdout(Stdio::piped());
620         assert_eq!(run_output(cmd), "/\n");
621     }
622
623     #[cfg(all(unix, not(target_os="android")))]
624     #[test]
625     fn stdin_works() {
626         let mut p = Command::new("/bin/sh")
627                             .arg("-c").arg("read line; echo $line")
628                             .stdin(Stdio::piped())
629                             .stdout(Stdio::piped())
630                             .spawn().unwrap();
631         p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap();
632         drop(p.stdin.take());
633         let mut out = String::new();
634         p.stdout.as_mut().unwrap().read_to_string(&mut out).unwrap();
635         assert!(p.wait().unwrap().success());
636         assert_eq!(out, "foobar\n");
637     }
638
639
640     #[cfg(all(unix, not(target_os="android")))]
641     #[test]
642     fn uid_works() {
643         use os::unix::prelude::*;
644         use libc;
645         let mut p = Command::new("/bin/sh")
646                             .arg("-c").arg("true")
647                             .uid(unsafe { libc::getuid() })
648                             .gid(unsafe { libc::getgid() })
649                             .spawn().unwrap();
650         assert!(p.wait().unwrap().success());
651     }
652
653     #[cfg(all(unix, not(target_os="android")))]
654     #[test]
655     fn uid_to_root_fails() {
656         use os::unix::prelude::*;
657         use libc;
658
659         // if we're already root, this isn't a valid test. Most of the bots run
660         // as non-root though (android is an exception).
661         if unsafe { libc::getuid() == 0 } { return }
662         assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
663     }
664
665     #[cfg(not(target_os="android"))]
666     #[test]
667     fn test_process_status() {
668         let mut status = Command::new("false").status().unwrap();
669         assert!(status.code() == Some(1));
670
671         status = Command::new("true").status().unwrap();
672         assert!(status.success());
673     }
674
675     #[test]
676     fn test_process_output_fail_to_start() {
677         match Command::new("/no-binary-by-this-name-should-exist").output() {
678             Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
679             Ok(..) => panic!()
680         }
681     }
682
683     #[cfg(not(target_os="android"))]
684     #[test]
685     fn test_process_output_output() {
686         let Output {status, stdout, stderr}
687              = Command::new("echo").arg("hello").output().unwrap();
688         let output_str = str::from_utf8(&stdout).unwrap();
689
690         assert!(status.success());
691         assert_eq!(output_str.trim().to_string(), "hello");
692         // FIXME #7224
693         if !running_on_valgrind() {
694             assert_eq!(stderr, Vec::new());
695         }
696     }
697
698     #[cfg(not(target_os="android"))]
699     #[test]
700     fn test_process_output_error() {
701         let Output {status, stdout, stderr}
702              = Command::new("mkdir").arg(".").output().unwrap();
703
704         assert!(status.code() == Some(1));
705         assert_eq!(stdout, Vec::new());
706         assert!(!stderr.is_empty());
707     }
708
709     #[cfg(not(target_os="android"))]
710     #[test]
711     fn test_finish_once() {
712         let mut prog = Command::new("false").spawn().unwrap();
713         assert!(prog.wait().unwrap().code() == Some(1));
714     }
715
716     #[cfg(not(target_os="android"))]
717     #[test]
718     fn test_finish_twice() {
719         let mut prog = Command::new("false").spawn().unwrap();
720         assert!(prog.wait().unwrap().code() == Some(1));
721         assert!(prog.wait().unwrap().code() == Some(1));
722     }
723
724     #[cfg(not(target_os="android"))]
725     #[test]
726     fn test_wait_with_output_once() {
727         let prog = Command::new("echo").arg("hello").stdout(Stdio::piped())
728             .spawn().unwrap();
729         let Output {status, stdout, stderr} = prog.wait_with_output().unwrap();
730         let output_str = str::from_utf8(&stdout).unwrap();
731
732         assert!(status.success());
733         assert_eq!(output_str.trim().to_string(), "hello");
734         // FIXME #7224
735         if !running_on_valgrind() {
736             assert_eq!(stderr, Vec::new());
737         }
738     }
739
740     #[cfg(all(unix, not(target_os="android")))]
741     pub fn pwd_cmd() -> Command {
742         Command::new("pwd")
743     }
744     #[cfg(target_os="android")]
745     pub fn pwd_cmd() -> Command {
746         let mut cmd = Command::new("/system/bin/sh");
747         cmd.arg("-c").arg("pwd");
748         cmd
749     }
750
751     #[cfg(windows)]
752     pub fn pwd_cmd() -> Command {
753         let mut cmd = Command::new("cmd");
754         cmd.arg("/c").arg("cd");
755         cmd
756     }
757
758     #[cfg(all(unix, not(target_os="android")))]
759     pub fn env_cmd() -> Command {
760         Command::new("env")
761     }
762     #[cfg(target_os="android")]
763     pub fn env_cmd() -> Command {
764         let mut cmd = Command::new("/system/bin/sh");
765         cmd.arg("-c").arg("set");
766         cmd
767     }
768
769     #[cfg(windows)]
770     pub fn env_cmd() -> Command {
771         let mut cmd = Command::new("cmd");
772         cmd.arg("/c").arg("set");
773         cmd
774     }
775
776     #[cfg(not(target_os="android"))]
777     #[test]
778     fn test_inherit_env() {
779         use std::env;
780         if running_on_valgrind() { return; }
781
782         let result = env_cmd().output().unwrap();
783         let output = String::from_utf8(result.stdout).unwrap();
784
785         for (ref k, ref v) in env::vars() {
786             // don't check windows magical empty-named variables
787             assert!(k.is_empty() ||
788                     output.contains(&format!("{}={}", *k, *v)),
789                     "output doesn't contain `{}={}`\n{}",
790                     k, v, output);
791         }
792     }
793     #[cfg(target_os="android")]
794     #[test]
795     fn test_inherit_env() {
796         use std::env;
797         if running_on_valgrind() { return; }
798
799         let mut result = env_cmd().output().unwrap();
800         let output = String::from_utf8(result.stdout).unwrap();
801
802         for (ref k, ref v) in env::vars() {
803             // don't check android RANDOM variables
804             if *k != "RANDOM".to_string() {
805                 assert!(output.contains(&format!("{}={}",
806                                                  *k,
807                                                  *v)) ||
808                         output.contains(&format!("{}=\'{}\'",
809                                                  *k,
810                                                  *v)));
811             }
812         }
813     }
814
815     #[test]
816     fn test_override_env() {
817         use env;
818
819         // In some build environments (such as chrooted Nix builds), `env` can
820         // only be found in the explicitly-provided PATH env variable, not in
821         // default places such as /bin or /usr/bin. So we need to pass through
822         // PATH to our sub-process.
823         let mut cmd = env_cmd();
824         cmd.env_clear().env("RUN_TEST_NEW_ENV", "123");
825         if let Some(p) = env::var_os("PATH") {
826             cmd.env("PATH", &p);
827         }
828         let result = cmd.output().unwrap();
829         let output = String::from_utf8_lossy(&result.stdout).to_string();
830
831         assert!(output.contains("RUN_TEST_NEW_ENV=123"),
832                 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
833     }
834
835     #[test]
836     fn test_add_to_env() {
837         let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
838         let output = String::from_utf8_lossy(&result.stdout).to_string();
839
840         assert!(output.contains("RUN_TEST_NEW_ENV=123"),
841                 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
842     }
843 }