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