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