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