]> git.proxmox.com Git - rustc.git/blame - src/libstd/process.rs
New upstream version 1.30.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
c30ab7b3
SL
11//! A module for working with processes.
12//!
abe05a73
XL
13//! This module is mostly concerned with spawning and interacting with child
14//! processes, but it also provides [`abort`] and [`exit`] for terminating the
15//! current process.
c30ab7b3 16//!
abe05a73 17//! # Spawning a process
c30ab7b3 18//!
abe05a73
XL
19//! The [`Command`] struct is used to configure and spawn processes:
20//!
21//! ```
c30ab7b3
SL
22//! use std::process::Command;
23//!
abe05a73
XL
24//! let output = Command::new("echo")
25//! .arg("Hello world")
26//! .output()
27//! .expect("Failed to execute command");
28//!
29//! assert_eq!(b"Hello world\n", output.stdout.as_slice());
30//! ```
31//!
32//! Several methods on [`Command`], such as [`spawn`] or [`output`], can be used
33//! to spawn a process. In particular, [`output`] spawns the child process and
34//! waits until the process terminates, while [`spawn`] will return a [`Child`]
35//! that represents the spawned child process.
36//!
37//! # Handling I/O
38//!
39//! The [`stdout`], [`stdin`], and [`stderr`] of a child process can be
40//! configured by passing an [`Stdio`] to the corresponding method on
41//! [`Command`]. Once spawned, they can be accessed from the [`Child`]. For
42//! example, piping output from one command into another command can be done
43//! like so:
44//!
45//! ```no_run
46//! use std::process::{Command, Stdio};
47//!
48//! // stdout must be configured with `Stdio::piped` in order to use
49//! // `echo_child.stdout`
50//! let echo_child = Command::new("echo")
51//! .arg("Oh no, a tpyo!")
52//! .stdout(Stdio::piped())
53//! .spawn()
54//! .expect("Failed to start echo process");
55//!
56//! // Note that `echo_child` is moved here, but we won't be needing
57//! // `echo_child` anymore
58//! let echo_out = echo_child.stdout.expect("Failed to open echo stdout");
c30ab7b3 59//!
abe05a73
XL
60//! let mut sed_child = Command::new("sed")
61//! .arg("s/tpyo/typo/")
62//! .stdin(Stdio::from(echo_out))
63//! .stdout(Stdio::piped())
64//! .spawn()
65//! .expect("Failed to start sed process");
c30ab7b3 66//!
abe05a73
XL
67//! let output = sed_child.wait_with_output().expect("Failed to wait on sed");
68//! assert_eq!(b"Oh no, a typo!\n", output.stdout.as_slice());
c30ab7b3 69//! ```
8bb4bdeb 70//!
2c00a5a8
XL
71//! Note that [`ChildStderr`] and [`ChildStdout`] implement [`Read`] and
72//! [`ChildStdin`] implements [`Write`]:
8bb4bdeb
XL
73//!
74//! ```no_run
75//! use std::process::{Command, Stdio};
76//! use std::io::Write;
77//!
78//! let mut child = Command::new("/bin/cat")
79//! .stdin(Stdio::piped())
80//! .stdout(Stdio::piped())
81//! .spawn()
82//! .expect("failed to execute child");
83//!
84//! {
85//! // limited borrow of stdin
86//! let stdin = child.stdin.as_mut().expect("failed to get stdin");
87//! stdin.write_all(b"test").expect("failed to write to stdin");
88//! }
89//!
90//! let output = child
91//! .wait_with_output()
92//! .expect("failed to wait on child");
93//!
94//! assert_eq!(b"test", output.stdout.as_slice());
95//! ```
abe05a73
XL
96//!
97//! [`abort`]: fn.abort.html
98//! [`exit`]: fn.exit.html
99//!
100//! [`Command`]: struct.Command.html
101//! [`spawn`]: struct.Command.html#method.spawn
102//! [`output`]: struct.Command.html#method.output
103//!
104//! [`Child`]: struct.Child.html
105//! [`ChildStdin`]: struct.ChildStdin.html
106//! [`ChildStdout`]: struct.ChildStdout.html
107//! [`ChildStderr`]: struct.ChildStderr.html
108//! [`Stdio`]: struct.Stdio.html
109//!
110//! [`stdout`]: struct.Command.html#method.stdout
111//! [`stdin`]: struct.Command.html#method.stdin
112//! [`stderr`]: struct.Command.html#method.stderr
113//!
114//! [`Write`]: ../io/trait.Write.html
115//! [`Read`]: ../io/trait.Read.html
85aaf69f 116
c34b1796 117#![stable(feature = "process", since = "1.0.0")]
85aaf69f 118
85aaf69f
SL
119use io::prelude::*;
120
c34b1796 121use ffi::OsStr;
85aaf69f 122use fmt;
041b39d2
XL
123use fs;
124use io::{self, Initializer};
7453a54e 125use path::Path;
9cc50fc6 126use str;
54a0048b 127use sys::pipe::{read2, AnonPipe};
62682a34 128use sys::process as imp;
c1a9b12d 129use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
85aaf69f
SL
130
131/// Representation of a running or exited child process.
132///
133/// This structure is used to represent and manage child processes. A child
5bcae85e
SL
134/// process is created via the [`Command`] struct, which configures the
135/// spawning process and can itself be constructed using a builder-style
136/// interface.
85aaf69f 137///
cc61c64b
XL
138/// There is no implementation of [`Drop`] for child processes,
139/// so if you do not ensure the `Child` has exited then it will continue to
140/// run, even after the `Child` handle to the child process has gone out of
141/// scope.
142///
143/// Calling [`wait`](#method.wait) (or other functions that wrap around it) will make
144/// the parent process wait until the child has actually exited before
145/// continuing.
146///
c34b1796 147/// # Examples
85aaf69f 148///
c34b1796 149/// ```should_panic
85aaf69f
SL
150/// use std::process::Command;
151///
bd371182
AL
152/// let mut child = Command::new("/bin/cat")
153/// .arg("file.txt")
154/// .spawn()
a7813a04 155/// .expect("failed to execute child");
bd371182
AL
156///
157/// let ecode = child.wait()
a7813a04 158/// .expect("failed to wait on child");
bd371182
AL
159///
160/// assert!(ecode.success());
85aaf69f 161/// ```
7453a54e 162///
5bcae85e
SL
163/// [`Command`]: struct.Command.html
164/// [`Drop`]: ../../core/ops/trait.Drop.html
165/// [`wait`]: #method.wait
c34b1796 166#[stable(feature = "process", since = "1.0.0")]
85aaf69f 167pub struct Child {
62682a34 168 handle: imp::Process,
85aaf69f 169
ea8adc8c
XL
170 /// The handle for writing to the child's standard input (stdin), if it has
171 /// been captured.
c34b1796 172 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
173 pub stdin: Option<ChildStdin>,
174
ea8adc8c
XL
175 /// The handle for reading from the child's standard output (stdout), if it
176 /// has been captured.
c34b1796 177 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
178 pub stdout: Option<ChildStdout>,
179
ea8adc8c
XL
180 /// The handle for reading from the child's standard error (stderr), if it
181 /// has been captured.
c34b1796 182 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
183 pub stderr: Option<ChildStderr>,
184}
185
62682a34
SL
186impl AsInner<imp::Process> for Child {
187 fn as_inner(&self) -> &imp::Process { &self.handle }
188}
189
7453a54e
SL
190impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
191 fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child {
192 Child {
3b2f2976 193 handle,
7453a54e
SL
194 stdin: io.stdin.map(ChildStdin::from_inner),
195 stdout: io.stdout.map(ChildStdout::from_inner),
196 stderr: io.stderr.map(ChildStderr::from_inner),
197 }
198 }
199}
200
c1a9b12d
SL
201impl IntoInner<imp::Process> for Child {
202 fn into_inner(self) -> imp::Process { self.handle }
203}
204
8bb4bdeb 205#[stable(feature = "std_debug", since = "1.16.0")]
32a655c1
SL
206impl fmt::Debug for Child {
207 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
208 f.debug_struct("Child")
209 .field("stdin", &self.stdin)
210 .field("stdout", &self.stdout)
211 .field("stderr", &self.stderr)
212 .finish()
213 }
214}
215
ea8adc8c 216/// A handle to a child process's standard input (stdin).
7cac9316
XL
217///
218/// This struct is used in the [`stdin`] field on [`Child`].
5bcae85e 219///
ea8adc8c
XL
220/// When an instance of `ChildStdin` is [dropped], the `ChildStdin`'s underlying
221/// file handle will be closed. If the child process was blocked on input prior
222/// to being dropped, it will become unblocked after dropping.
223///
5bcae85e
SL
224/// [`Child`]: struct.Child.html
225/// [`stdin`]: struct.Child.html#structfield.stdin
ea8adc8c 226/// [dropped]: ../ops/trait.Drop.html
c34b1796 227#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
228pub struct ChildStdin {
229 inner: AnonPipe
230}
231
c34b1796 232#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
233impl Write for ChildStdin {
234 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
235 self.inner.write(buf)
236 }
237
238 fn flush(&mut self) -> io::Result<()> {
239 Ok(())
240 }
241}
242
62682a34
SL
243impl AsInner<AnonPipe> for ChildStdin {
244 fn as_inner(&self) -> &AnonPipe { &self.inner }
245}
246
c1a9b12d
SL
247impl IntoInner<AnonPipe> for ChildStdin {
248 fn into_inner(self) -> AnonPipe { self.inner }
249}
250
7453a54e
SL
251impl FromInner<AnonPipe> for ChildStdin {
252 fn from_inner(pipe: AnonPipe) -> ChildStdin {
253 ChildStdin { inner: pipe }
254 }
255}
256
8bb4bdeb 257#[stable(feature = "std_debug", since = "1.16.0")]
32a655c1
SL
258impl fmt::Debug for ChildStdin {
259 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
260 f.pad("ChildStdin { .. }")
261 }
262}
263
ea8adc8c 264/// A handle to a child process's standard output (stdout).
7cac9316
XL
265///
266/// This struct is used in the [`stdout`] field on [`Child`].
5bcae85e 267///
ea8adc8c
XL
268/// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s
269/// underlying file handle will be closed.
270///
5bcae85e
SL
271/// [`Child`]: struct.Child.html
272/// [`stdout`]: struct.Child.html#structfield.stdout
ea8adc8c 273/// [dropped]: ../ops/trait.Drop.html
c34b1796 274#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
275pub struct ChildStdout {
276 inner: AnonPipe
277}
278
c34b1796 279#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
280impl Read for ChildStdout {
281 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
282 self.inner.read(buf)
283 }
041b39d2
XL
284 #[inline]
285 unsafe fn initializer(&self) -> Initializer {
286 Initializer::nop()
54a0048b 287 }
85aaf69f
SL
288}
289
62682a34
SL
290impl AsInner<AnonPipe> for ChildStdout {
291 fn as_inner(&self) -> &AnonPipe { &self.inner }
292}
293
c1a9b12d
SL
294impl IntoInner<AnonPipe> for ChildStdout {
295 fn into_inner(self) -> AnonPipe { self.inner }
296}
297
7453a54e
SL
298impl FromInner<AnonPipe> for ChildStdout {
299 fn from_inner(pipe: AnonPipe) -> ChildStdout {
300 ChildStdout { inner: pipe }
301 }
302}
303
8bb4bdeb 304#[stable(feature = "std_debug", since = "1.16.0")]
32a655c1
SL
305impl fmt::Debug for ChildStdout {
306 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
307 f.pad("ChildStdout { .. }")
308 }
309}
310
cc61c64b
XL
311/// A handle to a child process's stderr.
312///
313/// This struct is used in the [`stderr`] field on [`Child`].
5bcae85e 314///
ea8adc8c
XL
315/// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s
316/// underlying file handle will be closed.
317///
5bcae85e
SL
318/// [`Child`]: struct.Child.html
319/// [`stderr`]: struct.Child.html#structfield.stderr
ea8adc8c 320/// [dropped]: ../ops/trait.Drop.html
c34b1796 321#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
322pub struct ChildStderr {
323 inner: AnonPipe
324}
325
c34b1796 326#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
327impl Read for ChildStderr {
328 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
329 self.inner.read(buf)
330 }
041b39d2
XL
331 #[inline]
332 unsafe fn initializer(&self) -> Initializer {
333 Initializer::nop()
54a0048b 334 }
85aaf69f
SL
335}
336
62682a34
SL
337impl AsInner<AnonPipe> for ChildStderr {
338 fn as_inner(&self) -> &AnonPipe { &self.inner }
339}
340
c1a9b12d
SL
341impl IntoInner<AnonPipe> for ChildStderr {
342 fn into_inner(self) -> AnonPipe { self.inner }
343}
344
7453a54e
SL
345impl FromInner<AnonPipe> for ChildStderr {
346 fn from_inner(pipe: AnonPipe) -> ChildStderr {
347 ChildStderr { inner: pipe }
348 }
349}
350
8bb4bdeb 351#[stable(feature = "std_debug", since = "1.16.0")]
32a655c1
SL
352impl fmt::Debug for ChildStderr {
353 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
354 f.pad("ChildStderr { .. }")
355 }
356}
357
3157f602
XL
358/// A process builder, providing fine-grained control
359/// over how a new process should be spawned.
360///
361/// A default configuration can be
85aaf69f
SL
362/// generated using `Command::new(program)`, where `program` gives a path to the
363/// program to be executed. Additional builder methods allow the configuration
364/// to be changed (for example, by adding arguments) prior to spawning:
365///
366/// ```
85aaf69f
SL
367/// use std::process::Command;
368///
32a655c1
SL
369/// let output = if cfg!(target_os = "windows") {
370/// Command::new("cmd")
371/// .args(&["/C", "echo hello"])
372/// .output()
373/// .expect("failed to execute process")
374/// } else {
375/// Command::new("sh")
376/// .arg("-c")
377/// .arg("echo hello")
378/// .output()
379/// .expect("failed to execute process")
380/// };
a7813a04 381///
85aaf69f
SL
382/// let hello = output.stdout;
383/// ```
b7449926
XL
384///
385/// `Command` can be reused to spawn multiple processes. The builder methods
386/// change the command without needing to immediately spawn the process.
387///
388/// ```no_run
389/// use std::process::Command;
390///
391/// let mut echo_hello = Command::new("sh");
392/// echo_hello.arg("-c")
393/// .arg("echo hello");
394/// let hello_1 = echo_hello.output().expect("failed to execute process");
395/// let hello_2 = echo_hello.output().expect("failed to execute process");
396/// ```
397///
398/// Similarly, you can call builder methods after spawning a process and then
399/// spawn a new process with the modified settings.
400///
401/// ```no_run
402/// use std::process::Command;
403///
404/// let mut list_dir = Command::new("ls");
405///
406/// // Execute `ls` in the current directory of the program.
407/// list_dir.status().expect("process failed to execute");
408///
409/// println!("");
410///
411/// // Change `ls` to execute in the root directory.
412/// list_dir.current_dir("/");
413///
414/// // And then execute `ls` again but in the root directory.
415/// list_dir.status().expect("process failed to execute");
416/// ```
c34b1796 417#[stable(feature = "process", since = "1.0.0")]
85aaf69f 418pub struct Command {
62682a34 419 inner: imp::Command,
85aaf69f
SL
420}
421
422impl Command {
423 /// Constructs a new `Command` for launching the program at
424 /// path `program`, with the following default configuration:
425 ///
426 /// * No arguments to the program
427 /// * Inherit the current process's environment
428 /// * Inherit the current process's working directory
bd371182 429 /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
85aaf69f
SL
430 ///
431 /// Builder methods are provided to change these defaults and
432 /// otherwise configure the process.
a7813a04 433 ///
476ff2be
SL
434 /// If `program` is not an absolute path, the `PATH` will be searched in
435 /// an OS-defined way.
436 ///
437 /// The search path to be used may be controlled by setting the
438 /// `PATH` environment variable on the Command,
439 /// but this has some implementation limitations on Windows
abe05a73 440 /// (see <https://github.com/rust-lang/rust/issues/37519>).
476ff2be 441 ///
a7813a04
XL
442 /// # Examples
443 ///
444 /// Basic usage:
445 ///
446 /// ```no_run
447 /// use std::process::Command;
448 ///
449 /// Command::new("sh")
450 /// .spawn()
451 /// .expect("sh command failed to start");
452 /// ```
c34b1796
AL
453 #[stable(feature = "process", since = "1.0.0")]
454 pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
7453a54e 455 Command { inner: imp::Command::new(program.as_ref()) }
85aaf69f
SL
456 }
457
458 /// Add an argument to pass to the program.
a7813a04 459 ///
cc61c64b
XL
460 /// Only one argument can be passed per use. So instead of:
461 ///
041b39d2
XL
462 /// ```no_run
463 /// # std::process::Command::new("sh")
cc61c64b 464 /// .arg("-C /path/to/repo")
041b39d2 465 /// # ;
cc61c64b
XL
466 /// ```
467 ///
468 /// usage would be:
469 ///
041b39d2
XL
470 /// ```no_run
471 /// # std::process::Command::new("sh")
cc61c64b
XL
472 /// .arg("-C")
473 /// .arg("/path/to/repo")
041b39d2 474 /// # ;
cc61c64b
XL
475 /// ```
476 ///
477 /// To pass multiple arguments see [`args`].
478 ///
479 /// [`args`]: #method.args
480 ///
a7813a04
XL
481 /// # Examples
482 ///
483 /// Basic usage:
484 ///
485 /// ```no_run
486 /// use std::process::Command;
487 ///
488 /// Command::new("ls")
489 /// .arg("-l")
490 /// .arg("-a")
491 /// .spawn()
492 /// .expect("ls command failed to start");
493 /// ```
c34b1796
AL
494 #[stable(feature = "process", since = "1.0.0")]
495 pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
496 self.inner.arg(arg.as_ref());
85aaf69f
SL
497 self
498 }
499
500 /// Add multiple arguments to pass to the program.
a7813a04 501 ///
cc61c64b
XL
502 /// To pass a single argument see [`arg`].
503 ///
504 /// [`arg`]: #method.arg
505 ///
a7813a04
XL
506 /// # Examples
507 ///
508 /// Basic usage:
509 ///
510 /// ```no_run
511 /// use std::process::Command;
512 ///
513 /// Command::new("ls")
514 /// .args(&["-l", "-a"])
515 /// .spawn()
516 /// .expect("ls command failed to start");
517 /// ```
c34b1796 518 #[stable(feature = "process", since = "1.0.0")]
32a655c1
SL
519 pub fn args<I, S>(&mut self, args: I) -> &mut Command
520 where I: IntoIterator<Item=S>, S: AsRef<OsStr>
521 {
7453a54e
SL
522 for arg in args {
523 self.arg(arg.as_ref());
524 }
85aaf69f
SL
525 self
526 }
527
528 /// Inserts or updates an environment variable mapping.
529 ///
530 /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
531 /// and case-sensitive on all other platforms.
a7813a04
XL
532 ///
533 /// # Examples
534 ///
535 /// Basic usage:
536 ///
537 /// ```no_run
538 /// use std::process::Command;
539 ///
540 /// Command::new("ls")
541 /// .env("PATH", "/bin")
542 /// .spawn()
543 /// .expect("ls command failed to start");
544 /// ```
c34b1796
AL
545 #[stable(feature = "process", since = "1.0.0")]
546 pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
547 where K: AsRef<OsStr>, V: AsRef<OsStr>
85aaf69f 548 {
ff7c6d11 549 self.inner.env_mut().set(key.as_ref(), val.as_ref());
85aaf69f
SL
550 self
551 }
552
32a655c1
SL
553 /// Add or update multiple environment variable mappings.
554 ///
555 /// # Examples
556 ///
557 /// Basic usage:
cc61c64b 558 ///
32a655c1
SL
559 /// ```no_run
560 /// use std::process::{Command, Stdio};
561 /// use std::env;
562 /// use std::collections::HashMap;
563 ///
564 /// let filtered_env : HashMap<String, String> =
565 /// env::vars().filter(|&(ref k, _)|
566 /// k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH"
567 /// ).collect();
568 ///
569 /// Command::new("printenv")
570 /// .stdin(Stdio::null())
571 /// .stdout(Stdio::inherit())
572 /// .env_clear()
573 /// .envs(&filtered_env)
574 /// .spawn()
575 /// .expect("printenv failed to start");
576 /// ```
7cac9316 577 #[stable(feature = "command_envs", since = "1.19.0")]
32a655c1
SL
578 pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
579 where I: IntoIterator<Item=(K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>
580 {
581 for (ref key, ref val) in vars {
ff7c6d11 582 self.inner.env_mut().set(key.as_ref(), val.as_ref());
32a655c1
SL
583 }
584 self
585 }
586
85aaf69f 587 /// Removes an environment variable mapping.
a7813a04
XL
588 ///
589 /// # Examples
590 ///
591 /// Basic usage:
592 ///
593 /// ```no_run
594 /// use std::process::Command;
595 ///
596 /// Command::new("ls")
597 /// .env_remove("PATH")
598 /// .spawn()
599 /// .expect("ls command failed to start");
600 /// ```
c34b1796
AL
601 #[stable(feature = "process", since = "1.0.0")]
602 pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
ff7c6d11 603 self.inner.env_mut().remove(key.as_ref());
85aaf69f
SL
604 self
605 }
606
607 /// Clears the entire environment map for the child process.
a7813a04
XL
608 ///
609 /// # Examples
610 ///
611 /// Basic usage:
612 ///
613 /// ```no_run
614 /// use std::process::Command;
615 ///
616 /// Command::new("ls")
617 /// .env_clear()
618 /// .spawn()
619 /// .expect("ls command failed to start");
620 /// ```
c34b1796 621 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 622 pub fn env_clear(&mut self) -> &mut Command {
ff7c6d11 623 self.inner.env_mut().clear();
85aaf69f
SL
624 self
625 }
626
9346a6ac 627 /// Sets the working directory for the child process.
a7813a04 628 ///
b7449926
XL
629 /// # Platform-specific behavior
630 ///
631 /// If the program path is relative (e.g. `"./script.sh"`), it's ambiguous
632 /// whether it should be interpreted relative to the parent's working
633 /// directory or relative to `current_dir`. The behavior in this case is
634 /// platform specific and unstable, and it's recommended to use
635 /// [`canonicalize`] to get an absolute program path instead.
636 ///
a7813a04
XL
637 /// # Examples
638 ///
639 /// Basic usage:
640 ///
641 /// ```no_run
642 /// use std::process::Command;
643 ///
644 /// Command::new("ls")
645 /// .current_dir("/bin")
646 /// .spawn()
647 /// .expect("ls command failed to start");
648 /// ```
b7449926
XL
649 ///
650 /// [`canonicalize`]: ../fs/fn.canonicalize.html
c34b1796 651 #[stable(feature = "process", since = "1.0.0")]
7453a54e 652 pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
c34b1796 653 self.inner.cwd(dir.as_ref().as_ref());
85aaf69f
SL
654 self
655 }
656
ea8adc8c 657 /// Configuration for the child process's standard input (stdin) handle.
a7813a04 658 ///
abe05a73
XL
659 /// Defaults to [`inherit`] when used with `spawn` or `status`, and
660 /// defaults to [`piped`] when used with `output`.
661 ///
662 /// [`inherit`]: struct.Stdio.html#method.inherit
663 /// [`piped`]: struct.Stdio.html#method.piped
664 ///
a7813a04
XL
665 /// # Examples
666 ///
667 /// Basic usage:
668 ///
669 /// ```no_run
670 /// use std::process::{Command, Stdio};
671 ///
672 /// Command::new("ls")
673 /// .stdin(Stdio::null())
674 /// .spawn()
675 /// .expect("ls command failed to start");
676 /// ```
c34b1796 677 #[stable(feature = "process", since = "1.0.0")]
041b39d2
XL
678 pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
679 self.inner.stdin(cfg.into().0);
85aaf69f
SL
680 self
681 }
682
ea8adc8c 683 /// Configuration for the child process's standard output (stdout) handle.
a7813a04 684 ///
abe05a73
XL
685 /// Defaults to [`inherit`] when used with `spawn` or `status`, and
686 /// defaults to [`piped`] when used with `output`.
687 ///
688 /// [`inherit`]: struct.Stdio.html#method.inherit
689 /// [`piped`]: struct.Stdio.html#method.piped
690 ///
a7813a04
XL
691 /// # Examples
692 ///
693 /// Basic usage:
694 ///
695 /// ```no_run
696 /// use std::process::{Command, Stdio};
697 ///
698 /// Command::new("ls")
699 /// .stdout(Stdio::null())
700 /// .spawn()
701 /// .expect("ls command failed to start");
702 /// ```
c34b1796 703 #[stable(feature = "process", since = "1.0.0")]
041b39d2
XL
704 pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
705 self.inner.stdout(cfg.into().0);
85aaf69f
SL
706 self
707 }
708
ea8adc8c 709 /// Configuration for the child process's standard error (stderr) handle.
a7813a04 710 ///
abe05a73
XL
711 /// Defaults to [`inherit`] when used with `spawn` or `status`, and
712 /// defaults to [`piped`] when used with `output`.
713 ///
714 /// [`inherit`]: struct.Stdio.html#method.inherit
715 /// [`piped`]: struct.Stdio.html#method.piped
716 ///
a7813a04
XL
717 /// # Examples
718 ///
719 /// Basic usage:
720 ///
721 /// ```no_run
722 /// use std::process::{Command, Stdio};
723 ///
724 /// Command::new("ls")
725 /// .stderr(Stdio::null())
726 /// .spawn()
727 /// .expect("ls command failed to start");
728 /// ```
c34b1796 729 #[stable(feature = "process", since = "1.0.0")]
041b39d2
XL
730 pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
731 self.inner.stderr(cfg.into().0);
85aaf69f
SL
732 self
733 }
734
85aaf69f
SL
735 /// Executes the command as a child process, returning a handle to it.
736 ///
62682a34 737 /// By default, stdin, stdout and stderr are inherited from the parent.
a7813a04
XL
738 ///
739 /// # Examples
740 ///
741 /// Basic usage:
742 ///
743 /// ```no_run
744 /// use std::process::Command;
745 ///
746 /// Command::new("ls")
747 /// .spawn()
748 /// .expect("ls command failed to start");
749 /// ```
c34b1796 750 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 751 pub fn spawn(&mut self) -> io::Result<Child> {
54a0048b 752 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
85aaf69f
SL
753 }
754
755 /// Executes the command as a child process, waiting for it to finish and
756 /// collecting all of its output.
757 ///
ff7c6d11
XL
758 /// By default, stdout and stderr are captured (and used to provide the
759 /// resulting output). Stdin is not inherited from the parent and any
760 /// attempt by the child process to read from the stdin stream will result
761 /// in the stream immediately closing.
85aaf69f 762 ///
c34b1796 763 /// # Examples
85aaf69f 764 ///
a7813a04 765 /// ```should_panic
85aaf69f 766 /// use std::process::Command;
a7813a04
XL
767 /// let output = Command::new("/bin/cat")
768 /// .arg("file.txt")
769 /// .output()
770 /// .expect("failed to execute process");
85aaf69f
SL
771 ///
772 /// println!("status: {}", output.status);
c34b1796
AL
773 /// println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
774 /// println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
a7813a04
XL
775 ///
776 /// assert!(output.status.success());
85aaf69f 777 /// ```
c34b1796 778 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 779 pub fn output(&mut self) -> io::Result<Output> {
54a0048b 780 self.inner.spawn(imp::Stdio::MakePipe, false).map(Child::from_inner)
7453a54e 781 .and_then(|p| p.wait_with_output())
85aaf69f
SL
782 }
783
784 /// Executes a command as a child process, waiting for it to finish and
785 /// collecting its exit status.
786 ///
62682a34 787 /// By default, stdin, stdout and stderr are inherited from the parent.
85aaf69f 788 ///
c34b1796 789 /// # Examples
85aaf69f 790 ///
a7813a04 791 /// ```should_panic
85aaf69f
SL
792 /// use std::process::Command;
793 ///
a7813a04
XL
794 /// let status = Command::new("/bin/cat")
795 /// .arg("file.txt")
796 /// .status()
797 /// .expect("failed to execute process");
85aaf69f
SL
798 ///
799 /// println!("process exited with: {}", status);
a7813a04
XL
800 ///
801 /// assert!(status.success());
85aaf69f 802 /// ```
c34b1796 803 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 804 pub fn status(&mut self) -> io::Result<ExitStatus> {
54a0048b
SL
805 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
806 .and_then(|mut p| p.wait())
85aaf69f
SL
807 }
808}
809
810#[stable(feature = "rust1", since = "1.0.0")]
811impl fmt::Debug for Command {
812 /// Format the program and arguments of a Command for display. Any
813 /// non-utf8 data is lossily converted using the utf8 replacement
814 /// character.
815 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7453a54e 816 self.inner.fmt(f)
85aaf69f
SL
817 }
818}
819
62682a34
SL
820impl AsInner<imp::Command> for Command {
821 fn as_inner(&self) -> &imp::Command { &self.inner }
85aaf69f
SL
822}
823
62682a34
SL
824impl AsInnerMut<imp::Command> for Command {
825 fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner }
85aaf69f
SL
826}
827
85aaf69f 828/// The output of a finished process.
abe05a73
XL
829///
830/// This is returned in a Result by either the [`output`] method of a
831/// [`Command`], or the [`wait_with_output`] method of a [`Child`]
832/// process.
833///
834/// [`Command`]: struct.Command.html
835/// [`Child`]: struct.Child.html
836/// [`output`]: struct.Command.html#method.output
837/// [`wait_with_output`]: struct.Child.html#method.wait_with_output
85aaf69f 838#[derive(PartialEq, Eq, Clone)]
c34b1796 839#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
840pub struct Output {
841 /// The status (exit code) of the process.
c34b1796 842 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
843 pub status: ExitStatus,
844 /// The data that the process wrote to stdout.
c34b1796 845 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
846 pub stdout: Vec<u8>,
847 /// The data that the process wrote to stderr.
c34b1796 848 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
849 pub stderr: Vec<u8>,
850}
851
9cc50fc6
SL
852// If either stderr or stdout are valid utf8 strings it prints the valid
853// strings, otherwise it prints the byte sequence instead
854#[stable(feature = "process_output_debug", since = "1.7.0")]
855impl fmt::Debug for Output {
856 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
857
858 let stdout_utf8 = str::from_utf8(&self.stdout);
8faf50e0 859 let stdout_debug: &dyn fmt::Debug = match stdout_utf8 {
9cc50fc6
SL
860 Ok(ref str) => str,
861 Err(_) => &self.stdout
862 };
863
864 let stderr_utf8 = str::from_utf8(&self.stderr);
8faf50e0 865 let stderr_debug: &dyn fmt::Debug = match stderr_utf8 {
9cc50fc6
SL
866 Ok(ref str) => str,
867 Err(_) => &self.stderr
868 };
869
870 fmt.debug_struct("Output")
871 .field("status", &self.status)
872 .field("stdout", stdout_debug)
873 .field("stderr", stderr_debug)
874 .finish()
875 }
876}
877
abe05a73
XL
878/// Describes what to do with a standard I/O stream for a child process when
879/// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`].
880///
881/// [`stdin`]: struct.Command.html#method.stdin
882/// [`stdout`]: struct.Command.html#method.stdout
883/// [`stderr`]: struct.Command.html#method.stderr
884/// [`Command`]: struct.Command.html
c34b1796 885#[stable(feature = "process", since = "1.0.0")]
7453a54e 886pub struct Stdio(imp::Stdio);
85aaf69f
SL
887
888impl Stdio {
889 /// A new pipe should be arranged to connect the parent and child processes.
abe05a73
XL
890 ///
891 /// # Examples
892 ///
893 /// With stdout:
894 ///
895 /// ```no_run
896 /// use std::process::{Command, Stdio};
897 ///
898 /// let output = Command::new("echo")
899 /// .arg("Hello, world!")
900 /// .stdout(Stdio::piped())
901 /// .output()
902 /// .expect("Failed to execute command");
903 ///
904 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "Hello, world!\n");
905 /// // Nothing echoed to console
906 /// ```
907 ///
908 /// With stdin:
909 ///
910 /// ```no_run
911 /// use std::io::Write;
912 /// use std::process::{Command, Stdio};
913 ///
914 /// let mut child = Command::new("rev")
915 /// .stdin(Stdio::piped())
916 /// .stdout(Stdio::piped())
917 /// .spawn()
918 /// .expect("Failed to spawn child process");
919 ///
920 /// {
921 /// let mut stdin = child.stdin.as_mut().expect("Failed to open stdin");
922 /// stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin");
923 /// }
924 ///
925 /// let output = child.wait_with_output().expect("Failed to read stdout");
926 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH\n");
927 /// ```
c34b1796 928 #[stable(feature = "process", since = "1.0.0")]
7453a54e 929 pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) }
85aaf69f
SL
930
931 /// The child inherits from the corresponding parent descriptor.
abe05a73
XL
932 ///
933 /// # Examples
934 ///
935 /// With stdout:
936 ///
937 /// ```no_run
938 /// use std::process::{Command, Stdio};
939 ///
940 /// let output = Command::new("echo")
941 /// .arg("Hello, world!")
942 /// .stdout(Stdio::inherit())
943 /// .output()
944 /// .expect("Failed to execute command");
945 ///
946 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
947 /// // "Hello, world!" echoed to console
948 /// ```
949 ///
950 /// With stdin:
951 ///
952 /// ```no_run
953 /// use std::process::{Command, Stdio};
954 ///
955 /// let output = Command::new("rev")
956 /// .stdin(Stdio::inherit())
957 /// .stdout(Stdio::piped())
958 /// .output()
959 /// .expect("Failed to execute command");
960 ///
961 /// println!("You piped in the reverse of: {}", String::from_utf8_lossy(&output.stdout));
962 /// ```
c34b1796 963 #[stable(feature = "process", since = "1.0.0")]
7453a54e 964 pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) }
85aaf69f
SL
965
966 /// This stream will be ignored. This is the equivalent of attaching the
967 /// stream to `/dev/null`
abe05a73
XL
968 ///
969 /// # Examples
970 ///
971 /// With stdout:
972 ///
973 /// ```no_run
974 /// use std::process::{Command, Stdio};
975 ///
976 /// let output = Command::new("echo")
977 /// .arg("Hello, world!")
978 /// .stdout(Stdio::null())
979 /// .output()
980 /// .expect("Failed to execute command");
981 ///
982 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
983 /// // Nothing echoed to console
984 /// ```
985 ///
986 /// With stdin:
987 ///
988 /// ```no_run
989 /// use std::process::{Command, Stdio};
990 ///
991 /// let output = Command::new("rev")
992 /// .stdin(Stdio::null())
993 /// .stdout(Stdio::piped())
994 /// .output()
995 /// .expect("Failed to execute command");
996 ///
997 /// assert_eq!(String::from_utf8_lossy(&output.stdout), "");
998 /// // Ignores any piped-in input
999 /// ```
c34b1796 1000 #[stable(feature = "process", since = "1.0.0")]
7453a54e 1001 pub fn null() -> Stdio { Stdio(imp::Stdio::Null) }
62682a34
SL
1002}
1003
7453a54e
SL
1004impl FromInner<imp::Stdio> for Stdio {
1005 fn from_inner(inner: imp::Stdio) -> Stdio {
1006 Stdio(inner)
62682a34 1007 }
85aaf69f
SL
1008}
1009
8bb4bdeb 1010#[stable(feature = "std_debug", since = "1.16.0")]
32a655c1
SL
1011impl fmt::Debug for Stdio {
1012 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1013 f.pad("Stdio { .. }")
1014 }
1015}
1016
041b39d2
XL
1017#[stable(feature = "stdio_from", since = "1.20.0")]
1018impl From<ChildStdin> for Stdio {
1019 fn from(child: ChildStdin) -> Stdio {
1020 Stdio::from_inner(child.into_inner().into())
1021 }
1022}
1023
1024#[stable(feature = "stdio_from", since = "1.20.0")]
1025impl From<ChildStdout> for Stdio {
1026 fn from(child: ChildStdout) -> Stdio {
1027 Stdio::from_inner(child.into_inner().into())
1028 }
1029}
1030
1031#[stable(feature = "stdio_from", since = "1.20.0")]
1032impl From<ChildStderr> for Stdio {
1033 fn from(child: ChildStderr) -> Stdio {
1034 Stdio::from_inner(child.into_inner().into())
1035 }
1036}
1037
1038#[stable(feature = "stdio_from", since = "1.20.0")]
1039impl From<fs::File> for Stdio {
1040 fn from(file: fs::File) -> Stdio {
1041 Stdio::from_inner(file.into_inner().into())
1042 }
1043}
1044
85aaf69f 1045/// Describes the result of a process after it has terminated.
7cac9316
XL
1046///
1047/// This `struct` is used to represent the exit status of a child process.
1048/// Child processes are created via the [`Command`] struct and their exit
1049/// status is exposed through the [`status`] method.
1050///
1051/// [`Command`]: struct.Command.html
1052/// [`status`]: struct.Command.html#method.status
85aaf69f 1053#[derive(PartialEq, Eq, Clone, Copy, Debug)]
c34b1796 1054#[stable(feature = "process", since = "1.0.0")]
62682a34 1055pub struct ExitStatus(imp::ExitStatus);
85aaf69f
SL
1056
1057impl ExitStatus {
3b2f2976
XL
1058 /// Was termination successful? Signal termination is not considered a
1059 /// success, and success is defined as a zero exit status.
5bcae85e
SL
1060 ///
1061 /// # Examples
1062 ///
1063 /// ```rust,no_run
1064 /// use std::process::Command;
1065 ///
1066 /// let status = Command::new("mkdir")
1067 /// .arg("projects")
1068 /// .status()
1069 /// .expect("failed to execute mkdir");
1070 ///
1071 /// if status.success() {
1072 /// println!("'projects/' directory created");
1073 /// } else {
1074 /// println!("failed to create 'projects/' directory");
1075 /// }
1076 /// ```
c34b1796 1077 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
1078 pub fn success(&self) -> bool {
1079 self.0.success()
1080 }
1081
9346a6ac 1082 /// Returns the exit code of the process, if any.
85aaf69f
SL
1083 ///
1084 /// On Unix, this will return `None` if the process was terminated
1085 /// by a signal; `std::os::unix` provides an extension trait for
1086 /// extracting the signal and other details from the `ExitStatus`.
7cac9316
XL
1087 ///
1088 /// # Examples
1089 ///
1090 /// ```no_run
1091 /// use std::process::Command;
1092 ///
1093 /// let status = Command::new("mkdir")
1094 /// .arg("projects")
1095 /// .status()
1096 /// .expect("failed to execute mkdir");
1097 ///
1098 /// match status.code() {
1099 /// Some(code) => println!("Exited with status code: {}", code),
1100 /// None => println!("Process terminated by signal")
1101 /// }
1102 /// ```
c34b1796 1103 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
1104 pub fn code(&self) -> Option<i32> {
1105 self.0.code()
1106 }
1107}
1108
62682a34
SL
1109impl AsInner<imp::ExitStatus> for ExitStatus {
1110 fn as_inner(&self) -> &imp::ExitStatus { &self.0 }
85aaf69f
SL
1111}
1112
a7813a04
XL
1113impl FromInner<imp::ExitStatus> for ExitStatus {
1114 fn from_inner(s: imp::ExitStatus) -> ExitStatus {
1115 ExitStatus(s)
1116 }
1117}
1118
c34b1796 1119#[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
1120impl fmt::Display for ExitStatus {
1121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1122 self.0.fmt(f)
1123 }
1124}
1125
0531ce1d
XL
1126/// This type represents the status code a process can return to its
1127/// parent under normal termination.
1128///
1129/// Numeric values used in this type don't have portable meanings, and
1130/// different platforms may mask different amounts of them.
1131///
1132/// For the platform's canonical successful and unsuccessful codes, see
1133/// the [`SUCCESS`] and [`FAILURE`] associated items.
1134///
1135/// [`SUCCESS`]: #associatedconstant.SUCCESS
1136/// [`FAILURE`]: #associatedconstant.FAILURE
1137///
1138/// **Warning**: While various forms of this were discussed in [RFC #1937],
1139/// it was ultimately cut from that RFC, and thus this type is more subject
1140/// to change even than the usual unstable item churn.
1141///
1142/// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937
1143#[derive(Clone, Copy, Debug)]
1144#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1145pub struct ExitCode(imp::ExitCode);
1146
1147#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1148impl ExitCode {
1149 /// The canonical ExitCode for successful termination on this platform.
1150 ///
1151 /// Note that a `()`-returning `main` implicitly results in a successful
1152 /// termination, so there's no need to return this from `main` unless
1153 /// you're also returning other possible codes.
1154 #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1155 pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS);
1156
1157 /// The canonical ExitCode for unsuccessful termination on this platform.
1158 ///
1159 /// If you're only returning this and `SUCCESS` from `main`, consider
1160 /// instead returning `Err(_)` and `Ok(())` respectively, which will
1161 /// return the same codes (but will also `eprintln!` the error).
1162 #[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
1163 pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
1164}
1165
85aaf69f 1166impl Child {
83c7162d
XL
1167 /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`]
1168 /// error is returned.
1169 ///
1170 /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function,
1171 /// especially the [`Other`] kind might change to more specific kinds in the future.
1172 ///
1173 /// This is equivalent to sending a SIGKILL on Unix platforms.
a7813a04
XL
1174 ///
1175 /// # Examples
1176 ///
1177 /// Basic usage:
1178 ///
1179 /// ```no_run
1180 /// use std::process::Command;
1181 ///
1182 /// let mut command = Command::new("yes");
1183 /// if let Ok(mut child) = command.spawn() {
1184 /// child.kill().expect("command wasn't running");
1185 /// } else {
1186 /// println!("yes command didn't start");
1187 /// }
1188 /// ```
83c7162d
XL
1189 ///
1190 /// [`ErrorKind`]: ../io/enum.ErrorKind.html
1191 /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput
1192 /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other
c34b1796 1193 #[stable(feature = "process", since = "1.0.0")]
85aaf69f 1194 pub fn kill(&mut self) -> io::Result<()> {
7453a54e 1195 self.handle.kill()
85aaf69f
SL
1196 }
1197
62682a34 1198 /// Returns the OS-assigned process identifier associated with this child.
a7813a04
XL
1199 ///
1200 /// # Examples
1201 ///
1202 /// Basic usage:
1203 ///
1204 /// ```no_run
1205 /// use std::process::Command;
1206 ///
1207 /// let mut command = Command::new("ls");
1208 /// if let Ok(child) = command.spawn() {
1209 /// println!("Child's id is {}", child.id());
1210 /// } else {
1211 /// println!("ls command didn't start");
1212 /// }
1213 /// ```
c1a9b12d 1214 #[stable(feature = "process_id", since = "1.3.0")]
62682a34
SL
1215 pub fn id(&self) -> u32 {
1216 self.handle.id()
1217 }
1218
9346a6ac 1219 /// Waits for the child to exit completely, returning the status that it
85aaf69f
SL
1220 /// exited with. This function will continue to have the same return value
1221 /// after it has been called at least once.
1222 ///
1223 /// The stdin handle to the child process, if any, will be closed
1224 /// before waiting. This helps avoid deadlock: it ensures that the
1225 /// child does not block waiting for input from the parent, while
1226 /// the parent waits for the child to exit.
a7813a04
XL
1227 ///
1228 /// # Examples
1229 ///
1230 /// Basic usage:
1231 ///
1232 /// ```no_run
1233 /// use std::process::Command;
1234 ///
1235 /// let mut command = Command::new("ls");
1236 /// if let Ok(mut child) = command.spawn() {
1237 /// child.wait().expect("command wasn't running");
1238 /// println!("Child has finished its execution!");
1239 /// } else {
1240 /// println!("ls command didn't start");
1241 /// }
1242 /// ```
c34b1796 1243 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
1244 pub fn wait(&mut self) -> io::Result<ExitStatus> {
1245 drop(self.stdin.take());
7453a54e 1246 self.handle.wait().map(ExitStatus)
85aaf69f
SL
1247 }
1248
32a655c1
SL
1249 /// Attempts to collect the exit status of the child if it has already
1250 /// exited.
1251 ///
1252 /// This function will not block the calling thread and will only advisorily
1253 /// check to see if the child process has exited or not. If the child has
1254 /// exited then on Unix the process id is reaped. This function is
1255 /// guaranteed to repeatedly return a successful exit status so long as the
1256 /// child has already exited.
1257 ///
8bb4bdeb
XL
1258 /// If the child has exited, then `Ok(Some(status))` is returned. If the
1259 /// exit status is not available at this time then `Ok(None)` is returned.
1260 /// If an error occurs, then that error is returned.
32a655c1
SL
1261 ///
1262 /// Note that unlike `wait`, this function will not attempt to drop stdin.
1263 ///
1264 /// # Examples
1265 ///
1266 /// Basic usage:
1267 ///
1268 /// ```no_run
32a655c1
SL
1269 /// use std::process::Command;
1270 ///
1271 /// let mut child = Command::new("ls").spawn().unwrap();
1272 ///
1273 /// match child.try_wait() {
8bb4bdeb
XL
1274 /// Ok(Some(status)) => println!("exited with: {}", status),
1275 /// Ok(None) => {
32a655c1
SL
1276 /// println!("status not ready yet, let's really wait");
1277 /// let res = child.wait();
1278 /// println!("result: {:?}", res);
1279 /// }
1280 /// Err(e) => println!("error attempting to wait: {}", e),
1281 /// }
1282 /// ```
cc61c64b 1283 #[stable(feature = "process_try_wait", since = "1.18.0")]
8bb4bdeb
XL
1284 pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
1285 Ok(self.handle.try_wait()?.map(ExitStatus))
32a655c1
SL
1286 }
1287
9346a6ac 1288 /// Simultaneously waits for the child to exit and collect all remaining
92a42be0 1289 /// output on the stdout/stderr handles, returning an `Output`
85aaf69f
SL
1290 /// instance.
1291 ///
1292 /// The stdin handle to the child process, if any, will be closed
1293 /// before waiting. This helps avoid deadlock: it ensures that the
1294 /// child does not block waiting for input from the parent, while
1295 /// the parent waits for the child to exit.
a7813a04
XL
1296 ///
1297 /// By default, stdin, stdout and stderr are inherited from the parent.
1298 /// In order to capture the output into this `Result<Output>` it is
1299 /// necessary to create new pipes between parent and child. Use
1300 /// `stdout(Stdio::piped())` or `stderr(Stdio::piped())`, respectively.
1301 ///
1302 /// # Examples
1303 ///
1304 /// ```should_panic
1305 /// use std::process::{Command, Stdio};
1306 ///
3157f602
XL
1307 /// let child = Command::new("/bin/cat")
1308 /// .arg("file.txt")
1309 /// .stdout(Stdio::piped())
1310 /// .spawn()
1311 /// .expect("failed to execute child");
a7813a04 1312 ///
3157f602
XL
1313 /// let output = child
1314 /// .wait_with_output()
1315 /// .expect("failed to wait on child");
a7813a04 1316 ///
3157f602 1317 /// assert!(output.status.success());
a7813a04
XL
1318 /// ```
1319 ///
c34b1796 1320 #[stable(feature = "process", since = "1.0.0")]
85aaf69f
SL
1321 pub fn wait_with_output(mut self) -> io::Result<Output> {
1322 drop(self.stdin.take());
54a0048b
SL
1323
1324 let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
1325 match (self.stdout.take(), self.stderr.take()) {
1326 (None, None) => {}
1327 (Some(mut out), None) => {
1328 let res = out.read_to_end(&mut stdout);
1329 res.unwrap();
1330 }
1331 (None, Some(mut err)) => {
1332 let res = err.read_to_end(&mut stderr);
1333 res.unwrap();
1334 }
1335 (Some(out), Some(err)) => {
1336 let res = read2(out.inner, &mut stdout, err.inner, &mut stderr);
1337 res.unwrap();
1338 }
85aaf69f 1339 }
85aaf69f 1340
54a0048b 1341 let status = self.wait()?;
85aaf69f 1342 Ok(Output {
3b2f2976
XL
1343 status,
1344 stdout,
1345 stderr,
85aaf69f
SL
1346 })
1347 }
1348}
1349
c34b1796
AL
1350/// Terminates the current process with the specified exit code.
1351///
1352/// This function will never return and will immediately terminate the current
1353/// process. The exit code is passed through to the underlying OS and will be
1354/// available for consumption by another process.
1355///
1356/// Note that because this function never returns, and that it terminates the
1357/// process, no destructors on the current stack or any other thread's stack
1358/// will be run. If a clean shutdown is needed it is recommended to only call
1359/// this function at a known point where there are no more destructors left
1360/// to run.
476ff2be
SL
1361///
1362/// ## Platform-specific behavior
1363///
1364/// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit`
1365/// will be visible to a parent process inspecting the exit code. On most
1366/// Unix-like platforms, only the eight least-significant bits are considered.
1367///
1368/// # Examples
1369///
8bb4bdeb
XL
1370/// Due to this function’s behavior regarding destructors, a conventional way
1371/// to use the function is to extract the actual computation to another
1372/// function and compute the exit code from its return value:
1373///
476ff2be 1374/// ```
8bb4bdeb
XL
1375/// fn run_app() -> Result<(), ()> {
1376/// // Application logic here
1377/// Ok(())
1378/// }
476ff2be 1379///
8bb4bdeb
XL
1380/// fn main() {
1381/// ::std::process::exit(match run_app() {
1382/// Ok(_) => 0,
1383/// Err(err) => {
abe05a73 1384/// eprintln!("error: {:?}", err);
8bb4bdeb
XL
1385/// 1
1386/// }
1387/// });
1388/// }
476ff2be
SL
1389/// ```
1390///
1391/// Due to [platform-specific behavior], the exit code for this example will be
1392/// `0` on Linux, but `256` on Windows:
1393///
1394/// ```no_run
1395/// use std::process;
1396///
7cac9316 1397/// process::exit(0x0100);
476ff2be
SL
1398/// ```
1399///
1400/// [platform-specific behavior]: #platform-specific-behavior
c34b1796
AL
1401#[stable(feature = "rust1", since = "1.0.0")]
1402pub fn exit(code: i32) -> ! {
e9174d1e 1403 ::sys_common::cleanup();
c34b1796
AL
1404 ::sys::os::exit(code)
1405}
1406
476ff2be
SL
1407/// Terminates the process in an abnormal fashion.
1408///
1409/// The function will never return and will immediately terminate the current
1410/// process in a platform specific "abnormal" manner.
1411///
1412/// Note that because this function never returns, and that it terminates the
1413/// process, no destructors on the current stack or any other thread's stack
ea8adc8c
XL
1414/// will be run.
1415///
1416/// This is in contrast to the default behaviour of [`panic!`] which unwinds
1417/// the current thread's stack and calls all destructors.
1418/// When `panic="abort"` is set, either as an argument to `rustc` or in a
1419/// crate's Cargo.toml, [`panic!`] and `abort` are similar. However,
1420/// [`panic!`] will still call the [panic hook] while `abort` will not.
1421///
1422/// If a clean shutdown is needed it is recommended to only call
476ff2be
SL
1423/// this function at a known point where there are no more destructors left
1424/// to run.
cc61c64b
XL
1425///
1426/// # Examples
1427///
1428/// ```no_run
1429/// use std::process;
1430///
1431/// fn main() {
1432/// println!("aborting");
1433///
1434/// process::abort();
1435///
1436/// // execution never gets here
1437/// }
1438/// ```
1439///
ea8adc8c 1440/// The `abort` function terminates the process, so the destructor will not
cc61c64b
XL
1441/// get run on the example below:
1442///
1443/// ```no_run
1444/// use std::process;
1445///
1446/// struct HasDrop;
1447///
1448/// impl Drop for HasDrop {
1449/// fn drop(&mut self) {
1450/// println!("This will never be printed!");
1451/// }
1452/// }
1453///
1454/// fn main() {
1455/// let _x = HasDrop;
1456/// process::abort();
1457/// // the destructor implemented for HasDrop will never get run
1458/// }
1459/// ```
ea8adc8c
XL
1460///
1461/// [`panic!`]: ../../std/macro.panic.html
1462/// [panic hook]: ../../std/panic/fn.set_hook.html
8bb4bdeb 1463#[stable(feature = "process_abort", since = "1.17.0")]
476ff2be
SL
1464pub fn abort() -> ! {
1465 unsafe { ::sys::abort_internal() };
1466}
1467
abe05a73
XL
1468/// Returns the OS-assigned process identifier associated with this process.
1469///
1470/// # Examples
1471///
1472/// Basic usage:
1473///
1474/// ```no_run
abe05a73
XL
1475/// use std::process;
1476///
1477/// println!("My pid is {}", process::id());
1478/// ```
1479///
1480///
0531ce1d 1481#[stable(feature = "getpid", since = "1.26.0")]
abe05a73
XL
1482pub fn id() -> u32 {
1483 ::sys::os::getpid()
1484}
1485
0531ce1d
XL
1486/// A trait for implementing arbitrary return types in the `main` function.
1487///
1488/// The c-main function only supports to return integers as return type.
1489/// So, every type implementing the `Termination` trait has to be converted
1490/// to an integer.
1491///
1492/// The default implementations are returning `libc::EXIT_SUCCESS` to indicate
1493/// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
1494#[cfg_attr(not(test), lang = "termination")]
1495#[unstable(feature = "termination_trait_lib", issue = "43301")]
1496#[rustc_on_unimplemented(
1497 message="`main` has invalid return type `{Self}`",
1498 label="`main` can only return types that implement `{Termination}`")]
1499pub trait Termination {
1500 /// Is called to get the representation of the value as status code.
1501 /// This status code is returned to the operating system.
1502 fn report(self) -> i32;
1503}
1504
1505#[unstable(feature = "termination_trait_lib", issue = "43301")]
1506impl Termination for () {
83c7162d 1507 #[inline]
0531ce1d
XL
1508 fn report(self) -> i32 { ExitCode::SUCCESS.report() }
1509}
1510
1511#[unstable(feature = "termination_trait_lib", issue = "43301")]
1512impl<E: fmt::Debug> Termination for Result<(), E> {
1513 fn report(self) -> i32 {
1514 match self {
1515 Ok(()) => ().report(),
1516 Err(err) => Err::<!, _>(err).report(),
1517 }
1518 }
1519}
1520
1521#[unstable(feature = "termination_trait_lib", issue = "43301")]
1522impl Termination for ! {
1523 fn report(self) -> i32 { self }
1524}
1525
1526#[unstable(feature = "termination_trait_lib", issue = "43301")]
1527impl<E: fmt::Debug> Termination for Result<!, E> {
1528 fn report(self) -> i32 {
1529 let Err(err) = self;
1530 eprintln!("Error: {:?}", err);
1531 ExitCode::FAILURE.report()
1532 }
1533}
1534
1535#[unstable(feature = "termination_trait_lib", issue = "43301")]
1536impl Termination for ExitCode {
83c7162d 1537 #[inline]
0531ce1d
XL
1538 fn report(self) -> i32 {
1539 self.0.as_i32()
1540 }
1541}
1542
2c00a5a8 1543#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
85aaf69f 1544mod tests {
85aaf69f 1545 use io::prelude::*;
c34b1796
AL
1546
1547 use io::ErrorKind;
85aaf69f 1548 use str;
c34b1796 1549 use super::{Command, Output, Stdio};
85aaf69f
SL
1550
1551 // FIXME(#10380) these tests should not all be ignored on android.
1552
85aaf69f 1553 #[test]
7453a54e 1554 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 1555 fn smoke() {
32a655c1
SL
1556 let p = if cfg!(target_os = "windows") {
1557 Command::new("cmd").args(&["/C", "exit 0"]).spawn()
1558 } else {
1559 Command::new("true").spawn()
1560 };
85aaf69f
SL
1561 assert!(p.is_ok());
1562 let mut p = p.unwrap();
1563 assert!(p.wait().unwrap().success());
1564 }
1565
85aaf69f 1566 #[test]
7453a54e 1567 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
1568 fn smoke_failure() {
1569 match Command::new("if-this-is-a-binary-then-the-world-has-ended").spawn() {
1570 Ok(..) => panic!(),
1571 Err(..) => {}
1572 }
1573 }
1574
85aaf69f 1575 #[test]
7453a54e 1576 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 1577 fn exit_reported_right() {
32a655c1
SL
1578 let p = if cfg!(target_os = "windows") {
1579 Command::new("cmd").args(&["/C", "exit 1"]).spawn()
1580 } else {
1581 Command::new("false").spawn()
1582 };
85aaf69f
SL
1583 assert!(p.is_ok());
1584 let mut p = p.unwrap();
1585 assert!(p.wait().unwrap().code() == Some(1));
c34b1796 1586 drop(p.wait());
85aaf69f
SL
1587 }
1588
85aaf69f 1589 #[test]
7453a54e
SL
1590 #[cfg(unix)]
1591 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 1592 fn signal_reported_right() {
c34b1796 1593 use os::unix::process::ExitStatusExt;
85aaf69f 1594
b039eaaf
SL
1595 let mut p = Command::new("/bin/sh")
1596 .arg("-c").arg("read a")
1597 .stdin(Stdio::piped())
1598 .spawn().unwrap();
1599 p.kill().unwrap();
85aaf69f
SL
1600 match p.wait().unwrap().signal() {
1601 Some(9) => {},
b039eaaf
SL
1602 result => panic!("not terminated by signal 9 (instead, {:?})",
1603 result),
85aaf69f
SL
1604 }
1605 }
1606
1607 pub fn run_output(mut cmd: Command) -> String {
1608 let p = cmd.spawn();
1609 assert!(p.is_ok());
1610 let mut p = p.unwrap();
1611 assert!(p.stdout.is_some());
1612 let mut ret = String::new();
1613 p.stdout.as_mut().unwrap().read_to_string(&mut ret).unwrap();
1614 assert!(p.wait().unwrap().success());
1615 return ret;
1616 }
1617
85aaf69f 1618 #[test]
7453a54e 1619 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 1620 fn stdout_works() {
32a655c1
SL
1621 if cfg!(target_os = "windows") {
1622 let mut cmd = Command::new("cmd");
1623 cmd.args(&["/C", "echo foobar"]).stdout(Stdio::piped());
1624 assert_eq!(run_output(cmd), "foobar\r\n");
1625 } else {
1626 let mut cmd = Command::new("echo");
1627 cmd.arg("foobar").stdout(Stdio::piped());
1628 assert_eq!(run_output(cmd), "foobar\n");
1629 }
85aaf69f
SL
1630 }
1631
85aaf69f 1632 #[test]
7453a54e 1633 #[cfg_attr(any(windows, target_os = "android"), ignore)]
85aaf69f
SL
1634 fn set_current_dir_works() {
1635 let mut cmd = Command::new("/bin/sh");
1636 cmd.arg("-c").arg("pwd")
1637 .current_dir("/")
c34b1796 1638 .stdout(Stdio::piped());
85aaf69f
SL
1639 assert_eq!(run_output(cmd), "/\n");
1640 }
1641
85aaf69f 1642 #[test]
7453a54e 1643 #[cfg_attr(any(windows, target_os = "android"), ignore)]
85aaf69f
SL
1644 fn stdin_works() {
1645 let mut p = Command::new("/bin/sh")
1646 .arg("-c").arg("read line; echo $line")
c34b1796
AL
1647 .stdin(Stdio::piped())
1648 .stdout(Stdio::piped())
85aaf69f
SL
1649 .spawn().unwrap();
1650 p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap();
1651 drop(p.stdin.take());
1652 let mut out = String::new();
1653 p.stdout.as_mut().unwrap().read_to_string(&mut out).unwrap();
1654 assert!(p.wait().unwrap().success());
1655 assert_eq!(out, "foobar\n");
1656 }
1657
1658
85aaf69f 1659 #[test]
7453a54e
SL
1660 #[cfg_attr(target_os = "android", ignore)]
1661 #[cfg(unix)]
85aaf69f 1662 fn uid_works() {
c34b1796 1663 use os::unix::prelude::*;
85aaf69f
SL
1664 use libc;
1665 let mut p = Command::new("/bin/sh")
1666 .arg("-c").arg("true")
1667 .uid(unsafe { libc::getuid() })
1668 .gid(unsafe { libc::getgid() })
1669 .spawn().unwrap();
1670 assert!(p.wait().unwrap().success());
1671 }
1672
85aaf69f 1673 #[test]
7453a54e
SL
1674 #[cfg_attr(target_os = "android", ignore)]
1675 #[cfg(unix)]
85aaf69f 1676 fn uid_to_root_fails() {
c34b1796 1677 use os::unix::prelude::*;
85aaf69f
SL
1678 use libc;
1679
1680 // if we're already root, this isn't a valid test. Most of the bots run
1681 // as non-root though (android is an exception).
1682 if unsafe { libc::getuid() == 0 } { return }
1683 assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
1684 }
1685
85aaf69f 1686 #[test]
7453a54e 1687 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 1688 fn test_process_status() {
32a655c1
SL
1689 let mut status = if cfg!(target_os = "windows") {
1690 Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap()
1691 } else {
1692 Command::new("false").status().unwrap()
1693 };
85aaf69f
SL
1694 assert!(status.code() == Some(1));
1695
32a655c1
SL
1696 status = if cfg!(target_os = "windows") {
1697 Command::new("cmd").args(&["/C", "exit 0"]).status().unwrap()
1698 } else {
1699 Command::new("true").status().unwrap()
1700 };
85aaf69f
SL
1701 assert!(status.success());
1702 }
1703
1704 #[test]
1705 fn test_process_output_fail_to_start() {
1706 match Command::new("/no-binary-by-this-name-should-exist").output() {
c34b1796 1707 Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
85aaf69f
SL
1708 Ok(..) => panic!()
1709 }
1710 }
1711
85aaf69f 1712 #[test]
7453a54e 1713 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
1714 fn test_process_output_output() {
1715 let Output {status, stdout, stderr}
32a655c1
SL
1716 = if cfg!(target_os = "windows") {
1717 Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap()
1718 } else {
1719 Command::new("echo").arg("hello").output().unwrap()
1720 };
c34b1796 1721 let output_str = str::from_utf8(&stdout).unwrap();
85aaf69f
SL
1722
1723 assert!(status.success());
1724 assert_eq!(output_str.trim().to_string(), "hello");
c1a9b12d 1725 assert_eq!(stderr, Vec::new());
85aaf69f
SL
1726 }
1727
85aaf69f 1728 #[test]
7453a54e 1729 #[cfg_attr(target_os = "android", ignore)]
85aaf69f
SL
1730 fn test_process_output_error() {
1731 let Output {status, stdout, stderr}
32a655c1
SL
1732 = if cfg!(target_os = "windows") {
1733 Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap()
1734 } else {
ff7c6d11 1735 Command::new("mkdir").arg("./").output().unwrap()
32a655c1 1736 };
85aaf69f
SL
1737
1738 assert!(status.code() == Some(1));
1739 assert_eq!(stdout, Vec::new());
1740 assert!(!stderr.is_empty());
1741 }
1742
85aaf69f 1743 #[test]
7453a54e 1744 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 1745 fn test_finish_once() {
32a655c1
SL
1746 let mut prog = if cfg!(target_os = "windows") {
1747 Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
1748 } else {
1749 Command::new("false").spawn().unwrap()
1750 };
85aaf69f
SL
1751 assert!(prog.wait().unwrap().code() == Some(1));
1752 }
1753
85aaf69f 1754 #[test]
7453a54e 1755 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 1756 fn test_finish_twice() {
32a655c1
SL
1757 let mut prog = if cfg!(target_os = "windows") {
1758 Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
1759 } else {
1760 Command::new("false").spawn().unwrap()
1761 };
85aaf69f
SL
1762 assert!(prog.wait().unwrap().code() == Some(1));
1763 assert!(prog.wait().unwrap().code() == Some(1));
1764 }
1765
85aaf69f 1766 #[test]
7453a54e 1767 #[cfg_attr(target_os = "android", ignore)]
85aaf69f 1768 fn test_wait_with_output_once() {
32a655c1
SL
1769 let prog = if cfg!(target_os = "windows") {
1770 Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap()
1771 } else {
1772 Command::new("echo").arg("hello").stdout(Stdio::piped()).spawn().unwrap()
1773 };
1774
85aaf69f 1775 let Output {status, stdout, stderr} = prog.wait_with_output().unwrap();
c34b1796 1776 let output_str = str::from_utf8(&stdout).unwrap();
85aaf69f
SL
1777
1778 assert!(status.success());
1779 assert_eq!(output_str.trim().to_string(), "hello");
c1a9b12d 1780 assert_eq!(stderr, Vec::new());
85aaf69f
SL
1781 }
1782
85aaf69f
SL
1783 #[cfg(all(unix, not(target_os="android")))]
1784 pub fn env_cmd() -> Command {
1785 Command::new("env")
1786 }
1787 #[cfg(target_os="android")]
1788 pub fn env_cmd() -> Command {
1789 let mut cmd = Command::new("/system/bin/sh");
1790 cmd.arg("-c").arg("set");
1791 cmd
1792 }
1793
1794 #[cfg(windows)]
1795 pub fn env_cmd() -> Command {
1796 let mut cmd = Command::new("cmd");
1797 cmd.arg("/c").arg("set");
1798 cmd
1799 }
1800
85aaf69f
SL
1801 #[test]
1802 fn test_inherit_env() {
c1a9b12d 1803 use env;
85aaf69f
SL
1804
1805 let result = env_cmd().output().unwrap();
1806 let output = String::from_utf8(result.stdout).unwrap();
1807
c34b1796 1808 for (ref k, ref v) in env::vars() {
3b2f2976
XL
1809 // Don't check android RANDOM variable which seems to change
1810 // whenever the shell runs, and our `env_cmd` is indeed running a
1811 // shell which means it'll get a different RANDOM than we probably
1812 // have.
1813 //
1814 // Also skip env vars with `-` in the name on android because, well,
1815 // I'm not sure. It appears though that the `set` command above does
1816 // not print env vars with `-` in the name, so we just skip them
1817 // here as we won't find them in the output. Note that most env vars
1818 // use `_` instead of `-`, but our build system sets a few env vars
1819 // with `-` in the name.
1820 if cfg!(target_os = "android") &&
1821 (*k == "RANDOM" || k.contains("-")) {
7453a54e
SL
1822 continue
1823 }
1824
92a42be0
SL
1825 // Windows has hidden environment variables whose names start with
1826 // equals signs (`=`). Those do not show up in the output of the
1827 // `set` command.
1828 assert!((cfg!(windows) && k.starts_with("=")) ||
1829 k.starts_with("DYLD") ||
7453a54e
SL
1830 output.contains(&format!("{}={}", *k, *v)) ||
1831 output.contains(&format!("{}='{}'", *k, *v)),
85aaf69f
SL
1832 "output doesn't contain `{}={}`\n{}",
1833 k, v, output);
1834 }
1835 }
85aaf69f
SL
1836
1837 #[test]
1838 fn test_override_env() {
1839 use env;
1840
1841 // In some build environments (such as chrooted Nix builds), `env` can
1842 // only be found in the explicitly-provided PATH env variable, not in
1843 // default places such as /bin or /usr/bin. So we need to pass through
1844 // PATH to our sub-process.
1845 let mut cmd = env_cmd();
1846 cmd.env_clear().env("RUN_TEST_NEW_ENV", "123");
1847 if let Some(p) = env::var_os("PATH") {
1848 cmd.env("PATH", &p);
1849 }
1850 let result = cmd.output().unwrap();
c34b1796 1851 let output = String::from_utf8_lossy(&result.stdout).to_string();
85aaf69f
SL
1852
1853 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1854 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1855 }
1856
1857 #[test]
1858 fn test_add_to_env() {
1859 let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
c34b1796 1860 let output = String::from_utf8_lossy(&result.stdout).to_string();
85aaf69f
SL
1861
1862 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1863 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1864 }
7453a54e 1865
ff7c6d11
XL
1866 #[test]
1867 fn test_capture_env_at_spawn() {
1868 use env;
1869
1870 let mut cmd = env_cmd();
1871 cmd.env("RUN_TEST_NEW_ENV1", "123");
1872
1873 // This variable will not be present if the environment has already
1874 // been captured above.
1875 env::set_var("RUN_TEST_NEW_ENV2", "456");
1876 let result = cmd.output().unwrap();
1877 env::remove_var("RUN_TEST_NEW_ENV2");
1878
1879 let output = String::from_utf8_lossy(&result.stdout).to_string();
1880
1881 assert!(output.contains("RUN_TEST_NEW_ENV1=123"),
1882 "didn't find RUN_TEST_NEW_ENV1 inside of:\n\n{}", output);
1883 assert!(output.contains("RUN_TEST_NEW_ENV2=456"),
1884 "didn't find RUN_TEST_NEW_ENV2 inside of:\n\n{}", output);
1885 }
1886
7453a54e
SL
1887 // Regression tests for #30858.
1888 #[test]
1889 fn test_interior_nul_in_progname_is_error() {
1890 match Command::new("has-some-\0\0s-inside").spawn() {
1891 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1892 Ok(_) => panic!(),
1893 }
1894 }
1895
1896 #[test]
1897 fn test_interior_nul_in_arg_is_error() {
1898 match Command::new("echo").arg("has-some-\0\0s-inside").spawn() {
1899 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1900 Ok(_) => panic!(),
1901 }
1902 }
1903
1904 #[test]
1905 fn test_interior_nul_in_args_is_error() {
1906 match Command::new("echo").args(&["has-some-\0\0s-inside"]).spawn() {
1907 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1908 Ok(_) => panic!(),
1909 }
1910 }
1911
1912 #[test]
1913 fn test_interior_nul_in_current_dir_is_error() {
1914 match Command::new("echo").current_dir("has-some-\0\0s-inside").spawn() {
1915 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1916 Ok(_) => panic!(),
1917 }
1918 }
1919
1920 // Regression tests for #30862.
1921 #[test]
1922 fn test_interior_nul_in_env_key_is_error() {
1923 match env_cmd().env("has-some-\0\0s-inside", "value").spawn() {
1924 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1925 Ok(_) => panic!(),
1926 }
1927 }
1928
1929 #[test]
1930 fn test_interior_nul_in_env_value_is_error() {
1931 match env_cmd().env("key", "has-some-\0\0s-inside").spawn() {
1932 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1933 Ok(_) => panic!(),
1934 }
1935 }
476ff2be
SL
1936
1937 /// Test that process creation flags work by debugging a process.
1938 /// Other creation flags make it hard or impossible to detect
1939 /// behavioral changes in the process.
1940 #[test]
1941 #[cfg(windows)]
1942 fn test_creation_flags() {
1943 use os::windows::process::CommandExt;
1944 use sys::c::{BOOL, DWORD, INFINITE};
1945 #[repr(C, packed)]
1946 struct DEBUG_EVENT {
1947 pub event_code: DWORD,
1948 pub process_id: DWORD,
1949 pub thread_id: DWORD,
1950 // This is a union in the real struct, but we don't
1951 // need this data for the purposes of this test.
1952 pub _junk: [u8; 164],
1953 }
1954
1955 extern "system" {
1956 fn WaitForDebugEvent(lpDebugEvent: *mut DEBUG_EVENT, dwMilliseconds: DWORD) -> BOOL;
1957 fn ContinueDebugEvent(dwProcessId: DWORD, dwThreadId: DWORD,
1958 dwContinueStatus: DWORD) -> BOOL;
1959 }
1960
1961 const DEBUG_PROCESS: DWORD = 1;
1962 const EXIT_PROCESS_DEBUG_EVENT: DWORD = 5;
1963 const DBG_EXCEPTION_NOT_HANDLED: DWORD = 0x80010001;
1964
1965 let mut child = Command::new("cmd")
1966 .creation_flags(DEBUG_PROCESS)
1967 .stdin(Stdio::piped()).spawn().unwrap();
1968 child.stdin.take().unwrap().write_all(b"exit\r\n").unwrap();
1969 let mut events = 0;
1970 let mut event = DEBUG_EVENT {
1971 event_code: 0,
1972 process_id: 0,
1973 thread_id: 0,
1974 _junk: [0; 164],
1975 };
1976 loop {
1977 if unsafe { WaitForDebugEvent(&mut event as *mut DEBUG_EVENT, INFINITE) } == 0 {
1978 panic!("WaitForDebugEvent failed!");
1979 }
1980 events += 1;
1981
1982 if event.event_code == EXIT_PROCESS_DEBUG_EVENT {
1983 break;
1984 }
1985
1986 if unsafe { ContinueDebugEvent(event.process_id,
1987 event.thread_id,
1988 DBG_EXCEPTION_NOT_HANDLED) } == 0 {
1989 panic!("ContinueDebugEvent failed!");
1990 }
1991 }
1992 assert!(events > 0);
1993 }
2c00a5a8
XL
1994
1995 #[test]
1996 fn test_command_implements_send() {
1997 fn take_send_type<T: Send>(_: T) {}
1998 take_send_type(Command::new(""))
1999 }
85aaf69f 2000}