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