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