]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/process.rs
rollup merge of #21457: alexcrichton/issue-21436
[rust.git] / src / libstd / io / process.rs
1 // Copyright 2013 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 //! Bindings for executing child processes
12
13 #![allow(unstable)]
14 #![allow(non_upper_case_globals)]
15
16 pub use self::StdioContainer::*;
17 pub use self::ProcessExit::*;
18
19 use prelude::v1::*;
20
21 use collections::HashMap;
22 use ffi::CString;
23 use fmt;
24 use io::pipe::{PipeStream, PipePair};
25 use io::{IoResult, IoError};
26 use io;
27 use libc;
28 use os;
29 use path::BytesContainer;
30 use sync::mpsc::{channel, Receiver};
31 use sys::fs::FileDesc;
32 use sys::process::Process as ProcessImp;
33 use sys;
34 use thread::Thread;
35
36 #[cfg(windows)] use hash;
37 #[cfg(windows)] use str;
38
39 /// Signal a process to exit, without forcibly killing it. Corresponds to
40 /// SIGTERM on unix platforms.
41 #[cfg(windows)] pub const PleaseExitSignal: int = 15;
42 /// Signal a process to exit immediately, forcibly killing it. Corresponds to
43 /// SIGKILL on unix platforms.
44 #[cfg(windows)] pub const MustDieSignal: int = 9;
45 /// Signal a process to exit, without forcibly killing it. Corresponds to
46 /// SIGTERM on unix platforms.
47 #[cfg(not(windows))] pub const PleaseExitSignal: int = libc::SIGTERM as int;
48 /// Signal a process to exit immediately, forcibly killing it. Corresponds to
49 /// SIGKILL on unix platforms.
50 #[cfg(not(windows))] pub const MustDieSignal: int = libc::SIGKILL as int;
51
52 /// Representation of a running or exited child process.
53 ///
54 /// This structure is used to represent and manage child processes. A child
55 /// process is created via the `Command` struct, which configures the spawning
56 /// process and can itself be constructed using a builder-style interface.
57 ///
58 /// # Example
59 ///
60 /// ```should_fail
61 /// use std::io::Command;
62 ///
63 /// let mut child = match Command::new("/bin/cat").arg("file.txt").spawn() {
64 ///     Ok(child) => child,
65 ///     Err(e) => panic!("failed to execute child: {}", e),
66 /// };
67 ///
68 /// let contents = child.stdout.as_mut().unwrap().read_to_end();
69 /// assert!(child.wait().unwrap().success());
70 /// ```
71 pub struct Process {
72     handle: ProcessImp,
73     forget: bool,
74
75     /// None until wait() is called.
76     exit_code: Option<ProcessExit>,
77
78     /// Manually delivered signal
79     exit_signal: Option<int>,
80
81     /// Deadline after which wait() will return
82     deadline: u64,
83
84     /// Handle to the child's stdin, if the `stdin` field of this process's
85     /// `ProcessConfig` was `CreatePipe`. By default, this handle is `Some`.
86     pub stdin: Option<PipeStream>,
87
88     /// Handle to the child's stdout, if the `stdout` field of this process's
89     /// `ProcessConfig` was `CreatePipe`. By default, this handle is `Some`.
90     pub stdout: Option<PipeStream>,
91
92     /// Handle to the child's stderr, if the `stderr` field of this process's
93     /// `ProcessConfig` was `CreatePipe`. By default, this handle is `Some`.
94     pub stderr: Option<PipeStream>,
95 }
96
97 /// A representation of environment variable name
98 /// It compares case-insensitive on Windows and case-sensitive everywhere else.
99 #[cfg(not(windows))]
100 #[derive(Hash, PartialEq, Eq, Clone, Show)]
101 struct EnvKey(CString);
102
103 #[doc(hidden)]
104 #[cfg(windows)]
105 #[derive(Eq, Clone, Show)]
106 struct EnvKey(CString);
107
108 #[cfg(windows)]
109 impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for EnvKey {
110     fn hash(&self, state: &mut H) {
111         let &EnvKey(ref x) = self;
112         match str::from_utf8(x.as_bytes()) {
113             Ok(s) => for ch in s.chars() {
114                 (ch as u8 as char).to_lowercase().hash(state);
115             },
116             Err(..) => x.hash(state)
117         }
118     }
119 }
120
121 #[cfg(windows)]
122 impl PartialEq for EnvKey {
123     fn eq(&self, other: &EnvKey) -> bool {
124         let &EnvKey(ref x) = self;
125         let &EnvKey(ref y) = other;
126         match (str::from_utf8(x.as_bytes()), str::from_utf8(y.as_bytes())) {
127             (Ok(xs), Ok(ys)) => {
128                 if xs.len() != ys.len() {
129                     return false
130                 } else {
131                     for (xch, ych) in xs.chars().zip(ys.chars()) {
132                         if xch.to_lowercase() != ych.to_lowercase() {
133                             return false;
134                         }
135                     }
136                     return true;
137                 }
138             },
139             // If either is not a valid utf8 string, just compare them byte-wise
140             _ => return x.eq(y)
141         }
142     }
143 }
144
145 impl BytesContainer for EnvKey {
146     fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
147         let &EnvKey(ref k) = self;
148         k.container_as_bytes()
149     }
150 }
151
152 /// A HashMap representation of environment variables.
153 pub type EnvMap = HashMap<EnvKey, CString>;
154
155 /// The `Command` type acts as a process builder, providing fine-grained control
156 /// over how a new process should be spawned. A default configuration can be
157 /// generated using `Command::new(program)`, where `program` gives a path to the
158 /// program to be executed. Additional builder methods allow the configuration
159 /// to be changed (for example, by adding arguments) prior to spawning:
160 ///
161 /// ```
162 /// use std::io::Command;
163 ///
164 /// let mut process = match Command::new("sh").arg("-c").arg("echo hello").spawn() {
165 ///   Ok(p) => p,
166 ///   Err(e) => panic!("failed to execute process: {}", e),
167 /// };
168 ///
169 /// let output = process.stdout.as_mut().unwrap().read_to_end();
170 /// ```
171 #[derive(Clone)]
172 pub struct Command {
173     // The internal data for the builder. Documented by the builder
174     // methods below, and serialized into rt::rtio::ProcessConfig.
175     program: CString,
176     args: Vec<CString>,
177     env: Option<EnvMap>,
178     cwd: Option<CString>,
179     stdin: StdioContainer,
180     stdout: StdioContainer,
181     stderr: StdioContainer,
182     uid: Option<uint>,
183     gid: Option<uint>,
184     detach: bool,
185 }
186
187 // FIXME (#12938): Until DST lands, we cannot decompose &str into & and str, so
188 // we cannot usefully take BytesContainer arguments by reference (without forcing an
189 // additional & around &str). So we are instead temporarily adding an instance
190 // for &Path, so that we can take BytesContainer as owned. When DST lands, the &Path
191 // instance should be removed, and arguments bound by BytesContainer should be passed by
192 // reference. (Here: {new, arg, args, env}.)
193
194 impl Command {
195     /// Constructs a new `Command` for launching the program at
196     /// path `program`, with the following default configuration:
197     ///
198     /// * No arguments to the program
199     /// * Inherit the current process's environment
200     /// * Inherit the current process's working directory
201     /// * A readable pipe for stdin (file descriptor 0)
202     /// * A writeable pipe for stdout and stderr (file descriptors 1 and 2)
203     ///
204     /// Builder methods are provided to change these defaults and
205     /// otherwise configure the process.
206     pub fn new<T: BytesContainer>(program: T) -> Command {
207         Command {
208             program: CString::from_slice(program.container_as_bytes()),
209             args: Vec::new(),
210             env: None,
211             cwd: None,
212             stdin: CreatePipe(true, false),
213             stdout: CreatePipe(false, true),
214             stderr: CreatePipe(false, true),
215             uid: None,
216             gid: None,
217             detach: false,
218         }
219     }
220
221     /// Add an argument to pass to the program.
222     pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command {
223         self.args.push(CString::from_slice(arg.container_as_bytes()));
224         self
225     }
226
227     /// Add multiple arguments to pass to the program.
228     pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command {
229         self.args.extend(args.iter().map(|arg| {
230             CString::from_slice(arg.container_as_bytes())
231         }));
232         self
233     }
234     // Get a mutable borrow of the environment variable map for this `Command`.
235     fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap {
236         match self.env {
237             Some(ref mut map) => map,
238             None => {
239                 // if the env is currently just inheriting from the parent's,
240                 // materialize the parent's env into a hashtable.
241                 self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| {
242                     (EnvKey(CString::from_slice(k.as_slice())),
243                      CString::from_slice(v.as_slice()))
244                 }).collect());
245                 self.env.as_mut().unwrap()
246             }
247         }
248     }
249
250     /// Inserts or updates an environment variable mapping.
251     ///
252     /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
253     /// and case-sensitive on all other platforms.
254     pub fn env<'a, T, U>(&'a mut self, key: T, val: U)
255                          -> &'a mut Command
256                          where T: BytesContainer, U: BytesContainer {
257         let key = EnvKey(CString::from_slice(key.container_as_bytes()));
258         let val = CString::from_slice(val.container_as_bytes());
259         self.get_env_map().insert(key, val);
260         self
261     }
262
263     /// Removes an environment variable mapping.
264     pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command
265                              where T: BytesContainer {
266         let key = EnvKey(CString::from_slice(key.container_as_bytes()));
267         self.get_env_map().remove(&key);
268         self
269     }
270
271     /// Sets the entire environment map for the child process.
272     ///
273     /// If the given slice contains multiple instances of an environment
274     /// variable, the *rightmost* instance will determine the value.
275     pub fn env_set_all<'a, T, U>(&'a mut self, env: &[(T,U)])
276                                  -> &'a mut Command
277                                  where T: BytesContainer, U: BytesContainer {
278         self.env = Some(env.iter().map(|&(ref k, ref v)| {
279             (EnvKey(CString::from_slice(k.container_as_bytes())),
280              CString::from_slice(v.container_as_bytes()))
281         }).collect());
282         self
283     }
284
285     /// Set the working directory for the child process.
286     pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command {
287         self.cwd = Some(CString::from_slice(dir.as_vec()));
288         self
289     }
290
291     /// Configuration for the child process's stdin handle (file descriptor 0).
292     /// Defaults to `CreatePipe(true, false)` so the input can be written to.
293     pub fn stdin<'a>(&'a mut self, cfg: StdioContainer) -> &'a mut Command {
294         self.stdin = cfg;
295         self
296     }
297
298     /// Configuration for the child process's stdout handle (file descriptor 1).
299     /// Defaults to `CreatePipe(false, true)` so the output can be collected.
300     pub fn stdout<'a>(&'a mut self, cfg: StdioContainer) -> &'a mut Command {
301         self.stdout = cfg;
302         self
303     }
304
305     /// Configuration for the child process's stderr handle (file descriptor 2).
306     /// Defaults to `CreatePipe(false, true)` so the output can be collected.
307     pub fn stderr<'a>(&'a mut self, cfg: StdioContainer) -> &'a mut Command {
308         self.stderr = cfg;
309         self
310     }
311
312     /// Sets the child process's user id. This translates to a `setuid` call in
313     /// the child process. Setting this value on windows will cause the spawn to
314     /// fail. Failure in the `setuid` call on unix will also cause the spawn to
315     /// fail.
316     pub fn uid<'a>(&'a mut self, id: uint) -> &'a mut Command {
317         self.uid = Some(id);
318         self
319     }
320
321     /// Similar to `uid`, but sets the group id of the child process. This has
322     /// the same semantics as the `uid` field.
323     pub fn gid<'a>(&'a mut self, id: uint) -> &'a mut Command {
324         self.gid = Some(id);
325         self
326     }
327
328     /// Sets the child process to be spawned in a detached state. On unix, this
329     /// means that the child is the leader of a new process group.
330     pub fn detached<'a>(&'a mut self) -> &'a mut Command {
331         self.detach = true;
332         self
333     }
334
335     /// Executes the command as a child process, which is returned.
336     pub fn spawn(&self) -> IoResult<Process> {
337         let (their_stdin, our_stdin) = try!(setup_io(self.stdin));
338         let (their_stdout, our_stdout) = try!(setup_io(self.stdout));
339         let (their_stderr, our_stderr) = try!(setup_io(self.stderr));
340
341         match ProcessImp::spawn(self, their_stdin, their_stdout, their_stderr) {
342             Err(e) => Err(e),
343             Ok(handle) => Ok(Process {
344                 handle: handle,
345                 forget: false,
346                 exit_code: None,
347                 exit_signal: None,
348                 deadline: 0,
349                 stdin: our_stdin,
350                 stdout: our_stdout,
351                 stderr: our_stderr,
352             })
353         }
354     }
355
356     /// Executes the command as a child process, waiting for it to finish and
357     /// collecting all of its output.
358     ///
359     /// # Example
360     ///
361     /// ```
362     /// use std::io::Command;
363     ///
364     /// let output = match Command::new("cat").arg("foot.txt").output() {
365     ///     Ok(output) => output,
366     ///     Err(e) => panic!("failed to execute process: {}", e),
367     /// };
368     ///
369     /// println!("status: {}", output.status);
370     /// println!("stdout: {}", String::from_utf8_lossy(output.output.as_slice()));
371     /// println!("stderr: {}", String::from_utf8_lossy(output.error.as_slice()));
372     /// ```
373     pub fn output(&self) -> IoResult<ProcessOutput> {
374         self.spawn().and_then(|p| p.wait_with_output())
375     }
376
377     /// Executes a command as a child process, waiting for it to finish and
378     /// collecting its exit status.
379     ///
380     /// # Example
381     ///
382     /// ```
383     /// use std::io::Command;
384     ///
385     /// let status = match Command::new("ls").status() {
386     ///     Ok(status) => status,
387     ///     Err(e) => panic!("failed to execute process: {}", e),
388     /// };
389     ///
390     /// println!("process exited with: {}", status);
391     /// ```
392     pub fn status(&self) -> IoResult<ProcessExit> {
393         self.spawn().and_then(|mut p| p.wait())
394     }
395 }
396
397 impl fmt::Debug for Command {
398     /// Format the program and arguments of a Command for display. Any
399     /// non-utf8 data is lossily converted using the utf8 replacement
400     /// character.
401     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
402         try!(write!(f, "{}", String::from_utf8_lossy(self.program.as_bytes())));
403         for arg in self.args.iter() {
404             try!(write!(f, " '{}'", String::from_utf8_lossy(arg.as_bytes())));
405         }
406         Ok(())
407     }
408 }
409
410 fn setup_io(io: StdioContainer) -> IoResult<(Option<PipeStream>, Option<PipeStream>)> {
411     let ours;
412     let theirs;
413     match io {
414         Ignored => {
415             theirs = None;
416             ours = None;
417         }
418         InheritFd(fd) => {
419             theirs = Some(PipeStream::from_filedesc(FileDesc::new(fd, false)));
420             ours = None;
421         }
422         CreatePipe(readable, _writable) => {
423             let PipePair { reader, writer } = try!(PipeStream::pair());
424             if readable {
425                 theirs = Some(reader);
426                 ours = Some(writer);
427             } else {
428                 theirs = Some(writer);
429                 ours = Some(reader);
430             }
431         }
432     }
433     Ok((theirs, ours))
434 }
435
436 // Allow the sys module to get access to the Command state
437 impl sys::process::ProcessConfig<EnvKey, CString> for Command {
438     fn program(&self) -> &CString {
439         &self.program
440     }
441     fn args(&self) -> &[CString] {
442         self.args.as_slice()
443     }
444     fn env(&self) -> Option<&EnvMap> {
445         self.env.as_ref()
446     }
447     fn cwd(&self) -> Option<&CString> {
448         self.cwd.as_ref()
449     }
450     fn uid(&self) -> Option<uint> {
451         self.uid.clone()
452     }
453     fn gid(&self) -> Option<uint> {
454         self.gid.clone()
455     }
456     fn detach(&self) -> bool {
457         self.detach
458     }
459
460 }
461
462 /// The output of a finished process.
463 #[derive(PartialEq, Eq, Clone)]
464 pub struct ProcessOutput {
465     /// The status (exit code) of the process.
466     pub status: ProcessExit,
467     /// The data that the process wrote to stdout.
468     pub output: Vec<u8>,
469     /// The data that the process wrote to stderr.
470     pub error: Vec<u8>,
471 }
472
473 /// Describes what to do with a standard io stream for a child process.
474 #[derive(Clone, Copy)]
475 pub enum StdioContainer {
476     /// This stream will be ignored. This is the equivalent of attaching the
477     /// stream to `/dev/null`
478     Ignored,
479
480     /// The specified file descriptor is inherited for the stream which it is
481     /// specified for. Ownership of the file descriptor is *not* taken, so the
482     /// caller must clean it up.
483     InheritFd(libc::c_int),
484
485     /// Creates a pipe for the specified file descriptor which will be created
486     /// when the process is spawned.
487     ///
488     /// The first boolean argument is whether the pipe is readable, and the
489     /// second is whether it is writable. These properties are from the view of
490     /// the *child* process, not the parent process.
491     CreatePipe(bool /* readable */, bool /* writable */),
492 }
493
494 /// Describes the result of a process after it has terminated.
495 /// Note that Windows have no signals, so the result is usually ExitStatus.
496 #[derive(PartialEq, Eq, Clone, Copy, Show)]
497 pub enum ProcessExit {
498     /// Normal termination with an exit status.
499     ExitStatus(int),
500
501     /// Termination by signal, with the signal number.
502     ExitSignal(int),
503 }
504
505 #[stable]
506 impl fmt::Display for ProcessExit {
507     /// Format a ProcessExit enum, to nicely present the information.
508     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
509         match *self {
510             ExitStatus(code) =>  write!(f, "exit code: {}", code),
511             ExitSignal(code) =>  write!(f, "signal: {}", code),
512         }
513     }
514 }
515
516 impl ProcessExit {
517     /// Was termination successful? Signal termination not considered a success,
518     /// and success is defined as a zero exit status.
519     pub fn success(&self) -> bool {
520         return self.matches_exit_status(0);
521     }
522
523     /// Checks whether this ProcessExit matches the given exit status.
524     /// Termination by signal will never match an exit code.
525     pub fn matches_exit_status(&self, wanted: int) -> bool {
526         *self == ExitStatus(wanted)
527     }
528 }
529
530 impl Process {
531     /// Sends `signal` to another process in the system identified by `id`.
532     ///
533     /// Note that windows doesn't quite have the same model as unix, so some
534     /// unix signals are mapped to windows signals. Notably, unix termination
535     /// signals (SIGTERM/SIGKILL/SIGINT) are translated to `TerminateProcess`.
536     ///
537     /// Additionally, a signal number of 0 can check for existence of the target
538     /// process. Note, though, that on some platforms signals will continue to
539     /// be successfully delivered if the child has exited, but not yet been
540     /// reaped.
541     pub fn kill(id: libc::pid_t, signal: int) -> IoResult<()> {
542         unsafe { ProcessImp::killpid(id, signal) }
543     }
544
545     /// Returns the process id of this child process
546     pub fn id(&self) -> libc::pid_t { self.handle.id() }
547
548     /// Sends the specified signal to the child process, returning whether the
549     /// signal could be delivered or not.
550     ///
551     /// Note that signal 0 is interpreted as a poll to check whether the child
552     /// process is still alive or not. If an error is returned, then the child
553     /// process has exited.
554     ///
555     /// On some unix platforms signals will continue to be received after a
556     /// child has exited but not yet been reaped. In order to report the status
557     /// of signal delivery correctly, unix implementations may invoke
558     /// `waitpid()` with `WNOHANG` in order to reap the child as necessary.
559     ///
560     /// # Errors
561     ///
562     /// If the signal delivery fails, the corresponding error is returned.
563     pub fn signal(&mut self, signal: int) -> IoResult<()> {
564         #[cfg(unix)] fn collect_status(p: &mut Process) {
565             // On Linux (and possibly other unices), a process that has exited will
566             // continue to accept signals because it is "defunct". The delivery of
567             // signals will only fail once the child has been reaped. For this
568             // reason, if the process hasn't exited yet, then we attempt to collect
569             // their status with WNOHANG.
570             if p.exit_code.is_none() {
571                 match p.handle.try_wait() {
572                     Some(code) => { p.exit_code = Some(code); }
573                     None => {}
574                 }
575             }
576         }
577         #[cfg(windows)] fn collect_status(_p: &mut Process) {}
578
579         collect_status(self);
580
581         // if the process has finished, and therefore had waitpid called,
582         // and we kill it, then on unix we might ending up killing a
583         // newer process that happens to have the same (re-used) id
584         if self.exit_code.is_some() {
585             return Err(IoError {
586                 kind: io::InvalidInput,
587                 desc: "invalid argument: can't kill an exited process",
588                 detail: None,
589             })
590         }
591
592         // A successfully delivered signal that isn't 0 (just a poll for being
593         // alive) is recorded for windows (see wait())
594         match unsafe { self.handle.kill(signal) } {
595             Ok(()) if signal == 0 => Ok(()),
596             Ok(()) => { self.exit_signal = Some(signal); Ok(()) }
597             Err(e) => Err(e),
598         }
599
600     }
601
602     /// Sends a signal to this child requesting that it exits. This is
603     /// equivalent to sending a SIGTERM on unix platforms.
604     pub fn signal_exit(&mut self) -> IoResult<()> {
605         self.signal(PleaseExitSignal)
606     }
607
608     /// Sends a signal to this child forcing it to exit. This is equivalent to
609     /// sending a SIGKILL on unix platforms.
610     pub fn signal_kill(&mut self) -> IoResult<()> {
611         self.signal(MustDieSignal)
612     }
613
614     /// Wait for the child to exit completely, returning the status that it
615     /// exited with. This function will continue to have the same return value
616     /// after it has been called at least once.
617     ///
618     /// The stdin handle to the child process will be closed before waiting.
619     ///
620     /// # Errors
621     ///
622     /// This function can fail if a timeout was previously specified via
623     /// `set_timeout` and the timeout expires before the child exits.
624     pub fn wait(&mut self) -> IoResult<ProcessExit> {
625         drop(self.stdin.take());
626         match self.exit_code {
627             Some(code) => Ok(code),
628             None => {
629                 let code = try!(self.handle.wait(self.deadline));
630                 // On windows, waitpid will never return a signal. If a signal
631                 // was successfully delivered to the process, however, we can
632                 // consider it as having died via a signal.
633                 let code = match self.exit_signal {
634                     None => code,
635                     Some(signal) if cfg!(windows) => ExitSignal(signal),
636                     Some(..) => code,
637                 };
638                 self.exit_code = Some(code);
639                 Ok(code)
640             }
641         }
642     }
643
644     /// Sets a timeout, in milliseconds, for future calls to wait().
645     ///
646     /// The argument specified is a relative distance into the future, in
647     /// milliseconds, after which any call to wait() will return immediately
648     /// with a timeout error, and all future calls to wait() will not block.
649     ///
650     /// A value of `None` will clear any previous timeout, and a value of `Some`
651     /// will override any previously set timeout.
652     ///
653     /// # Example
654     ///
655     /// ```no_run
656     /// # #![allow(unstable)]
657     /// use std::io::{Command, IoResult};
658     /// use std::io::process::ProcessExit;
659     ///
660     /// fn run_gracefully(prog: &str) -> IoResult<ProcessExit> {
661     ///     let mut p = try!(Command::new("long-running-process").spawn());
662     ///
663     ///     // give the process 10 seconds to finish completely
664     ///     p.set_timeout(Some(10_000));
665     ///     match p.wait() {
666     ///         Ok(status) => return Ok(status),
667     ///         Err(..) => {}
668     ///     }
669     ///
670     ///     // Attempt to exit gracefully, but don't wait for it too long
671     ///     try!(p.signal_exit());
672     ///     p.set_timeout(Some(1_000));
673     ///     match p.wait() {
674     ///         Ok(status) => return Ok(status),
675     ///         Err(..) => {}
676     ///     }
677     ///
678     ///     // Well, we did our best, forcefully kill the process
679     ///     try!(p.signal_kill());
680     ///     p.set_timeout(None);
681     ///     p.wait()
682     /// }
683     /// ```
684     #[unstable = "the type of the timeout is likely to change"]
685     pub fn set_timeout(&mut self, timeout_ms: Option<u64>) {
686         self.deadline = timeout_ms.map(|i| i + sys::timer::now()).unwrap_or(0);
687     }
688
689     /// Simultaneously wait for the child to exit and collect all remaining
690     /// output on the stdout/stderr handles, returning a `ProcessOutput`
691     /// instance.
692     ///
693     /// The stdin handle to the child is closed before waiting.
694     ///
695     /// # Errors
696     ///
697     /// This function can fail for any of the same reasons that `wait()` can
698     /// fail.
699     pub fn wait_with_output(mut self) -> IoResult<ProcessOutput> {
700         drop(self.stdin.take());
701         fn read(stream: Option<io::PipeStream>) -> Receiver<IoResult<Vec<u8>>> {
702             let (tx, rx) = channel();
703             match stream {
704                 Some(stream) => {
705                     Thread::spawn(move |:| {
706                         let mut stream = stream;
707                         tx.send(stream.read_to_end()).unwrap();
708                     });
709                 }
710                 None => tx.send(Ok(Vec::new())).unwrap()
711             }
712             rx
713         }
714         let stdout = read(self.stdout.take());
715         let stderr = read(self.stderr.take());
716
717         let status = try!(self.wait());
718
719         Ok(ProcessOutput {
720             status: status,
721             output: stdout.recv().unwrap().unwrap_or(Vec::new()),
722             error:  stderr.recv().unwrap().unwrap_or(Vec::new()),
723         })
724     }
725
726     /// Forgets this process, allowing it to outlive the parent
727     ///
728     /// This function will forcefully prevent calling `wait()` on the child
729     /// process in the destructor, allowing the child to outlive the
730     /// parent. Note that this operation can easily lead to leaking the
731     /// resources of the child process, so care must be taken when
732     /// invoking this method.
733     pub fn forget(mut self) {
734         self.forget = true;
735     }
736 }
737
738 impl Drop for Process {
739     fn drop(&mut self) {
740         if self.forget { return }
741
742         // Close all I/O before exiting to ensure that the child doesn't wait
743         // forever to print some text or something similar.
744         drop(self.stdin.take());
745         drop(self.stdout.take());
746         drop(self.stderr.take());
747
748         self.set_timeout(None);
749         let _ = self.wait().unwrap();
750     }
751 }
752
753 #[cfg(test)]
754 mod tests {
755     use io::{Truncate, Write, TimedOut, timer, process, FileNotFound};
756     use prelude::v1::{Ok, Err, range, drop, Some, None, Vec};
757     use prelude::v1::{Path, String, Reader, Writer, Clone};
758     use prelude::v1::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath};
759     use io::fs::PathExtensions;
760     use io::timer::*;
761     use rt::running_on_valgrind;
762     use str;
763     use super::{CreatePipe};
764     use super::{InheritFd, Process, PleaseExitSignal, Command, ProcessOutput};
765     use sync::mpsc::channel;
766     use thread::Thread;
767     use time::Duration;
768
769     // FIXME(#10380) these tests should not all be ignored on android.
770
771     #[cfg(not(target_os="android"))]
772     #[test]
773     fn smoke() {
774         let p = Command::new("true").spawn();
775         assert!(p.is_ok());
776         let mut p = p.unwrap();
777         assert!(p.wait().unwrap().success());
778     }
779
780     #[cfg(not(target_os="android"))]
781     #[test]
782     fn smoke_failure() {
783         match Command::new("if-this-is-a-binary-then-the-world-has-ended").spawn() {
784             Ok(..) => panic!(),
785             Err(..) => {}
786         }
787     }
788
789     #[cfg(not(target_os="android"))]
790     #[test]
791     fn exit_reported_right() {
792         let p = Command::new("false").spawn();
793         assert!(p.is_ok());
794         let mut p = p.unwrap();
795         assert!(p.wait().unwrap().matches_exit_status(1));
796         drop(p.wait().clone());
797     }
798
799     #[cfg(all(unix, not(target_os="android")))]
800     #[test]
801     fn signal_reported_right() {
802         let p = Command::new("/bin/sh").arg("-c").arg("kill -1 $$").spawn();
803         assert!(p.is_ok());
804         let mut p = p.unwrap();
805         match p.wait().unwrap() {
806             process::ExitSignal(1) => {},
807             result => panic!("not terminated by signal 1 (instead, {})", result),
808         }
809     }
810
811     pub fn read_all(input: &mut Reader) -> String {
812         input.read_to_string().unwrap()
813     }
814
815     pub fn run_output(cmd: Command) -> String {
816         let p = cmd.spawn();
817         assert!(p.is_ok());
818         let mut p = p.unwrap();
819         assert!(p.stdout.is_some());
820         let ret = read_all(p.stdout.as_mut().unwrap() as &mut Reader);
821         assert!(p.wait().unwrap().success());
822         return ret;
823     }
824
825     #[cfg(not(target_os="android"))]
826     #[test]
827     fn stdout_works() {
828         let mut cmd = Command::new("echo");
829         cmd.arg("foobar").stdout(CreatePipe(false, true));
830         assert_eq!(run_output(cmd), "foobar\n");
831     }
832
833     #[cfg(all(unix, not(target_os="android")))]
834     #[test]
835     fn set_cwd_works() {
836         let mut cmd = Command::new("/bin/sh");
837         cmd.arg("-c").arg("pwd")
838            .cwd(&Path::new("/"))
839            .stdout(CreatePipe(false, true));
840         assert_eq!(run_output(cmd), "/\n");
841     }
842
843     #[cfg(all(unix, not(target_os="android")))]
844     #[test]
845     fn stdin_works() {
846         let mut p = Command::new("/bin/sh")
847                             .arg("-c").arg("read line; echo $line")
848                             .stdin(CreatePipe(true, false))
849                             .stdout(CreatePipe(false, true))
850                             .spawn().unwrap();
851         p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap();
852         drop(p.stdin.take());
853         let out = read_all(p.stdout.as_mut().unwrap() as &mut Reader);
854         assert!(p.wait().unwrap().success());
855         assert_eq!(out, "foobar\n");
856     }
857
858     #[cfg(not(target_os="android"))]
859     #[test]
860     fn detach_works() {
861         let mut p = Command::new("true").detached().spawn().unwrap();
862         assert!(p.wait().unwrap().success());
863     }
864
865     #[cfg(windows)]
866     #[test]
867     fn uid_fails_on_windows() {
868         assert!(Command::new("test").uid(10).spawn().is_err());
869     }
870
871     #[cfg(all(unix, not(target_os="android")))]
872     #[test]
873     fn uid_works() {
874         use libc;
875         let mut p = Command::new("/bin/sh")
876                             .arg("-c").arg("true")
877                             .uid(unsafe { libc::getuid() as uint })
878                             .gid(unsafe { libc::getgid() as uint })
879                             .spawn().unwrap();
880         assert!(p.wait().unwrap().success());
881     }
882
883     #[cfg(all(unix, not(target_os="android")))]
884     #[test]
885     fn uid_to_root_fails() {
886         use libc;
887
888         // if we're already root, this isn't a valid test. Most of the bots run
889         // as non-root though (android is an exception).
890         if unsafe { libc::getuid() == 0 } { return }
891         assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
892     }
893
894     #[cfg(not(target_os="android"))]
895     #[test]
896     fn test_process_status() {
897         let mut status = Command::new("false").status().unwrap();
898         assert!(status.matches_exit_status(1));
899
900         status = Command::new("true").status().unwrap();
901         assert!(status.success());
902     }
903
904     #[test]
905     fn test_process_output_fail_to_start() {
906         match Command::new("/no-binary-by-this-name-should-exist").output() {
907             Err(e) => assert_eq!(e.kind, FileNotFound),
908             Ok(..) => panic!()
909         }
910     }
911
912     #[cfg(not(target_os="android"))]
913     #[test]
914     fn test_process_output_output() {
915         let ProcessOutput {status, output, error}
916              = Command::new("echo").arg("hello").output().unwrap();
917         let output_str = str::from_utf8(output.as_slice()).unwrap();
918
919         assert!(status.success());
920         assert_eq!(output_str.trim().to_string(), "hello");
921         // FIXME #7224
922         if !running_on_valgrind() {
923             assert_eq!(error, Vec::new());
924         }
925     }
926
927     #[cfg(not(target_os="android"))]
928     #[test]
929     fn test_process_output_error() {
930         let ProcessOutput {status, output, error}
931              = Command::new("mkdir").arg(".").output().unwrap();
932
933         assert!(status.matches_exit_status(1));
934         assert_eq!(output, Vec::new());
935         assert!(!error.is_empty());
936     }
937
938     #[cfg(not(target_os="android"))]
939     #[test]
940     fn test_finish_once() {
941         let mut prog = Command::new("false").spawn().unwrap();
942         assert!(prog.wait().unwrap().matches_exit_status(1));
943     }
944
945     #[cfg(not(target_os="android"))]
946     #[test]
947     fn test_finish_twice() {
948         let mut prog = Command::new("false").spawn().unwrap();
949         assert!(prog.wait().unwrap().matches_exit_status(1));
950         assert!(prog.wait().unwrap().matches_exit_status(1));
951     }
952
953     #[cfg(not(target_os="android"))]
954     #[test]
955     fn test_wait_with_output_once() {
956         let prog = Command::new("echo").arg("hello").spawn().unwrap();
957         let ProcessOutput {status, output, error} = prog.wait_with_output().unwrap();
958         let output_str = str::from_utf8(output.as_slice()).unwrap();
959
960         assert!(status.success());
961         assert_eq!(output_str.trim().to_string(), "hello");
962         // FIXME #7224
963         if !running_on_valgrind() {
964             assert_eq!(error, Vec::new());
965         }
966     }
967
968     #[cfg(all(unix, not(target_os="android")))]
969     pub fn pwd_cmd() -> Command {
970         Command::new("pwd")
971     }
972     #[cfg(target_os="android")]
973     pub fn pwd_cmd() -> Command {
974         let mut cmd = Command::new("/system/bin/sh");
975         cmd.arg("-c").arg("pwd");
976         cmd
977     }
978
979     #[cfg(windows)]
980     pub fn pwd_cmd() -> Command {
981         let mut cmd = Command::new("cmd");
982         cmd.arg("/c").arg("cd");
983         cmd
984     }
985
986     #[test]
987     fn test_keep_current_working_dir() {
988         use os;
989         let prog = pwd_cmd().spawn().unwrap();
990
991         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
992         let parent_dir = os::getcwd().unwrap();
993         let child_dir = Path::new(output.trim());
994
995         let parent_stat = parent_dir.stat().unwrap();
996         let child_stat = child_dir.stat().unwrap();
997
998         assert_eq!(parent_stat.unstable.device, child_stat.unstable.device);
999         assert_eq!(parent_stat.unstable.inode, child_stat.unstable.inode);
1000     }
1001
1002     #[test]
1003     fn test_change_working_directory() {
1004         use os;
1005         // test changing to the parent of os::getcwd() because we know
1006         // the path exists (and os::getcwd() is not expected to be root)
1007         let parent_dir = os::getcwd().unwrap().dir_path();
1008         let prog = pwd_cmd().cwd(&parent_dir).spawn().unwrap();
1009
1010         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
1011         let child_dir = Path::new(output.trim());
1012
1013         let parent_stat = parent_dir.stat().unwrap();
1014         let child_stat = child_dir.stat().unwrap();
1015
1016         assert_eq!(parent_stat.unstable.device, child_stat.unstable.device);
1017         assert_eq!(parent_stat.unstable.inode, child_stat.unstable.inode);
1018     }
1019
1020     #[cfg(all(unix, not(target_os="android")))]
1021     pub fn env_cmd() -> Command {
1022         Command::new("env")
1023     }
1024     #[cfg(target_os="android")]
1025     pub fn env_cmd() -> Command {
1026         let mut cmd = Command::new("/system/bin/sh");
1027         cmd.arg("-c").arg("set");
1028         cmd
1029     }
1030
1031     #[cfg(windows)]
1032     pub fn env_cmd() -> Command {
1033         let mut cmd = Command::new("cmd");
1034         cmd.arg("/c").arg("set");
1035         cmd
1036     }
1037
1038     #[cfg(not(target_os="android"))]
1039     #[test]
1040     fn test_inherit_env() {
1041         use os;
1042         if running_on_valgrind() { return; }
1043
1044         let prog = env_cmd().spawn().unwrap();
1045         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
1046
1047         let r = os::env();
1048         for &(ref k, ref v) in r.iter() {
1049             // don't check windows magical empty-named variables
1050             assert!(k.is_empty() ||
1051                     output.contains(format!("{}={}", *k, *v).as_slice()),
1052                     "output doesn't contain `{}={}`\n{}",
1053                     k, v, output);
1054         }
1055     }
1056     #[cfg(target_os="android")]
1057     #[test]
1058     fn test_inherit_env() {
1059         use os;
1060         if running_on_valgrind() { return; }
1061
1062         let mut prog = env_cmd().spawn().unwrap();
1063         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
1064
1065         let r = os::env();
1066         for &(ref k, ref v) in r.iter() {
1067             // don't check android RANDOM variables
1068             if *k != "RANDOM".to_string() {
1069                 assert!(output.contains(format!("{}={}",
1070                                                 *k,
1071                                                 *v).as_slice()) ||
1072                         output.contains(format!("{}=\'{}\'",
1073                                                 *k,
1074                                                 *v).as_slice()));
1075             }
1076         }
1077     }
1078
1079     #[test]
1080     fn test_override_env() {
1081         use os;
1082         let mut new_env = vec![("RUN_TEST_NEW_ENV", "123")];
1083
1084         // In some build environments (such as chrooted Nix builds), `env` can
1085         // only be found in the explicitly-provided PATH env variable, not in
1086         // default places such as /bin or /usr/bin. So we need to pass through
1087         // PATH to our sub-process.
1088         let path_val: String;
1089         match os::getenv("PATH") {
1090             None => {}
1091             Some(val) => {
1092                 path_val = val;
1093                 new_env.push(("PATH", path_val.as_slice()))
1094             }
1095         }
1096
1097         let prog = env_cmd().env_set_all(new_env.as_slice()).spawn().unwrap();
1098         let result = prog.wait_with_output().unwrap();
1099         let output = String::from_utf8_lossy(result.output.as_slice()).to_string();
1100
1101         assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1102                 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1103     }
1104
1105     #[test]
1106     fn test_add_to_env() {
1107         let prog = env_cmd().env("RUN_TEST_NEW_ENV", "123").spawn().unwrap();
1108         let result = prog.wait_with_output().unwrap();
1109         let output = String::from_utf8_lossy(result.output.as_slice()).to_string();
1110
1111         assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1112                 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1113     }
1114
1115     #[cfg(unix)]
1116     pub fn sleeper() -> Process {
1117         Command::new("sleep").arg("1000").spawn().unwrap()
1118     }
1119     #[cfg(windows)]
1120     pub fn sleeper() -> Process {
1121         // There's a `timeout` command on windows, but it doesn't like having
1122         // its output piped, so instead just ping ourselves a few times with
1123         // gaps in between so we're sure this process is alive for awhile
1124         Command::new("ping").arg("127.0.0.1").arg("-n").arg("1000").spawn().unwrap()
1125     }
1126
1127     #[test]
1128     fn test_kill() {
1129         let mut p = sleeper();
1130         Process::kill(p.id(), PleaseExitSignal).unwrap();
1131         assert!(!p.wait().unwrap().success());
1132     }
1133
1134     #[test]
1135     fn test_exists() {
1136         let mut p = sleeper();
1137         assert!(Process::kill(p.id(), 0).is_ok());
1138         p.signal_kill().unwrap();
1139         assert!(!p.wait().unwrap().success());
1140     }
1141
1142     #[test]
1143     fn test_zero() {
1144         let mut p = sleeper();
1145         p.signal_kill().unwrap();
1146         for _ in range(0i, 20) {
1147             if p.signal(0).is_err() {
1148                 assert!(!p.wait().unwrap().success());
1149                 return
1150             }
1151             timer::sleep(Duration::milliseconds(100));
1152         }
1153         panic!("never saw the child go away");
1154     }
1155
1156     #[test]
1157     fn wait_timeout() {
1158         let mut p = sleeper();
1159         p.set_timeout(Some(10));
1160         assert_eq!(p.wait().err().unwrap().kind, TimedOut);
1161         assert_eq!(p.wait().err().unwrap().kind, TimedOut);
1162         p.signal_kill().unwrap();
1163         p.set_timeout(None);
1164         assert!(p.wait().is_ok());
1165     }
1166
1167     #[test]
1168     fn wait_timeout2() {
1169         let (tx, rx) = channel();
1170         let tx2 = tx.clone();
1171         let _t = Thread::spawn(move|| {
1172             let mut p = sleeper();
1173             p.set_timeout(Some(10));
1174             assert_eq!(p.wait().err().unwrap().kind, TimedOut);
1175             p.signal_kill().unwrap();
1176             tx.send(()).unwrap();
1177         });
1178         let _t = Thread::spawn(move|| {
1179             let mut p = sleeper();
1180             p.set_timeout(Some(10));
1181             assert_eq!(p.wait().err().unwrap().kind, TimedOut);
1182             p.signal_kill().unwrap();
1183             tx2.send(()).unwrap();
1184         });
1185         rx.recv().unwrap();
1186         rx.recv().unwrap();
1187     }
1188
1189     #[test]
1190     fn forget() {
1191         let p = sleeper();
1192         let id = p.id();
1193         p.forget();
1194         assert!(Process::kill(id, 0).is_ok());
1195         assert!(Process::kill(id, PleaseExitSignal).is_ok());
1196     }
1197
1198     #[test]
1199     fn dont_close_fd_on_command_spawn() {
1200         use sys::fs;
1201
1202         let path = if cfg!(windows) {
1203             Path::new("NUL")
1204         } else {
1205             Path::new("/dev/null")
1206         };
1207
1208         let fdes = match fs::open(&path, Truncate, Write) {
1209             Ok(f) => f,
1210             Err(_) => panic!("failed to open file descriptor"),
1211         };
1212
1213         let mut cmd = pwd_cmd();
1214         let _ = cmd.stdout(InheritFd(fdes.fd()));
1215         assert!(cmd.status().unwrap().success());
1216         assert!(fdes.write("extra write\n".as_bytes()).is_ok());
1217     }
1218
1219     #[test]
1220     #[cfg(windows)]
1221     fn env_map_keys_ci() {
1222         use ffi::CString;
1223         use super::EnvKey;
1224         let mut cmd = Command::new("");
1225         cmd.env("path", "foo");
1226         cmd.env("Path", "bar");
1227         let env = &cmd.env.unwrap();
1228         let val = env.get(&EnvKey(CString::from_slice(b"PATH")));
1229         assert!(val.unwrap() == &CString::from_slice(b"bar"));
1230     }
1231 }