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