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