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