]> git.proxmox.com Git - rustc.git/blame - src/libstd/process.rs
New upstream version 1.13.0+dfsg1
[rustc.git] / src / libstd / process.rs
CommitLineData
85aaf69f
SL
1// Copyright 2015 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//! Working with processes.
12
c34b1796 13#![stable(feature = "process", since = "1.0.0")]
85aaf69f 14
85aaf69f
SL
15use io::prelude::*;
16
c34b1796 17use ffi::OsStr;
85aaf69f 18use fmt;
7453a54e
SL
19use io;
20use path::Path;
9cc50fc6 21use str;
54a0048b 22use sys::pipe::{read2, AnonPipe};
62682a34 23use sys::process as imp;
c1a9b12d 24use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
85aaf69f
SL
25
26/// Representation of a running or exited child process.
27///
28/// This structure is used to represent and manage child processes. A child
5bcae85e
SL
29/// process is created via the [`Command`] struct, which configures the
30/// spawning process and can itself be constructed using a builder-style
31/// interface.
85aaf69f 32///
c34b1796 33/// # Examples
85aaf69f 34///
c34b1796 35/// ```should_panic
85aaf69f
SL
36/// use std::process::Command;
37///
bd371182
AL
38/// let mut child = Command::new("/bin/cat")
39/// .arg("file.txt")
40/// .spawn()
a7813a04 41/// .expect("failed to execute child");
bd371182
AL
42///
43/// let ecode = child.wait()
a7813a04 44/// .expect("failed to wait on child");
bd371182
AL
45///
46/// assert!(ecode.success());
85aaf69f 47/// ```
7453a54e
SL
48///
49/// # Note
50///
5bcae85e
SL
51/// Take note that there is no implementation of [`Drop`] for child processes,
52/// so if you do not ensure the `Child` has exited then it will continue to
53/// run, even after the `Child` handle to the child process has gone out of
54/// scope.
7453a54e 55///
5bcae85e
SL
56/// Calling [`wait`][`wait`] (or other functions that wrap around it) will make
57/// the parent process wait until the child has actually exited before
58/// continuing.
59///
60/// [`Command`]: struct.Command.html
61/// [`Drop`]: ../../core/ops/trait.Drop.html
62/// [`wait`]: #method.wait
c34b1796 63#[stable(feature = "process", since = "1.0.0")]
85aaf69f 64pub struct Child {
62682a34 65 handle: imp::Process,
85aaf69f 66
85aaf69f 67 /// The handle for writing to the child's stdin, if it has been captured
c34b1796 68 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
69 pub stdin: Option<ChildStdin>,
70
71 /// The handle for reading from the child's stdout, if it has been captured
c34b1796 72 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
73 pub stdout: Option<ChildStdout>,
74
75 /// The handle for reading from the child's stderr, if it has been captured
c34b1796 76 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
77 pub stderr: Option<ChildStderr>,
78}
79
62682a34
SL
80impl AsInner<imp::Process> for Child {
81 fn as_inner(&self) -> &imp::Process { &self.handle }
82}
83
7453a54e
SL
84impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
85 fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child {
86 Child {
87 handle: handle,
88 stdin: io.stdin.map(ChildStdin::from_inner),
89 stdout: io.stdout.map(ChildStdout::from_inner),
90 stderr: io.stderr.map(ChildStderr::from_inner),
91 }
92 }
93}
94
c1a9b12d
SL
95impl IntoInner<imp::Process> for Child {
96 fn into_inner(self) -> imp::Process { self.handle }
97}
98
5bcae85e
SL
99/// A handle to a child process's stdin. This struct is used in the [`stdin`]
100/// field on [`Child`].
101///
102/// [`Child`]: struct.Child.html
103/// [`stdin`]: struct.Child.html#structfield.stdin
c34b1796 104#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
105pub struct ChildStdin {
106 inner: AnonPipe
107}
108
c34b1796 109#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
110impl Write for ChildStdin {
111 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
112 self.inner.write(buf)
113 }
114
115 fn flush(&mut self) -> io::Result<()> {
116 Ok(())
117 }
118}
119
62682a34
SL
120impl AsInner<AnonPipe> for ChildStdin {
121 fn as_inner(&self) -> &AnonPipe { &self.inner }
122}
123
c1a9b12d
SL
124impl IntoInner<AnonPipe> for ChildStdin {
125 fn into_inner(self) -> AnonPipe { self.inner }
126}
127
7453a54e
SL
128impl FromInner<AnonPipe> for ChildStdin {
129 fn from_inner(pipe: AnonPipe) -> ChildStdin {
130 ChildStdin { inner: pipe }
131 }
132}
133
5bcae85e
SL
134/// A handle to a child process's stdout. This struct is used in the [`stdout`]
135/// field on [`Child`].
136///
137/// [`Child`]: struct.Child.html
138/// [`stdout`]: struct.Child.html#structfield.stdout
c34b1796 139#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
140pub struct ChildStdout {
141 inner: AnonPipe
142}
143
c34b1796 144#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
145impl Read for ChildStdout {
146 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
147 self.inner.read(buf)
148 }
54a0048b
SL
149 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
150 self.inner.read_to_end(buf)
151 }
85aaf69f
SL
152}
153
62682a34
SL
154impl AsInner<AnonPipe> for ChildStdout {
155 fn as_inner(&self) -> &AnonPipe { &self.inner }
156}
157
c1a9b12d
SL
158impl IntoInner<AnonPipe> for ChildStdout {
159 fn into_inner(self) -> AnonPipe { self.inner }
160}
161
7453a54e
SL
162impl FromInner<AnonPipe> for ChildStdout {
163 fn from_inner(pipe: AnonPipe) -> ChildStdout {
164 ChildStdout { inner: pipe }
165 }
166}
167
5bcae85e
SL
168/// A handle to a child process's stderr. This struct is used in the [`stderr`]
169/// field on [`Child`].
170///
171/// [`Child`]: struct.Child.html
172/// [`stderr`]: struct.Child.html#structfield.stderr
c34b1796 173#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
174pub struct ChildStderr {
175 inner: AnonPipe
176}
177
c34b1796 178#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
179impl Read for ChildStderr {
180 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
181 self.inner.read(buf)
182 }
54a0048b
SL
183 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
184 self.inner.read_to_end(buf)
185 }
85aaf69f
SL
186}
187
62682a34
SL
188impl AsInner<AnonPipe> for ChildStderr {
189 fn as_inner(&self) -> &AnonPipe { &self.inner }
190}
191
c1a9b12d
SL
192impl IntoInner<AnonPipe> for ChildStderr {
193 fn into_inner(self) -> AnonPipe { self.inner }
194}
195
7453a54e
SL
196impl FromInner<AnonPipe> for ChildStderr {
197 fn from_inner(pipe: AnonPipe) -> ChildStderr {
198 ChildStderr { inner: pipe }
199 }
200}
201
3157f602
XL
202/// A process builder, providing fine-grained control
203/// over how a new process should be spawned.
204///
205/// A default configuration can be
85aaf69f
SL
206/// generated using `Command::new(program)`, where `program` gives a path to the
207/// program to be executed. Additional builder methods allow the configuration
208/// to be changed (for example, by adding arguments) prior to spawning:
209///
210/// ```
85aaf69f
SL
211/// use std::process::Command;
212///
bd371182
AL
213/// let output = Command::new("sh")
214/// .arg("-c")
215/// .arg("echo hello")
216/// .output()
3157f602 217/// .expect("failed to execute process");
a7813a04 218///
85aaf69f
SL
219/// let hello = output.stdout;
220/// ```
c34b1796 221#[stable(feature = "process", since = "1.0.0")]
85aaf69f 222pub struct Command {
62682a34 223 inner: imp::Command,
85aaf69f
SL
224}
225
226impl Command {
227 /// Constructs a new `Command` for launching the program at
228 /// path `program`, with the following default configuration:
229 ///
230 /// * No arguments to the program
231 /// * Inherit the current process's environment
232 /// * Inherit the current process's working directory
bd371182 233 /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
85aaf69f
SL
234 ///
235 /// Builder methods are provided to change these defaults and
236 /// otherwise configure the process.
a7813a04
XL
237 ///
238 /// # Examples
239 ///
240 /// Basic usage:
241 ///
242 /// ```no_run
243 /// use std::process::Command;
244 ///
245 /// Command::new("sh")
246 /// .spawn()
247 /// .expect("sh command failed to start");
248 /// ```
c34b1796
AL
249 #[stable(feature = "process", since = "1.0.0")]
250 pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
7453a54e 251 Command { inner: imp::Command::new(program.as_ref()) }
85aaf69f
SL
252 }
253
254 /// Add an argument to pass to the program.
a7813a04
XL
255 ///
256 /// # Examples
257 ///
258 /// Basic usage:
259 ///
260 /// ```no_run
261 /// use std::process::Command;
262 ///
263 /// Command::new("ls")
264 /// .arg("-l")
265 /// .arg("-a")
266 /// .spawn()
267 /// .expect("ls command failed to start");
268 /// ```
c34b1796
AL
269 #[stable(feature = "process", since = "1.0.0")]
270 pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
271 self.inner.arg(arg.as_ref());
85aaf69f
SL
272 self
273 }
274
275 /// Add multiple arguments to pass to the program.
a7813a04
XL
276 ///
277 /// # Examples
278 ///
279 /// Basic usage:
280 ///
281 /// ```no_run
282 /// use std::process::Command;
283 ///
284 /// Command::new("ls")
285 /// .args(&["-l", "-a"])
286 /// .spawn()
287 /// .expect("ls command failed to start");
288 /// ```
c34b1796
AL
289 #[stable(feature = "process", since = "1.0.0")]
290 pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut Command {
7453a54e
SL
291 for arg in args {
292 self.arg(arg.as_ref());
293 }
85aaf69f
SL
294 self
295 }
296
297 /// Inserts or updates an environment variable mapping.
298 ///
299 /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
300 /// and case-sensitive on all other platforms.
a7813a04
XL
301 ///
302 /// # Examples
303 ///
304 /// Basic usage:
305 ///
306 /// ```no_run
307 /// use std::process::Command;
308 ///
309 /// Command::new("ls")
310 /// .env("PATH", "/bin")
311 /// .spawn()
312 /// .expect("ls command failed to start");
313 /// ```
c34b1796
AL
314 #[stable(feature = "process", since = "1.0.0")]
315 pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
316 where K: AsRef<OsStr>, V: AsRef<OsStr>
85aaf69f 317 {
c34b1796 318 self.inner.env(key.as_ref(), val.as_ref());
85aaf69f
SL
319 self
320 }
321
322 /// Removes an environment variable mapping.
a7813a04
XL
323 ///
324 /// # Examples
325 ///
326 /// Basic usage:
327 ///
328 /// ```no_run
329 /// use std::process::Command;
330 ///
331 /// Command::new("ls")
332 /// .env_remove("PATH")
333 /// .spawn()
334 /// .expect("ls command failed to start");
335 /// ```
c34b1796
AL
336 #[stable(feature = "process", since = "1.0.0")]
337 pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
338 self.inner.env_remove(key.as_ref());
85aaf69f
SL
339 self
340 }
341
342 /// Clears the entire environment map for the child process.
a7813a04
XL
343 ///
344 /// # Examples
345 ///
346 /// Basic usage:
347 ///
348 /// ```no_run
349 /// use std::process::Command;
350 ///
351 /// Command::new("ls")
352 /// .env_clear()
353 /// .spawn()
354 /// .expect("ls command failed to start");
355 /// ```
c34b1796 356 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
357 pub fn env_clear(&mut self) -> &mut Command {
358 self.inner.env_clear();
359 self
360 }
361
9346a6ac 362 /// Sets the working directory for the child process.
a7813a04
XL
363 ///
364 /// # Examples
365 ///
366 /// Basic usage:
367 ///
368 /// ```no_run
369 /// use std::process::Command;
370 ///
371 /// Command::new("ls")
372 /// .current_dir("/bin")
373 /// .spawn()
374 /// .expect("ls command failed to start");
375 /// ```
c34b1796 376 #[stable(feature = "process", since = "1.0.0")]
7453a54e 377 pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
c34b1796 378 self.inner.cwd(dir.as_ref().as_ref());
85aaf69f
SL
379 self
380 }
381
382 /// Configuration for the child process's stdin handle (file descriptor 0).
a7813a04
XL
383 ///
384 /// # Examples
385 ///
386 /// Basic usage:
387 ///
388 /// ```no_run
389 /// use std::process::{Command, Stdio};
390 ///
391 /// Command::new("ls")
392 /// .stdin(Stdio::null())
393 /// .spawn()
394 /// .expect("ls command failed to start");
395 /// ```
c34b1796 396 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 397 pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
7453a54e 398 self.inner.stdin(cfg.0);
85aaf69f
SL
399 self
400 }
401
402 /// Configuration for the child process's stdout handle (file descriptor 1).
a7813a04
XL
403 ///
404 /// # Examples
405 ///
406 /// Basic usage:
407 ///
408 /// ```no_run
409 /// use std::process::{Command, Stdio};
410 ///
411 /// Command::new("ls")
412 /// .stdout(Stdio::null())
413 /// .spawn()
414 /// .expect("ls command failed to start");
415 /// ```
c34b1796 416 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 417 pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
7453a54e 418 self.inner.stdout(cfg.0);
85aaf69f
SL
419 self
420 }
421
422 /// Configuration for the child process's stderr handle (file descriptor 2).
a7813a04
XL
423 ///
424 /// # Examples
425 ///
426 /// Basic usage:
427 ///
428 /// ```no_run
429 /// use std::process::{Command, Stdio};
430 ///
431 /// Command::new("ls")
432 /// .stderr(Stdio::null())
433 /// .spawn()
434 /// .expect("ls command failed to start");
435 /// ```
c34b1796 436 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 437 pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
7453a54e 438 self.inner.stderr(cfg.0);
85aaf69f
SL
439 self
440 }
441
85aaf69f
SL
442 /// Executes the command as a child process, returning a handle to it.
443 ///
62682a34 444 /// By default, stdin, stdout and stderr are inherited from the parent.
a7813a04
XL
445 ///
446 /// # Examples
447 ///
448 /// Basic usage:
449 ///
450 /// ```no_run
451 /// use std::process::Command;
452 ///
453 /// Command::new("ls")
454 /// .spawn()
455 /// .expect("ls command failed to start");
456 /// ```
c34b1796 457 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 458 pub fn spawn(&mut self) -> io::Result<Child> {
54a0048b 459 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
85aaf69f
SL
460 }
461
462 /// Executes the command as a child process, waiting for it to finish and
463 /// collecting all of its output.
464 ///
465 /// By default, stdin, stdout and stderr are captured (and used to
466 /// provide the resulting output).
467 ///
c34b1796 468 /// # Examples
85aaf69f 469 ///
a7813a04 470 /// ```should_panic
85aaf69f 471 /// use std::process::Command;
a7813a04
XL
472 /// let output = Command::new("/bin/cat")
473 /// .arg("file.txt")
474 /// .output()
475 /// .expect("failed to execute process");
85aaf69f
SL
476 ///
477 /// println!("status: {}", output.status);
c34b1796
AL
478 /// println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
479 /// println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
a7813a04
XL
480 ///
481 /// assert!(output.status.success());
85aaf69f 482 /// ```
c34b1796 483 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 484 pub fn output(&mut self) -> io::Result<Output> {
54a0048b 485 self.inner.spawn(imp::Stdio::MakePipe, false).map(Child::from_inner)
7453a54e 486 .and_then(|p| p.wait_with_output())
85aaf69f
SL
487 }
488
489 /// Executes a command as a child process, waiting for it to finish and
490 /// collecting its exit status.
491 ///
62682a34 492 /// By default, stdin, stdout and stderr are inherited from the parent.
85aaf69f 493 ///
c34b1796 494 /// # Examples
85aaf69f 495 ///
a7813a04 496 /// ```should_panic
85aaf69f
SL
497 /// use std::process::Command;
498 ///
a7813a04
XL
499 /// let status = Command::new("/bin/cat")
500 /// .arg("file.txt")
501 /// .status()
502 /// .expect("failed to execute process");
85aaf69f
SL
503 ///
504 /// println!("process exited with: {}", status);
a7813a04
XL
505 ///
506 /// assert!(status.success());
85aaf69f 507 /// ```
c34b1796 508 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 509 pub fn status(&mut self) -> io::Result<ExitStatus> {
54a0048b
SL
510 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
511 .and_then(|mut p| p.wait())
85aaf69f
SL
512 }
513}
514
515#[stable(feature = "rust1", since = "1.0.0")]
516impl fmt::Debug for Command {
517 /// Format the program and arguments of a Command for display. Any
518 /// non-utf8 data is lossily converted using the utf8 replacement
519 /// character.
520 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7453a54e 521 self.inner.fmt(f)
85aaf69f
SL
522 }
523}
524
62682a34
SL
525impl AsInner<imp::Command> for Command {
526 fn as_inner(&self) -> &imp::Command { &self.inner }
85aaf69f
SL
527}
528
62682a34
SL
529impl AsInnerMut<imp::Command> for Command {
530 fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner }
85aaf69f
SL
531}
532
85aaf69f
SL
533/// The output of a finished process.
534#[derive(PartialEq, Eq, Clone)]
c34b1796 535#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
536pub struct Output {
537 /// The status (exit code) of the process.
c34b1796 538 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
539 pub status: ExitStatus,
540 /// The data that the process wrote to stdout.
c34b1796 541 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
542 pub stdout: Vec<u8>,
543 /// The data that the process wrote to stderr.
c34b1796 544 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
545 pub stderr: Vec<u8>,
546}
547
9cc50fc6
SL
548// If either stderr or stdout are valid utf8 strings it prints the valid
549// strings, otherwise it prints the byte sequence instead
550#[stable(feature = "process_output_debug", since = "1.7.0")]
551impl fmt::Debug for Output {
552 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
553
554 let stdout_utf8 = str::from_utf8(&self.stdout);
555 let stdout_debug: &fmt::Debug = match stdout_utf8 {
556 Ok(ref str) => str,
557 Err(_) => &self.stdout
558 };
559
560 let stderr_utf8 = str::from_utf8(&self.stderr);
561 let stderr_debug: &fmt::Debug = match stderr_utf8 {
562 Ok(ref str) => str,
563 Err(_) => &self.stderr
564 };
565
566 fmt.debug_struct("Output")
567 .field("status", &self.status)
568 .field("stdout", stdout_debug)
569 .field("stderr", stderr_debug)
570 .finish()
571 }
572}
573
bd371182 574/// Describes what to do with a standard I/O stream for a child process.
c34b1796 575#[stable(feature = "process", since = "1.0.0")]
7453a54e 576pub struct Stdio(imp::Stdio);
85aaf69f
SL
577
578impl Stdio {
579 /// A new pipe should be arranged to connect the parent and child processes.
c34b1796 580 #[stable(feature = "process", since = "1.0.0")]
7453a54e 581 pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) }
85aaf69f
SL
582
583 /// The child inherits from the corresponding parent descriptor.
c34b1796 584 #[stable(feature = "process", since = "1.0.0")]
7453a54e 585 pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) }
85aaf69f
SL
586
587 /// This stream will be ignored. This is the equivalent of attaching the
588 /// stream to `/dev/null`
c34b1796 589 #[stable(feature = "process", since = "1.0.0")]
7453a54e 590 pub fn null() -> Stdio { Stdio(imp::Stdio::Null) }
62682a34
SL
591}
592
7453a54e
SL
593impl FromInner<imp::Stdio> for Stdio {
594 fn from_inner(inner: imp::Stdio) -> Stdio {
595 Stdio(inner)
62682a34 596 }
85aaf69f
SL
597}
598
599/// Describes the result of a process after it has terminated.
600#[derive(PartialEq, Eq, Clone, Copy, Debug)]
c34b1796 601#[stable(feature = "process", since = "1.0.0")]
62682a34 602pub struct ExitStatus(imp::ExitStatus);
85aaf69f
SL
603
604impl ExitStatus {
605 /// Was termination successful? Signal termination not considered a success,
606 /// and success is defined as a zero exit status.
5bcae85e
SL
607 ///
608 /// # Examples
609 ///
610 /// ```rust,no_run
611 /// use std::process::Command;
612 ///
613 /// let status = Command::new("mkdir")
614 /// .arg("projects")
615 /// .status()
616 /// .expect("failed to execute mkdir");
617 ///
618 /// if status.success() {
619 /// println!("'projects/' directory created");
620 /// } else {
621 /// println!("failed to create 'projects/' directory");
622 /// }
623 /// ```
c34b1796 624 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
625 pub fn success(&self) -> bool {
626 self.0.success()
627 }
628
9346a6ac 629 /// Returns the exit code of the process, if any.
85aaf69f
SL
630 ///
631 /// On Unix, this will return `None` if the process was terminated
632 /// by a signal; `std::os::unix` provides an extension trait for
633 /// extracting the signal and other details from the `ExitStatus`.
c34b1796 634 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
635 pub fn code(&self) -> Option<i32> {
636 self.0.code()
637 }
638}
639
62682a34
SL
640impl AsInner<imp::ExitStatus> for ExitStatus {
641 fn as_inner(&self) -> &imp::ExitStatus { &self.0 }
85aaf69f
SL
642}
643
a7813a04
XL
644impl FromInner<imp::ExitStatus> for ExitStatus {
645 fn from_inner(s: imp::ExitStatus) -> ExitStatus {
646 ExitStatus(s)
647 }
648}
649
c34b1796 650#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
651impl fmt::Display for ExitStatus {
652 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
653 self.0.fmt(f)
654 }
655}
656
657impl Child {
658 /// Forces the child to exit. This is equivalent to sending a
659 /// SIGKILL on unix platforms.
a7813a04
XL
660 ///
661 /// # Examples
662 ///
663 /// Basic usage:
664 ///
665 /// ```no_run
666 /// use std::process::Command;
667 ///
668 /// let mut command = Command::new("yes");
669 /// if let Ok(mut child) = command.spawn() {
670 /// child.kill().expect("command wasn't running");
671 /// } else {
672 /// println!("yes command didn't start");
673 /// }
674 /// ```
c34b1796 675 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 676 pub fn kill(&mut self) -> io::Result<()> {
7453a54e 677 self.handle.kill()
85aaf69f
SL
678 }
679
62682a34 680 /// Returns the OS-assigned process identifier associated with this child.
a7813a04
XL
681 ///
682 /// # Examples
683 ///
684 /// Basic usage:
685 ///
686 /// ```no_run
687 /// use std::process::Command;
688 ///
689 /// let mut command = Command::new("ls");
690 /// if let Ok(child) = command.spawn() {
691 /// println!("Child's id is {}", child.id());
692 /// } else {
693 /// println!("ls command didn't start");
694 /// }
695 /// ```
c1a9b12d 696 #[stable(feature = "process_id", since = "1.3.0")]
62682a34
SL
697 pub fn id(&self) -> u32 {
698 self.handle.id()
699 }
700
9346a6ac 701 /// Waits for the child to exit completely, returning the status that it
85aaf69f
SL
702 /// exited with. This function will continue to have the same return value
703 /// after it has been called at least once.
704 ///
705 /// The stdin handle to the child process, if any, will be closed
706 /// before waiting. This helps avoid deadlock: it ensures that the
707 /// child does not block waiting for input from the parent, while
708 /// the parent waits for the child to exit.
a7813a04
XL
709 ///
710 /// # Examples
711 ///
712 /// Basic usage:
713 ///
714 /// ```no_run
715 /// use std::process::Command;
716 ///
717 /// let mut command = Command::new("ls");
718 /// if let Ok(mut child) = command.spawn() {
719 /// child.wait().expect("command wasn't running");
720 /// println!("Child has finished its execution!");
721 /// } else {
722 /// println!("ls command didn't start");
723 /// }
724 /// ```
c34b1796 725 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
726 pub fn wait(&mut self) -> io::Result<ExitStatus> {
727 drop(self.stdin.take());
7453a54e 728 self.handle.wait().map(ExitStatus)
85aaf69f
SL
729 }
730
9346a6ac 731 /// Simultaneously waits for the child to exit and collect all remaining
92a42be0 732 /// output on the stdout/stderr handles, returning an `Output`
85aaf69f
SL
733 /// instance.
734 ///
735 /// The stdin handle to the child process, if any, will be closed
736 /// before waiting. This helps avoid deadlock: it ensures that the
737 /// child does not block waiting for input from the parent, while
738 /// the parent waits for the child to exit.
a7813a04
XL
739 ///
740 /// By default, stdin, stdout and stderr are inherited from the parent.
741 /// In order to capture the output into this `Result<Output>` it is
742 /// necessary to create new pipes between parent and child. Use
743 /// `stdout(Stdio::piped())` or `stderr(Stdio::piped())`, respectively.
744 ///
745 /// # Examples
746 ///
747 /// ```should_panic
748 /// use std::process::{Command, Stdio};
749 ///
3157f602
XL
750 /// let child = Command::new("/bin/cat")
751 /// .arg("file.txt")
752 /// .stdout(Stdio::piped())
753 /// .spawn()
754 /// .expect("failed to execute child");
a7813a04 755 ///
3157f602
XL
756 /// let output = child
757 /// .wait_with_output()
758 /// .expect("failed to wait on child");
a7813a04 759 ///
3157f602 760 /// assert!(output.status.success());
a7813a04
XL
761 /// ```
762 ///
c34b1796 763 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
764 pub fn wait_with_output(mut self) -> io::Result<Output> {
765 drop(self.stdin.take());
54a0048b
SL
766
767 let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
768 match (self.stdout.take(), self.stderr.take()) {
769 (None, None) => {}
770 (Some(mut out), None) => {
771 let res = out.read_to_end(&mut stdout);
772 res.unwrap();
773 }
774 (None, Some(mut err)) => {
775 let res = err.read_to_end(&mut stderr);
776 res.unwrap();
777 }
778 (Some(out), Some(err)) => {
779 let res = read2(out.inner, &mut stdout, err.inner, &mut stderr);
780 res.unwrap();
781 }
85aaf69f 782 }
85aaf69f 783
54a0048b 784 let status = self.wait()?;
85aaf69f
SL
785 Ok(Output {
786 status: status,
54a0048b
SL
787 stdout: stdout,
788 stderr: stderr,
85aaf69f
SL
789 })
790 }
791}
792
c34b1796
AL
793/// Terminates the current process with the specified exit code.
794///
795/// This function will never return and will immediately terminate the current
796/// process. The exit code is passed through to the underlying OS and will be
797/// available for consumption by another process.
798///
799/// Note that because this function never returns, and that it terminates the
800/// process, no destructors on the current stack or any other thread's stack
801/// will be run. If a clean shutdown is needed it is recommended to only call
802/// this function at a known point where there are no more destructors left
803/// to run.
804#[stable(feature = "rust1", since = "1.0.0")]
805pub fn exit(code: i32) -> ! {
e9174d1e 806 ::sys_common::cleanup();
c34b1796
AL
807 ::sys::os::exit(code)
808}
809
85aaf69f
SL
810#[cfg(test)]
811mod tests {
85aaf69f 812 use io::prelude::*;
c34b1796
AL
813
814 use io::ErrorKind;
85aaf69f 815 use str;
c34b1796 816 use super::{Command, Output, Stdio};
85aaf69f
SL
817
818 // FIXME(#10380) these tests should not all be ignored on android.
819
85aaf69f 820 #[test]
7453a54e 821 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
822 fn smoke() {
823 let p = Command::new("true").spawn();
824 assert!(p.is_ok());
825 let mut p = p.unwrap();
826 assert!(p.wait().unwrap().success());
827 }
828
85aaf69f 829 #[test]
7453a54e 830 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
831 fn smoke_failure() {
832 match Command::new("if-this-is-a-binary-then-the-world-has-ended").spawn() {
833 Ok(..) => panic!(),
834 Err(..) => {}
835 }
836 }
837
85aaf69f 838 #[test]
7453a54e 839 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
840 fn exit_reported_right() {
841 let p = Command::new("false").spawn();
842 assert!(p.is_ok());
843 let mut p = p.unwrap();
844 assert!(p.wait().unwrap().code() == Some(1));
c34b1796 845 drop(p.wait());
85aaf69f
SL
846 }
847
85aaf69f 848 #[test]
7453a54e
SL
849 #[cfg(unix)]
850 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 851 fn signal_reported_right() {
c34b1796 852 use os::unix::process::ExitStatusExt;
85aaf69f 853
b039eaaf
SL
854 let mut p = Command::new("/bin/sh")
855 .arg("-c").arg("read a")
856 .stdin(Stdio::piped())
857 .spawn().unwrap();
858 p.kill().unwrap();
85aaf69f
SL
859 match p.wait().unwrap().signal() {
860 Some(9) => {},
b039eaaf
SL
861 result => panic!("not terminated by signal 9 (instead, {:?})",
862 result),
85aaf69f
SL
863 }
864 }
865
866 pub fn run_output(mut cmd: Command) -> String {
867 let p = cmd.spawn();
868 assert!(p.is_ok());
869 let mut p = p.unwrap();
870 assert!(p.stdout.is_some());
871 let mut ret = String::new();
872 p.stdout.as_mut().unwrap().read_to_string(&mut ret).unwrap();
873 assert!(p.wait().unwrap().success());
874 return ret;
875 }
876
85aaf69f 877 #[test]
7453a54e 878 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
879 fn stdout_works() {
880 let mut cmd = Command::new("echo");
c34b1796 881 cmd.arg("foobar").stdout(Stdio::piped());
85aaf69f
SL
882 assert_eq!(run_output(cmd), "foobar\n");
883 }
884
85aaf69f 885 #[test]
7453a54e 886 #[cfg_attr(any(windows, target_os = "android"), ignore)]
85aaf69f
SL
887 fn set_current_dir_works() {
888 let mut cmd = Command::new("/bin/sh");
889 cmd.arg("-c").arg("pwd")
890 .current_dir("/")
c34b1796 891 .stdout(Stdio::piped());
85aaf69f
SL
892 assert_eq!(run_output(cmd), "/\n");
893 }
894
85aaf69f 895 #[test]
7453a54e 896 #[cfg_attr(any(windows, target_os = "android"), ignore)]
85aaf69f
SL
897 fn stdin_works() {
898 let mut p = Command::new("/bin/sh")
899 .arg("-c").arg("read line; echo $line")
c34b1796
AL
900 .stdin(Stdio::piped())
901 .stdout(Stdio::piped())
85aaf69f
SL
902 .spawn().unwrap();
903 p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap();
904 drop(p.stdin.take());
905 let mut out = String::new();
906 p.stdout.as_mut().unwrap().read_to_string(&mut out).unwrap();
907 assert!(p.wait().unwrap().success());
908 assert_eq!(out, "foobar\n");
909 }
910
911
85aaf69f 912 #[test]
7453a54e
SL
913 #[cfg_attr(target_os = "android", ignore)]
914 #[cfg(unix)]
85aaf69f 915 fn uid_works() {
c34b1796 916 use os::unix::prelude::*;
85aaf69f
SL
917 use libc;
918 let mut p = Command::new("/bin/sh")
919 .arg("-c").arg("true")
920 .uid(unsafe { libc::getuid() })
921 .gid(unsafe { libc::getgid() })
922 .spawn().unwrap();
923 assert!(p.wait().unwrap().success());
924 }
925
85aaf69f 926 #[test]
7453a54e
SL
927 #[cfg_attr(target_os = "android", ignore)]
928 #[cfg(unix)]
85aaf69f 929 fn uid_to_root_fails() {
c34b1796 930 use os::unix::prelude::*;
85aaf69f
SL
931 use libc;
932
933 // if we're already root, this isn't a valid test. Most of the bots run
934 // as non-root though (android is an exception).
935 if unsafe { libc::getuid() == 0 } { return }
936 assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
937 }
938
85aaf69f 939 #[test]
7453a54e 940 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
941 fn test_process_status() {
942 let mut status = Command::new("false").status().unwrap();
943 assert!(status.code() == Some(1));
944
945 status = Command::new("true").status().unwrap();
946 assert!(status.success());
947 }
948
949 #[test]
950 fn test_process_output_fail_to_start() {
951 match Command::new("/no-binary-by-this-name-should-exist").output() {
c34b1796 952 Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
85aaf69f
SL
953 Ok(..) => panic!()
954 }
955 }
956
85aaf69f 957 #[test]
7453a54e 958 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
959 fn test_process_output_output() {
960 let Output {status, stdout, stderr}
961 = Command::new("echo").arg("hello").output().unwrap();
c34b1796 962 let output_str = str::from_utf8(&stdout).unwrap();
85aaf69f
SL
963
964 assert!(status.success());
965 assert_eq!(output_str.trim().to_string(), "hello");
c1a9b12d 966 assert_eq!(stderr, Vec::new());
85aaf69f
SL
967 }
968
85aaf69f 969 #[test]
7453a54e 970 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
971 fn test_process_output_error() {
972 let Output {status, stdout, stderr}
973 = Command::new("mkdir").arg(".").output().unwrap();
974
975 assert!(status.code() == Some(1));
976 assert_eq!(stdout, Vec::new());
977 assert!(!stderr.is_empty());
978 }
979
85aaf69f 980 #[test]
7453a54e 981 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
982 fn test_finish_once() {
983 let mut prog = Command::new("false").spawn().unwrap();
984 assert!(prog.wait().unwrap().code() == Some(1));
985 }
986
85aaf69f 987 #[test]
7453a54e 988 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
989 fn test_finish_twice() {
990 let mut prog = Command::new("false").spawn().unwrap();
991 assert!(prog.wait().unwrap().code() == Some(1));
992 assert!(prog.wait().unwrap().code() == Some(1));
993 }
994
85aaf69f 995 #[test]
7453a54e 996 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 997 fn test_wait_with_output_once() {
c34b1796 998 let prog = Command::new("echo").arg("hello").stdout(Stdio::piped())
85aaf69f
SL
999 .spawn().unwrap();
1000 let Output {status, stdout, stderr} = prog.wait_with_output().unwrap();
c34b1796 1001 let output_str = str::from_utf8(&stdout).unwrap();
85aaf69f
SL
1002
1003 assert!(status.success());
1004 assert_eq!(output_str.trim().to_string(), "hello");
c1a9b12d 1005 assert_eq!(stderr, Vec::new());
85aaf69f
SL
1006 }
1007
85aaf69f
SL
1008 #[cfg(all(unix, not(target_os="android")))]
1009 pub fn env_cmd() -> Command {
1010 Command::new("env")
1011 }
1012 #[cfg(target_os="android")]
1013 pub fn env_cmd() -> Command {
1014 let mut cmd = Command::new("/system/bin/sh");
1015 cmd.arg("-c").arg("set");
1016 cmd
1017 }
1018
1019 #[cfg(windows)]
1020 pub fn env_cmd() -> Command {
1021 let mut cmd = Command::new("cmd");
1022 cmd.arg("/c").arg("set");
1023 cmd
1024 }
1025
85aaf69f
SL
1026 #[test]
1027 fn test_inherit_env() {
c1a9b12d 1028 use env;
85aaf69f
SL
1029
1030 let result = env_cmd().output().unwrap();
1031 let output = String::from_utf8(result.stdout).unwrap();
1032
c34b1796 1033 for (ref k, ref v) in env::vars() {
7453a54e
SL
1034 // don't check android RANDOM variables
1035 if cfg!(target_os = "android") && *k == "RANDOM" {
1036 continue
1037 }
1038
92a42be0
SL
1039 // Windows has hidden environment variables whose names start with
1040 // equals signs (`=`). Those do not show up in the output of the
1041 // `set` command.
1042 assert!((cfg!(windows) && k.starts_with("=")) ||
1043 k.starts_with("DYLD") ||
7453a54e
SL
1044 output.contains(&format!("{}={}", *k, *v)) ||
1045 output.contains(&format!("{}='{}'", *k, *v)),
85aaf69f
SL
1046 "output doesn't contain `{}={}`\n{}",
1047 k, v, output);
1048 }
1049 }
85aaf69f
SL
1050
1051 #[test]
1052 fn test_override_env() {
1053 use env;
1054
1055 // In some build environments (such as chrooted Nix builds), `env` can
1056 // only be found in the explicitly-provided PATH env variable, not in
1057 // default places such as /bin or /usr/bin. So we need to pass through
1058 // PATH to our sub-process.
1059 let mut cmd = env_cmd();
1060 cmd.env_clear().env("RUN_TEST_NEW_ENV", "123");
1061 if let Some(p) = env::var_os("PATH") {
1062 cmd.env("PATH", &p);
1063 }
1064 let result = cmd.output().unwrap();
c34b1796 1065 let output = String::from_utf8_lossy(&result.stdout).to_string();
85aaf69f
SL
1066
1067 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1068 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1069 }
1070
1071 #[test]
1072 fn test_add_to_env() {
1073 let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
c34b1796 1074 let output = String::from_utf8_lossy(&result.stdout).to_string();
85aaf69f
SL
1075
1076 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1077 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1078 }
7453a54e
SL
1079
1080 // Regression tests for #30858.
1081 #[test]
1082 fn test_interior_nul_in_progname_is_error() {
1083 match Command::new("has-some-\0\0s-inside").spawn() {
1084 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1085 Ok(_) => panic!(),
1086 }
1087 }
1088
1089 #[test]
1090 fn test_interior_nul_in_arg_is_error() {
1091 match Command::new("echo").arg("has-some-\0\0s-inside").spawn() {
1092 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1093 Ok(_) => panic!(),
1094 }
1095 }
1096
1097 #[test]
1098 fn test_interior_nul_in_args_is_error() {
1099 match Command::new("echo").args(&["has-some-\0\0s-inside"]).spawn() {
1100 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1101 Ok(_) => panic!(),
1102 }
1103 }
1104
1105 #[test]
1106 fn test_interior_nul_in_current_dir_is_error() {
1107 match Command::new("echo").current_dir("has-some-\0\0s-inside").spawn() {
1108 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1109 Ok(_) => panic!(),
1110 }
1111 }
1112
1113 // Regression tests for #30862.
1114 #[test]
1115 fn test_interior_nul_in_env_key_is_error() {
1116 match env_cmd().env("has-some-\0\0s-inside", "value").spawn() {
1117 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1118 Ok(_) => panic!(),
1119 }
1120 }
1121
1122 #[test]
1123 fn test_interior_nul_in_env_value_is_error() {
1124 match env_cmd().env("key", "has-some-\0\0s-inside").spawn() {
1125 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1126 Ok(_) => panic!(),
1127 }
1128 }
85aaf69f 1129}