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