1 //! Execution of and interaction with external processes and pipelines.
2 //!
3 //! The entry points to the crate are the [`Popen`] struct and the [`Exec`]
4 //! builder.  `Popen` is the interface to a running child process, inspired by
5 //! Python's [`subprocess.Popen`].  `Exec` provides a builder-pattern API with
6 //! convenient methods for streaming and capturing of output, as well as
7 //! combining `Popen` instances into pipelines.
8 //!
9 //! Compared to `std::process`, the module follows the following
10 //! additional features:
11 //!
12 //! * The *communicate* [family of methods] for deadlock-free capturing of
13 //!   subprocess output/error, while simultaneously feeding data to its
14 //!   standard input.  Capturing supports optional timeout and read size
15 //!   limit.
16 //!
17 //! * Connecting multiple commands into OS-level [pipelines].
18 //!
19 //! * Flexible [redirection options], such as connecting standard
20 //!   streams to arbitary [open files], or [merging] output streams
21 //!   like shell's `2>&1` and `1>&2` operators.
22 //!
23 //! * Non-blocking and timeout methods to wait on the process:
24 //!   [`poll`], [`wait`], and [`wait_timeout`].
25 //!
26 //! # Examples
27 //!
28 //! Communicate with a process and optionally terminate it:
29 //!
30 //! ```
31 //! # use subprocess::*;
32 //! # fn dummy() -> Result<()> {
33 //! let mut p = Popen::create(&["ps", "x"], PopenConfig {
34 //!     stdout: Redirection::Pipe, ..Default::default()
35 //! })?;
36 //!
37 //! // Obtain the output from the standard streams.
38 //! let (out, err) = p.communicate(None)?;
39 //!
40 //! if let Some(exit_status) = p.poll() {
41 //!     // the process has finished
42 //! } else {
43 //!     // it is still running, terminate it
44 //!     p.terminate()?;
45 //! }
46 //! # Ok(())
47 //! # }
48 //! ```
49 //!
50 //! Use the [`Exec`] builder to execute a pipeline of commands and
51 //! capture the output:
52 //!
53 //! ```no_run
54 //! # use subprocess::*;
55 //! # fn dummy() -> Result<()> {
56 //! let dir_checksum = {
57 //!     Exec::shell("find . -type f") | Exec::cmd("sort") | Exec::cmd("sha1sum")
58 //! }.capture()?.stdout_str();
59 //! # Ok(())
60 //! # }
61 //! ```
62 //!
63 //! [`Popen`]: struct.Popen.html
64 //! [`Exec`]: struct.Exec.html
65 //! [family of methods]: struct.Popen.html#method.communicate_start
66 //! [redirection options]: enum.Redirection.html
67 //! [open files]: enum.Redirection.html#variant.File
68 //! [merging]: enum.Redirection.html#variant.Merge
69 //! [`poll`]: struct.Popen.html#method.poll
70 //! [`wait`]: struct.Popen.html#method.wait
71 //! [`wait_timeout`]: struct.Popen.html#method.wait_timeout
72 //! [`subprocess.Popen`]: https://docs.python.org/3/library/subprocess.html#subprocess.Popen
73 //! [pipelines]: struct.Pipeline.html
74 
75 #![warn(missing_debug_implementations, rust_2018_idioms, missing_docs)]
76 #![allow(clippy::type_complexity, clippy::single_match)]
77 
78 mod builder;
79 mod communicate;
80 mod popen;
81 
82 #[cfg(unix)]
83 mod posix;
84 
85 #[cfg(windows)]
86 mod win32;
87 
88 mod os_common;
89 
90 pub use self::builder::{CaptureData, Exec, NullFile, Pipeline};
91 pub use self::communicate::{CommunicateError, Communicator};
92 pub use self::os_common::ExitStatus;
93 pub use self::popen::{make_pipe, Popen, PopenConfig, PopenError, Redirection, Result};
94 
95 /// Subprocess extensions for Unix platforms.
96 pub mod unix {
97     pub use super::popen::os_ext::*;
98 }
99 
100 #[cfg(test)]
101 mod tests {
102     mod builder;
103     mod common;
104     #[cfg(unix)]
105     mod posix;
106     #[cfg(windows)]
107     mod win32;
108 }
109