]>
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 | //! | |
6a06907d XL |
74 | //! // If the child process fills its stdout buffer, it may end up |
75 | //! // waiting until the parent reads the stdout, and not be able to | |
76 | //! // read stdin in the meantime, causing a deadlock. | |
77 | //! // Writing from another thread ensures that stdout is being read | |
78 | //! // at the same time, avoiding the problem. | |
79 | //! let mut stdin = child.stdin.take().expect("failed to get stdin"); | |
80 | //! std::thread::spawn(move || { | |
8bb4bdeb | 81 | //! stdin.write_all(b"test").expect("failed to write to stdin"); |
6a06907d | 82 | //! }); |
8bb4bdeb XL |
83 | //! |
84 | //! let output = child | |
85 | //! .wait_with_output() | |
86 | //! .expect("failed to wait on child"); | |
87 | //! | |
88 | //! assert_eq!(b"test", output.stdout.as_slice()); | |
89 | //! ``` | |
abe05a73 | 90 | //! |
3dfed10e XL |
91 | //! [`spawn`]: Command::spawn |
92 | //! [`output`]: Command::output | |
abe05a73 | 93 | //! |
3dfed10e XL |
94 | //! [`stdout`]: Command::stdout |
95 | //! [`stdin`]: Command::stdin | |
96 | //! [`stderr`]: Command::stderr | |
abe05a73 | 97 | //! |
3dfed10e XL |
98 | //! [`Write`]: io::Write |
99 | //! [`Read`]: io::Read | |
85aaf69f | 100 | |
c34b1796 | 101 | #![stable(feature = "process", since = "1.0.0")] |
1b1a35ee XL |
102 | #![deny(unsafe_op_in_unsafe_fn)] |
103 | ||
fc512014 | 104 | #[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))] |
1b1a35ee | 105 | mod tests; |
85aaf69f | 106 | |
532ac7d7 | 107 | use crate::io::prelude::*; |
85aaf69f | 108 | |
3c0e092e | 109 | use crate::convert::Infallible; |
532ac7d7 XL |
110 | use crate::ffi::OsStr; |
111 | use crate::fmt; | |
112 | use crate::fs; | |
a2a8927a | 113 | use crate::io::{self, IoSlice, IoSliceMut}; |
17df50a5 | 114 | use crate::num::NonZeroI32; |
532ac7d7 XL |
115 | use crate::path::Path; |
116 | use crate::str; | |
117 | use crate::sys::pipe::{read2, AnonPipe}; | |
118 | use crate::sys::process as imp; | |
c295e0f8 | 119 | #[stable(feature = "command_access", since = "1.57.0")] |
1b1a35ee | 120 | pub use crate::sys_common::process::CommandEnvs; |
532ac7d7 | 121 | use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; |
85aaf69f SL |
122 | |
123 | /// Representation of a running or exited child process. | |
124 | /// | |
125 | /// This structure is used to represent and manage child processes. A child | |
5bcae85e SL |
126 | /// process is created via the [`Command`] struct, which configures the |
127 | /// spawning process and can itself be constructed using a builder-style | |
128 | /// interface. | |
85aaf69f | 129 | /// |
cc61c64b XL |
130 | /// There is no implementation of [`Drop`] for child processes, |
131 | /// so if you do not ensure the `Child` has exited then it will continue to | |
132 | /// run, even after the `Child` handle to the child process has gone out of | |
133 | /// scope. | |
134 | /// | |
3dfed10e | 135 | /// Calling [`wait`] (or other functions that wrap around it) will make |
cc61c64b XL |
136 | /// the parent process wait until the child has actually exited before |
137 | /// continuing. | |
138 | /// | |
48663c56 XL |
139 | /// # Warning |
140 | /// | |
3dfed10e | 141 | /// On some systems, calling [`wait`] or similar is necessary for the OS to |
48663c56 XL |
142 | /// release resources. A process that terminated but has not been waited on is |
143 | /// still around as a "zombie". Leaving too many zombies around may exhaust | |
144 | /// global resources (for example process IDs). | |
145 | /// | |
146 | /// The standard library does *not* automatically wait on child processes (not | |
147 | /// even if the `Child` is dropped), it is up to the application developer to do | |
148 | /// so. As a consequence, dropping `Child` handles without waiting on them first | |
149 | /// is not recommended in long-running applications. | |
150 | /// | |
c34b1796 | 151 | /// # Examples |
85aaf69f | 152 | /// |
c34b1796 | 153 | /// ```should_panic |
85aaf69f SL |
154 | /// use std::process::Command; |
155 | /// | |
bd371182 AL |
156 | /// let mut child = Command::new("/bin/cat") |
157 | /// .arg("file.txt") | |
158 | /// .spawn() | |
a7813a04 | 159 | /// .expect("failed to execute child"); |
bd371182 AL |
160 | /// |
161 | /// let ecode = child.wait() | |
a7813a04 | 162 | /// .expect("failed to wait on child"); |
bd371182 AL |
163 | /// |
164 | /// assert!(ecode.success()); | |
85aaf69f | 165 | /// ``` |
7453a54e | 166 | /// |
3dfed10e | 167 | /// [`wait`]: Child::wait |
c34b1796 | 168 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 169 | pub struct Child { |
94222f64 | 170 | pub(crate) handle: imp::Process, |
85aaf69f | 171 | |
ea8adc8c | 172 | /// The handle for writing to the child's standard input (stdin), if it has |
3dfed10e XL |
173 | /// been captured. To avoid partially moving |
174 | /// the `child` and thus blocking yourself from calling | |
175 | /// functions on `child` while using `stdin`, | |
176 | /// you might find it helpful: | |
177 | /// | |
178 | /// ```compile_fail,E0425 | |
179 | /// let stdin = child.stdin.take().unwrap(); | |
180 | /// ``` | |
c34b1796 | 181 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
182 | pub stdin: Option<ChildStdin>, |
183 | ||
ea8adc8c | 184 | /// The handle for reading from the child's standard output (stdout), if it |
3dfed10e XL |
185 | /// has been captured. You might find it helpful to do |
186 | /// | |
187 | /// ```compile_fail,E0425 | |
188 | /// let stdout = child.stdout.take().unwrap(); | |
189 | /// ``` | |
190 | /// | |
191 | /// to avoid partially moving the `child` and thus blocking yourself from calling | |
192 | /// functions on `child` while using `stdout`. | |
c34b1796 | 193 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
194 | pub stdout: Option<ChildStdout>, |
195 | ||
ea8adc8c | 196 | /// The handle for reading from the child's standard error (stderr), if it |
3dfed10e XL |
197 | /// has been captured. You might find it helpful to do |
198 | /// | |
199 | /// ```compile_fail,E0425 | |
200 | /// let stderr = child.stderr.take().unwrap(); | |
201 | /// ``` | |
202 | /// | |
203 | /// to avoid partially moving the `child` and thus blocking yourself from calling | |
204 | /// functions on `child` while using `stderr`. | |
c34b1796 | 205 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
206 | pub stderr: Option<ChildStderr>, |
207 | } | |
208 | ||
94222f64 XL |
209 | /// Allows extension traits within `std`. |
210 | #[unstable(feature = "sealed", issue = "none")] | |
211 | impl crate::sealed::Sealed for Child {} | |
212 | ||
62682a34 | 213 | impl AsInner<imp::Process> for Child { |
60c5eb7d XL |
214 | fn as_inner(&self) -> &imp::Process { |
215 | &self.handle | |
216 | } | |
62682a34 SL |
217 | } |
218 | ||
7453a54e SL |
219 | impl FromInner<(imp::Process, imp::StdioPipes)> for Child { |
220 | fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child { | |
221 | Child { | |
3b2f2976 | 222 | handle, |
7453a54e SL |
223 | stdin: io.stdin.map(ChildStdin::from_inner), |
224 | stdout: io.stdout.map(ChildStdout::from_inner), | |
225 | stderr: io.stderr.map(ChildStderr::from_inner), | |
226 | } | |
227 | } | |
228 | } | |
229 | ||
c1a9b12d | 230 | impl IntoInner<imp::Process> for Child { |
60c5eb7d XL |
231 | fn into_inner(self) -> imp::Process { |
232 | self.handle | |
233 | } | |
c1a9b12d SL |
234 | } |
235 | ||
8bb4bdeb | 236 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 | 237 | impl fmt::Debug for Child { |
532ac7d7 | 238 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
32a655c1 SL |
239 | f.debug_struct("Child") |
240 | .field("stdin", &self.stdin) | |
241 | .field("stdout", &self.stdout) | |
242 | .field("stderr", &self.stderr) | |
cdc7bbd5 | 243 | .finish_non_exhaustive() |
32a655c1 SL |
244 | } |
245 | } | |
246 | ||
ea8adc8c | 247 | /// A handle to a child process's standard input (stdin). |
7cac9316 XL |
248 | /// |
249 | /// This struct is used in the [`stdin`] field on [`Child`]. | |
5bcae85e | 250 | /// |
ea8adc8c XL |
251 | /// When an instance of `ChildStdin` is [dropped], the `ChildStdin`'s underlying |
252 | /// file handle will be closed. If the child process was blocked on input prior | |
253 | /// to being dropped, it will become unblocked after dropping. | |
254 | /// | |
3dfed10e XL |
255 | /// [`stdin`]: Child::stdin |
256 | /// [dropped]: Drop | |
c34b1796 | 257 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 258 | pub struct ChildStdin { |
60c5eb7d | 259 | inner: AnonPipe, |
85aaf69f SL |
260 | } |
261 | ||
94222f64 XL |
262 | // In addition to the `impl`s here, `ChildStdin` also has `impl`s for |
263 | // `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and | |
264 | // `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and | |
265 | // `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and | |
266 | // `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows. | |
267 | ||
c34b1796 | 268 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 269 | impl Write for ChildStdin { |
1b1a35ee XL |
270 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
271 | (&*self).write(buf) | |
272 | } | |
273 | ||
274 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { | |
275 | (&*self).write_vectored(bufs) | |
276 | } | |
277 | ||
278 | fn is_write_vectored(&self) -> bool { | |
279 | io::Write::is_write_vectored(&&*self) | |
280 | } | |
281 | ||
282 | fn flush(&mut self) -> io::Result<()> { | |
283 | (&*self).flush() | |
284 | } | |
285 | } | |
286 | ||
287 | #[stable(feature = "write_mt", since = "1.48.0")] | |
288 | impl Write for &ChildStdin { | |
85aaf69f SL |
289 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
290 | self.inner.write(buf) | |
291 | } | |
292 | ||
48663c56 XL |
293 | fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
294 | self.inner.write_vectored(bufs) | |
295 | } | |
296 | ||
f9f354fc XL |
297 | fn is_write_vectored(&self) -> bool { |
298 | self.inner.is_write_vectored() | |
299 | } | |
300 | ||
85aaf69f SL |
301 | fn flush(&mut self) -> io::Result<()> { |
302 | Ok(()) | |
303 | } | |
304 | } | |
305 | ||
62682a34 | 306 | impl AsInner<AnonPipe> for ChildStdin { |
60c5eb7d XL |
307 | fn as_inner(&self) -> &AnonPipe { |
308 | &self.inner | |
309 | } | |
62682a34 SL |
310 | } |
311 | ||
c1a9b12d | 312 | impl IntoInner<AnonPipe> for ChildStdin { |
60c5eb7d XL |
313 | fn into_inner(self) -> AnonPipe { |
314 | self.inner | |
315 | } | |
c1a9b12d SL |
316 | } |
317 | ||
7453a54e SL |
318 | impl FromInner<AnonPipe> for ChildStdin { |
319 | fn from_inner(pipe: AnonPipe) -> ChildStdin { | |
320 | ChildStdin { inner: pipe } | |
321 | } | |
322 | } | |
323 | ||
8bb4bdeb | 324 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 | 325 | impl fmt::Debug for ChildStdin { |
532ac7d7 | 326 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
cdc7bbd5 | 327 | f.debug_struct("ChildStdin").finish_non_exhaustive() |
32a655c1 SL |
328 | } |
329 | } | |
330 | ||
ea8adc8c | 331 | /// A handle to a child process's standard output (stdout). |
7cac9316 XL |
332 | /// |
333 | /// This struct is used in the [`stdout`] field on [`Child`]. | |
5bcae85e | 334 | /// |
ea8adc8c XL |
335 | /// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s |
336 | /// underlying file handle will be closed. | |
337 | /// | |
3dfed10e XL |
338 | /// [`stdout`]: Child::stdout |
339 | /// [dropped]: Drop | |
c34b1796 | 340 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 341 | pub struct ChildStdout { |
60c5eb7d | 342 | inner: AnonPipe, |
85aaf69f SL |
343 | } |
344 | ||
94222f64 XL |
345 | // In addition to the `impl`s here, `ChildStdout` also has `impl`s for |
346 | // `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and | |
347 | // `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and | |
348 | // `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and | |
349 | // `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows. | |
350 | ||
c34b1796 | 351 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
352 | impl Read for ChildStdout { |
353 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
354 | self.inner.read(buf) | |
355 | } | |
48663c56 XL |
356 | |
357 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { | |
358 | self.inner.read_vectored(bufs) | |
359 | } | |
360 | ||
f9f354fc XL |
361 | #[inline] |
362 | fn is_read_vectored(&self) -> bool { | |
363 | self.inner.is_read_vectored() | |
364 | } | |
85aaf69f SL |
365 | } |
366 | ||
62682a34 | 367 | impl AsInner<AnonPipe> for ChildStdout { |
60c5eb7d XL |
368 | fn as_inner(&self) -> &AnonPipe { |
369 | &self.inner | |
370 | } | |
62682a34 SL |
371 | } |
372 | ||
c1a9b12d | 373 | impl IntoInner<AnonPipe> for ChildStdout { |
60c5eb7d XL |
374 | fn into_inner(self) -> AnonPipe { |
375 | self.inner | |
376 | } | |
c1a9b12d SL |
377 | } |
378 | ||
7453a54e SL |
379 | impl FromInner<AnonPipe> for ChildStdout { |
380 | fn from_inner(pipe: AnonPipe) -> ChildStdout { | |
381 | ChildStdout { inner: pipe } | |
382 | } | |
383 | } | |
384 | ||
8bb4bdeb | 385 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 | 386 | impl fmt::Debug for ChildStdout { |
532ac7d7 | 387 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
cdc7bbd5 | 388 | f.debug_struct("ChildStdout").finish_non_exhaustive() |
32a655c1 SL |
389 | } |
390 | } | |
391 | ||
cc61c64b XL |
392 | /// A handle to a child process's stderr. |
393 | /// | |
394 | /// This struct is used in the [`stderr`] field on [`Child`]. | |
5bcae85e | 395 | /// |
ea8adc8c XL |
396 | /// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s |
397 | /// underlying file handle will be closed. | |
398 | /// | |
3dfed10e XL |
399 | /// [`stderr`]: Child::stderr |
400 | /// [dropped]: Drop | |
c34b1796 | 401 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 402 | pub struct ChildStderr { |
60c5eb7d | 403 | inner: AnonPipe, |
85aaf69f SL |
404 | } |
405 | ||
94222f64 XL |
406 | // In addition to the `impl`s here, `ChildStderr` also has `impl`s for |
407 | // `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and | |
408 | // `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and | |
409 | // `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and | |
410 | // `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows. | |
411 | ||
c34b1796 | 412 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
413 | impl Read for ChildStderr { |
414 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
415 | self.inner.read(buf) | |
416 | } | |
48663c56 XL |
417 | |
418 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { | |
419 | self.inner.read_vectored(bufs) | |
420 | } | |
421 | ||
f9f354fc XL |
422 | #[inline] |
423 | fn is_read_vectored(&self) -> bool { | |
424 | self.inner.is_read_vectored() | |
425 | } | |
85aaf69f SL |
426 | } |
427 | ||
62682a34 | 428 | impl AsInner<AnonPipe> for ChildStderr { |
60c5eb7d XL |
429 | fn as_inner(&self) -> &AnonPipe { |
430 | &self.inner | |
431 | } | |
62682a34 SL |
432 | } |
433 | ||
c1a9b12d | 434 | impl IntoInner<AnonPipe> for ChildStderr { |
60c5eb7d XL |
435 | fn into_inner(self) -> AnonPipe { |
436 | self.inner | |
437 | } | |
c1a9b12d SL |
438 | } |
439 | ||
7453a54e SL |
440 | impl FromInner<AnonPipe> for ChildStderr { |
441 | fn from_inner(pipe: AnonPipe) -> ChildStderr { | |
442 | ChildStderr { inner: pipe } | |
443 | } | |
444 | } | |
445 | ||
8bb4bdeb | 446 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 | 447 | impl fmt::Debug for ChildStderr { |
532ac7d7 | 448 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
cdc7bbd5 | 449 | f.debug_struct("ChildStderr").finish_non_exhaustive() |
32a655c1 SL |
450 | } |
451 | } | |
452 | ||
3157f602 XL |
453 | /// A process builder, providing fine-grained control |
454 | /// over how a new process should be spawned. | |
455 | /// | |
456 | /// A default configuration can be | |
85aaf69f SL |
457 | /// generated using `Command::new(program)`, where `program` gives a path to the |
458 | /// program to be executed. Additional builder methods allow the configuration | |
459 | /// to be changed (for example, by adding arguments) prior to spawning: | |
460 | /// | |
461 | /// ``` | |
85aaf69f SL |
462 | /// use std::process::Command; |
463 | /// | |
32a655c1 SL |
464 | /// let output = if cfg!(target_os = "windows") { |
465 | /// Command::new("cmd") | |
136023e0 | 466 | /// .args(["/C", "echo hello"]) |
32a655c1 SL |
467 | /// .output() |
468 | /// .expect("failed to execute process") | |
469 | /// } else { | |
470 | /// Command::new("sh") | |
471 | /// .arg("-c") | |
472 | /// .arg("echo hello") | |
473 | /// .output() | |
474 | /// .expect("failed to execute process") | |
475 | /// }; | |
a7813a04 | 476 | /// |
85aaf69f SL |
477 | /// let hello = output.stdout; |
478 | /// ``` | |
b7449926 XL |
479 | /// |
480 | /// `Command` can be reused to spawn multiple processes. The builder methods | |
481 | /// change the command without needing to immediately spawn the process. | |
482 | /// | |
483 | /// ```no_run | |
484 | /// use std::process::Command; | |
485 | /// | |
486 | /// let mut echo_hello = Command::new("sh"); | |
487 | /// echo_hello.arg("-c") | |
488 | /// .arg("echo hello"); | |
489 | /// let hello_1 = echo_hello.output().expect("failed to execute process"); | |
490 | /// let hello_2 = echo_hello.output().expect("failed to execute process"); | |
491 | /// ``` | |
492 | /// | |
493 | /// Similarly, you can call builder methods after spawning a process and then | |
494 | /// spawn a new process with the modified settings. | |
495 | /// | |
496 | /// ```no_run | |
497 | /// use std::process::Command; | |
498 | /// | |
499 | /// let mut list_dir = Command::new("ls"); | |
500 | /// | |
501 | /// // Execute `ls` in the current directory of the program. | |
502 | /// list_dir.status().expect("process failed to execute"); | |
503 | /// | |
e1599b0c | 504 | /// println!(); |
b7449926 XL |
505 | /// |
506 | /// // Change `ls` to execute in the root directory. | |
507 | /// list_dir.current_dir("/"); | |
508 | /// | |
509 | /// // And then execute `ls` again but in the root directory. | |
510 | /// list_dir.status().expect("process failed to execute"); | |
511 | /// ``` | |
c34b1796 | 512 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 513 | pub struct Command { |
62682a34 | 514 | inner: imp::Command, |
85aaf69f SL |
515 | } |
516 | ||
6a06907d XL |
517 | /// Allows extension traits within `std`. |
518 | #[unstable(feature = "sealed", issue = "none")] | |
519 | impl crate::sealed::Sealed for Command {} | |
520 | ||
85aaf69f SL |
521 | impl Command { |
522 | /// Constructs a new `Command` for launching the program at | |
523 | /// path `program`, with the following default configuration: | |
524 | /// | |
525 | /// * No arguments to the program | |
526 | /// * Inherit the current process's environment | |
527 | /// * Inherit the current process's working directory | |
5e7ed085 FG |
528 | /// * Inherit stdin/stdout/stderr for [`spawn`] or [`status`], but create pipes for [`output`] |
529 | /// | |
530 | /// [`spawn`]: Self::spawn | |
531 | /// [`status`]: Self::status | |
532 | /// [`output`]: Self::output | |
85aaf69f SL |
533 | /// |
534 | /// Builder methods are provided to change these defaults and | |
535 | /// otherwise configure the process. | |
a7813a04 | 536 | /// |
476ff2be SL |
537 | /// If `program` is not an absolute path, the `PATH` will be searched in |
538 | /// an OS-defined way. | |
539 | /// | |
540 | /// The search path to be used may be controlled by setting the | |
541 | /// `PATH` environment variable on the Command, | |
542 | /// but this has some implementation limitations on Windows | |
9fa01778 | 543 | /// (see issue #37519). |
476ff2be | 544 | /// |
a7813a04 XL |
545 | /// # Examples |
546 | /// | |
547 | /// Basic usage: | |
548 | /// | |
549 | /// ```no_run | |
550 | /// use std::process::Command; | |
551 | /// | |
552 | /// Command::new("sh") | |
553 | /// .spawn() | |
554 | /// .expect("sh command failed to start"); | |
555 | /// ``` | |
c34b1796 AL |
556 | #[stable(feature = "process", since = "1.0.0")] |
557 | pub fn new<S: AsRef<OsStr>>(program: S) -> Command { | |
7453a54e | 558 | Command { inner: imp::Command::new(program.as_ref()) } |
85aaf69f SL |
559 | } |
560 | ||
9fa01778 | 561 | /// Adds an argument to pass to the program. |
a7813a04 | 562 | /// |
cc61c64b XL |
563 | /// Only one argument can be passed per use. So instead of: |
564 | /// | |
041b39d2 XL |
565 | /// ```no_run |
566 | /// # std::process::Command::new("sh") | |
cc61c64b | 567 | /// .arg("-C /path/to/repo") |
041b39d2 | 568 | /// # ; |
cc61c64b XL |
569 | /// ``` |
570 | /// | |
571 | /// usage would be: | |
572 | /// | |
041b39d2 XL |
573 | /// ```no_run |
574 | /// # std::process::Command::new("sh") | |
cc61c64b XL |
575 | /// .arg("-C") |
576 | /// .arg("/path/to/repo") | |
041b39d2 | 577 | /// # ; |
cc61c64b XL |
578 | /// ``` |
579 | /// | |
580 | /// To pass multiple arguments see [`args`]. | |
581 | /// | |
3dfed10e | 582 | /// [`args`]: Command::args |
cc61c64b | 583 | /// |
29967ef6 XL |
584 | /// Note that the argument is not passed through a shell, but given |
585 | /// literally to the program. This means that shell syntax like quotes, | |
586 | /// escaped characters, word splitting, glob patterns, substitution, etc. | |
587 | /// have no effect. | |
588 | /// | |
a7813a04 XL |
589 | /// # Examples |
590 | /// | |
591 | /// Basic usage: | |
592 | /// | |
593 | /// ```no_run | |
594 | /// use std::process::Command; | |
595 | /// | |
596 | /// Command::new("ls") | |
597 | /// .arg("-l") | |
598 | /// .arg("-a") | |
599 | /// .spawn() | |
600 | /// .expect("ls command failed to start"); | |
601 | /// ``` | |
c34b1796 AL |
602 | #[stable(feature = "process", since = "1.0.0")] |
603 | pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command { | |
604 | self.inner.arg(arg.as_ref()); | |
85aaf69f SL |
605 | self |
606 | } | |
607 | ||
9fa01778 | 608 | /// Adds multiple arguments to pass to the program. |
a7813a04 | 609 | /// |
cc61c64b XL |
610 | /// To pass a single argument see [`arg`]. |
611 | /// | |
3dfed10e | 612 | /// [`arg`]: Command::arg |
cc61c64b | 613 | /// |
29967ef6 XL |
614 | /// Note that the arguments are not passed through a shell, but given |
615 | /// literally to the program. This means that shell syntax like quotes, | |
616 | /// escaped characters, word splitting, glob patterns, substitution, etc. | |
617 | /// have no effect. | |
618 | /// | |
a7813a04 XL |
619 | /// # Examples |
620 | /// | |
621 | /// Basic usage: | |
622 | /// | |
623 | /// ```no_run | |
624 | /// use std::process::Command; | |
625 | /// | |
626 | /// Command::new("ls") | |
136023e0 | 627 | /// .args(["-l", "-a"]) |
a7813a04 XL |
628 | /// .spawn() |
629 | /// .expect("ls command failed to start"); | |
630 | /// ``` | |
c34b1796 | 631 | #[stable(feature = "process", since = "1.0.0")] |
32a655c1 | 632 | pub fn args<I, S>(&mut self, args: I) -> &mut Command |
60c5eb7d XL |
633 | where |
634 | I: IntoIterator<Item = S>, | |
635 | S: AsRef<OsStr>, | |
32a655c1 | 636 | { |
7453a54e SL |
637 | for arg in args { |
638 | self.arg(arg.as_ref()); | |
639 | } | |
85aaf69f SL |
640 | self |
641 | } | |
642 | ||
643 | /// Inserts or updates an environment variable mapping. | |
644 | /// | |
645 | /// Note that environment variable names are case-insensitive (but case-preserving) on Windows, | |
646 | /// and case-sensitive on all other platforms. | |
a7813a04 XL |
647 | /// |
648 | /// # Examples | |
649 | /// | |
650 | /// Basic usage: | |
651 | /// | |
652 | /// ```no_run | |
653 | /// use std::process::Command; | |
654 | /// | |
655 | /// Command::new("ls") | |
656 | /// .env("PATH", "/bin") | |
657 | /// .spawn() | |
658 | /// .expect("ls command failed to start"); | |
659 | /// ``` | |
c34b1796 AL |
660 | #[stable(feature = "process", since = "1.0.0")] |
661 | pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command | |
60c5eb7d XL |
662 | where |
663 | K: AsRef<OsStr>, | |
664 | V: AsRef<OsStr>, | |
85aaf69f | 665 | { |
ff7c6d11 | 666 | self.inner.env_mut().set(key.as_ref(), val.as_ref()); |
85aaf69f SL |
667 | self |
668 | } | |
669 | ||
9fa01778 | 670 | /// Adds or updates multiple environment variable mappings. |
32a655c1 SL |
671 | /// |
672 | /// # Examples | |
673 | /// | |
674 | /// Basic usage: | |
cc61c64b | 675 | /// |
32a655c1 SL |
676 | /// ```no_run |
677 | /// use std::process::{Command, Stdio}; | |
678 | /// use std::env; | |
679 | /// use std::collections::HashMap; | |
680 | /// | |
681 | /// let filtered_env : HashMap<String, String> = | |
682 | /// env::vars().filter(|&(ref k, _)| | |
683 | /// k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH" | |
684 | /// ).collect(); | |
685 | /// | |
686 | /// Command::new("printenv") | |
687 | /// .stdin(Stdio::null()) | |
688 | /// .stdout(Stdio::inherit()) | |
689 | /// .env_clear() | |
690 | /// .envs(&filtered_env) | |
691 | /// .spawn() | |
692 | /// .expect("printenv failed to start"); | |
693 | /// ``` | |
7cac9316 | 694 | #[stable(feature = "command_envs", since = "1.19.0")] |
32a655c1 | 695 | pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command |
60c5eb7d XL |
696 | where |
697 | I: IntoIterator<Item = (K, V)>, | |
698 | K: AsRef<OsStr>, | |
699 | V: AsRef<OsStr>, | |
32a655c1 SL |
700 | { |
701 | for (ref key, ref val) in vars { | |
ff7c6d11 | 702 | self.inner.env_mut().set(key.as_ref(), val.as_ref()); |
32a655c1 SL |
703 | } |
704 | self | |
705 | } | |
706 | ||
85aaf69f | 707 | /// Removes an environment variable mapping. |
a7813a04 XL |
708 | /// |
709 | /// # Examples | |
710 | /// | |
711 | /// Basic usage: | |
712 | /// | |
713 | /// ```no_run | |
714 | /// use std::process::Command; | |
715 | /// | |
716 | /// Command::new("ls") | |
717 | /// .env_remove("PATH") | |
718 | /// .spawn() | |
719 | /// .expect("ls command failed to start"); | |
720 | /// ``` | |
c34b1796 AL |
721 | #[stable(feature = "process", since = "1.0.0")] |
722 | pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command { | |
ff7c6d11 | 723 | self.inner.env_mut().remove(key.as_ref()); |
85aaf69f SL |
724 | self |
725 | } | |
726 | ||
727 | /// Clears the entire environment map for the child process. | |
a7813a04 XL |
728 | /// |
729 | /// # Examples | |
730 | /// | |
731 | /// Basic usage: | |
732 | /// | |
733 | /// ```no_run | |
734 | /// use std::process::Command; | |
735 | /// | |
736 | /// Command::new("ls") | |
737 | /// .env_clear() | |
738 | /// .spawn() | |
739 | /// .expect("ls command failed to start"); | |
740 | /// ``` | |
c34b1796 | 741 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 742 | pub fn env_clear(&mut self) -> &mut Command { |
ff7c6d11 | 743 | self.inner.env_mut().clear(); |
85aaf69f SL |
744 | self |
745 | } | |
746 | ||
9346a6ac | 747 | /// Sets the working directory for the child process. |
a7813a04 | 748 | /// |
b7449926 XL |
749 | /// # Platform-specific behavior |
750 | /// | |
0731742a | 751 | /// If the program path is relative (e.g., `"./script.sh"`), it's ambiguous |
b7449926 XL |
752 | /// whether it should be interpreted relative to the parent's working |
753 | /// directory or relative to `current_dir`. The behavior in this case is | |
754 | /// platform specific and unstable, and it's recommended to use | |
755 | /// [`canonicalize`] to get an absolute program path instead. | |
756 | /// | |
a7813a04 XL |
757 | /// # Examples |
758 | /// | |
759 | /// Basic usage: | |
760 | /// | |
761 | /// ```no_run | |
762 | /// use std::process::Command; | |
763 | /// | |
764 | /// Command::new("ls") | |
765 | /// .current_dir("/bin") | |
766 | /// .spawn() | |
767 | /// .expect("ls command failed to start"); | |
768 | /// ``` | |
b7449926 | 769 | /// |
3dfed10e | 770 | /// [`canonicalize`]: crate::fs::canonicalize |
c34b1796 | 771 | #[stable(feature = "process", since = "1.0.0")] |
7453a54e | 772 | pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command { |
c34b1796 | 773 | self.inner.cwd(dir.as_ref().as_ref()); |
85aaf69f SL |
774 | self |
775 | } | |
776 | ||
ea8adc8c | 777 | /// Configuration for the child process's standard input (stdin) handle. |
a7813a04 | 778 | /// |
5e7ed085 FG |
779 | /// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and |
780 | /// defaults to [`piped`] when used with [`output`]. | |
abe05a73 | 781 | /// |
3dfed10e XL |
782 | /// [`inherit`]: Stdio::inherit |
783 | /// [`piped`]: Stdio::piped | |
5e7ed085 FG |
784 | /// [`spawn`]: Self::spawn |
785 | /// [`status`]: Self::status | |
786 | /// [`output`]: Self::output | |
abe05a73 | 787 | /// |
a7813a04 XL |
788 | /// # Examples |
789 | /// | |
790 | /// Basic usage: | |
791 | /// | |
792 | /// ```no_run | |
793 | /// use std::process::{Command, Stdio}; | |
794 | /// | |
795 | /// Command::new("ls") | |
796 | /// .stdin(Stdio::null()) | |
797 | /// .spawn() | |
798 | /// .expect("ls command failed to start"); | |
799 | /// ``` | |
c34b1796 | 800 | #[stable(feature = "process", since = "1.0.0")] |
041b39d2 XL |
801 | pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command { |
802 | self.inner.stdin(cfg.into().0); | |
85aaf69f SL |
803 | self |
804 | } | |
805 | ||
ea8adc8c | 806 | /// Configuration for the child process's standard output (stdout) handle. |
a7813a04 | 807 | /// |
5e7ed085 FG |
808 | /// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and |
809 | /// defaults to [`piped`] when used with [`output`]. | |
abe05a73 | 810 | /// |
3dfed10e XL |
811 | /// [`inherit`]: Stdio::inherit |
812 | /// [`piped`]: Stdio::piped | |
5e7ed085 FG |
813 | /// [`spawn`]: Self::spawn |
814 | /// [`status`]: Self::status | |
815 | /// [`output`]: Self::output | |
abe05a73 | 816 | /// |
a7813a04 XL |
817 | /// # Examples |
818 | /// | |
819 | /// Basic usage: | |
820 | /// | |
821 | /// ```no_run | |
822 | /// use std::process::{Command, Stdio}; | |
823 | /// | |
824 | /// Command::new("ls") | |
825 | /// .stdout(Stdio::null()) | |
826 | /// .spawn() | |
827 | /// .expect("ls command failed to start"); | |
828 | /// ``` | |
c34b1796 | 829 | #[stable(feature = "process", since = "1.0.0")] |
041b39d2 XL |
830 | pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command { |
831 | self.inner.stdout(cfg.into().0); | |
85aaf69f SL |
832 | self |
833 | } | |
834 | ||
ea8adc8c | 835 | /// Configuration for the child process's standard error (stderr) handle. |
a7813a04 | 836 | /// |
5e7ed085 FG |
837 | /// Defaults to [`inherit`] when used with [`spawn`] or [`status`], and |
838 | /// defaults to [`piped`] when used with [`output`]. | |
abe05a73 | 839 | /// |
3dfed10e XL |
840 | /// [`inherit`]: Stdio::inherit |
841 | /// [`piped`]: Stdio::piped | |
5e7ed085 FG |
842 | /// [`spawn`]: Self::spawn |
843 | /// [`status`]: Self::status | |
844 | /// [`output`]: Self::output | |
abe05a73 | 845 | /// |
a7813a04 XL |
846 | /// # Examples |
847 | /// | |
848 | /// Basic usage: | |
849 | /// | |
850 | /// ```no_run | |
851 | /// use std::process::{Command, Stdio}; | |
852 | /// | |
853 | /// Command::new("ls") | |
854 | /// .stderr(Stdio::null()) | |
855 | /// .spawn() | |
856 | /// .expect("ls command failed to start"); | |
857 | /// ``` | |
c34b1796 | 858 | #[stable(feature = "process", since = "1.0.0")] |
041b39d2 XL |
859 | pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command { |
860 | self.inner.stderr(cfg.into().0); | |
85aaf69f SL |
861 | self |
862 | } | |
863 | ||
85aaf69f SL |
864 | /// Executes the command as a child process, returning a handle to it. |
865 | /// | |
62682a34 | 866 | /// By default, stdin, stdout and stderr are inherited from the parent. |
a7813a04 XL |
867 | /// |
868 | /// # Examples | |
869 | /// | |
870 | /// Basic usage: | |
871 | /// | |
872 | /// ```no_run | |
873 | /// use std::process::Command; | |
874 | /// | |
875 | /// Command::new("ls") | |
876 | /// .spawn() | |
877 | /// .expect("ls command failed to start"); | |
878 | /// ``` | |
c34b1796 | 879 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 880 | pub fn spawn(&mut self) -> io::Result<Child> { |
54a0048b | 881 | self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner) |
85aaf69f SL |
882 | } |
883 | ||
884 | /// Executes the command as a child process, waiting for it to finish and | |
885 | /// collecting all of its output. | |
886 | /// | |
ff7c6d11 XL |
887 | /// By default, stdout and stderr are captured (and used to provide the |
888 | /// resulting output). Stdin is not inherited from the parent and any | |
889 | /// attempt by the child process to read from the stdin stream will result | |
890 | /// in the stream immediately closing. | |
85aaf69f | 891 | /// |
c34b1796 | 892 | /// # Examples |
85aaf69f | 893 | /// |
a7813a04 | 894 | /// ```should_panic |
85aaf69f | 895 | /// use std::process::Command; |
a1dfa0c6 | 896 | /// use std::io::{self, Write}; |
a7813a04 XL |
897 | /// let output = Command::new("/bin/cat") |
898 | /// .arg("file.txt") | |
899 | /// .output() | |
900 | /// .expect("failed to execute process"); | |
85aaf69f SL |
901 | /// |
902 | /// println!("status: {}", output.status); | |
a1dfa0c6 XL |
903 | /// io::stdout().write_all(&output.stdout).unwrap(); |
904 | /// io::stderr().write_all(&output.stderr).unwrap(); | |
a7813a04 XL |
905 | /// |
906 | /// assert!(output.status.success()); | |
85aaf69f | 907 | /// ``` |
c34b1796 | 908 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 909 | pub fn output(&mut self) -> io::Result<Output> { |
60c5eb7d XL |
910 | self.inner |
911 | .spawn(imp::Stdio::MakePipe, false) | |
912 | .map(Child::from_inner) | |
7453a54e | 913 | .and_then(|p| p.wait_with_output()) |
85aaf69f SL |
914 | } |
915 | ||
916 | /// Executes a command as a child process, waiting for it to finish and | |
6a06907d | 917 | /// collecting its status. |
85aaf69f | 918 | /// |
62682a34 | 919 | /// By default, stdin, stdout and stderr are inherited from the parent. |
85aaf69f | 920 | /// |
c34b1796 | 921 | /// # Examples |
85aaf69f | 922 | /// |
a7813a04 | 923 | /// ```should_panic |
85aaf69f SL |
924 | /// use std::process::Command; |
925 | /// | |
a7813a04 XL |
926 | /// let status = Command::new("/bin/cat") |
927 | /// .arg("file.txt") | |
928 | /// .status() | |
929 | /// .expect("failed to execute process"); | |
85aaf69f | 930 | /// |
5e7ed085 | 931 | /// println!("process finished with: {status}"); |
a7813a04 XL |
932 | /// |
933 | /// assert!(status.success()); | |
85aaf69f | 934 | /// ``` |
c34b1796 | 935 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 936 | pub fn status(&mut self) -> io::Result<ExitStatus> { |
60c5eb7d XL |
937 | self.inner |
938 | .spawn(imp::Stdio::Inherit, true) | |
939 | .map(Child::from_inner) | |
940 | .and_then(|mut p| p.wait()) | |
85aaf69f | 941 | } |
1b1a35ee XL |
942 | |
943 | /// Returns the path to the program that was given to [`Command::new`]. | |
944 | /// | |
945 | /// # Examples | |
946 | /// | |
947 | /// ``` | |
1b1a35ee XL |
948 | /// use std::process::Command; |
949 | /// | |
950 | /// let cmd = Command::new("echo"); | |
951 | /// assert_eq!(cmd.get_program(), "echo"); | |
952 | /// ``` | |
3c0e092e | 953 | #[must_use] |
c295e0f8 | 954 | #[stable(feature = "command_access", since = "1.57.0")] |
1b1a35ee XL |
955 | pub fn get_program(&self) -> &OsStr { |
956 | self.inner.get_program() | |
957 | } | |
958 | ||
959 | /// Returns an iterator of the arguments that will be passed to the program. | |
960 | /// | |
961 | /// This does not include the path to the program as the first argument; | |
962 | /// it only includes the arguments specified with [`Command::arg`] and | |
963 | /// [`Command::args`]. | |
964 | /// | |
965 | /// # Examples | |
966 | /// | |
967 | /// ``` | |
1b1a35ee XL |
968 | /// use std::ffi::OsStr; |
969 | /// use std::process::Command; | |
970 | /// | |
971 | /// let mut cmd = Command::new("echo"); | |
972 | /// cmd.arg("first").arg("second"); | |
973 | /// let args: Vec<&OsStr> = cmd.get_args().collect(); | |
974 | /// assert_eq!(args, &["first", "second"]); | |
975 | /// ``` | |
c295e0f8 | 976 | #[stable(feature = "command_access", since = "1.57.0")] |
1b1a35ee XL |
977 | pub fn get_args(&self) -> CommandArgs<'_> { |
978 | CommandArgs { inner: self.inner.get_args() } | |
979 | } | |
980 | ||
981 | /// Returns an iterator of the environment variables that will be set when | |
982 | /// the process is spawned. | |
983 | /// | |
984 | /// Each element is a tuple `(&OsStr, Option<&OsStr>)`, where the first | |
985 | /// value is the key, and the second is the value, which is [`None`] if | |
986 | /// the environment variable is to be explicitly removed. | |
987 | /// | |
988 | /// This only includes environment variables explicitly set with | |
989 | /// [`Command::env`], [`Command::envs`], and [`Command::env_remove`]. It | |
990 | /// does not include environment variables that will be inherited by the | |
991 | /// child process. | |
992 | /// | |
993 | /// # Examples | |
994 | /// | |
995 | /// ``` | |
1b1a35ee XL |
996 | /// use std::ffi::OsStr; |
997 | /// use std::process::Command; | |
998 | /// | |
999 | /// let mut cmd = Command::new("ls"); | |
1000 | /// cmd.env("TERM", "dumb").env_remove("TZ"); | |
1001 | /// let envs: Vec<(&OsStr, Option<&OsStr>)> = cmd.get_envs().collect(); | |
1002 | /// assert_eq!(envs, &[ | |
1003 | /// (OsStr::new("TERM"), Some(OsStr::new("dumb"))), | |
1004 | /// (OsStr::new("TZ"), None) | |
1005 | /// ]); | |
1006 | /// ``` | |
c295e0f8 | 1007 | #[stable(feature = "command_access", since = "1.57.0")] |
1b1a35ee XL |
1008 | pub fn get_envs(&self) -> CommandEnvs<'_> { |
1009 | self.inner.get_envs() | |
1010 | } | |
1011 | ||
1012 | /// Returns the working directory for the child process. | |
1013 | /// | |
1014 | /// This returns [`None`] if the working directory will not be changed. | |
1015 | /// | |
1016 | /// # Examples | |
1017 | /// | |
1018 | /// ``` | |
1b1a35ee XL |
1019 | /// use std::path::Path; |
1020 | /// use std::process::Command; | |
1021 | /// | |
1022 | /// let mut cmd = Command::new("ls"); | |
1023 | /// assert_eq!(cmd.get_current_dir(), None); | |
1024 | /// cmd.current_dir("/bin"); | |
1025 | /// assert_eq!(cmd.get_current_dir(), Some(Path::new("/bin"))); | |
1026 | /// ``` | |
3c0e092e | 1027 | #[must_use] |
c295e0f8 | 1028 | #[stable(feature = "command_access", since = "1.57.0")] |
1b1a35ee XL |
1029 | pub fn get_current_dir(&self) -> Option<&Path> { |
1030 | self.inner.get_current_dir() | |
1031 | } | |
85aaf69f SL |
1032 | } |
1033 | ||
1034 | #[stable(feature = "rust1", since = "1.0.0")] | |
1035 | impl fmt::Debug for Command { | |
1036 | /// Format the program and arguments of a Command for display. Any | |
1037 | /// non-utf8 data is lossily converted using the utf8 replacement | |
1038 | /// character. | |
532ac7d7 | 1039 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
7453a54e | 1040 | self.inner.fmt(f) |
85aaf69f SL |
1041 | } |
1042 | } | |
1043 | ||
62682a34 | 1044 | impl AsInner<imp::Command> for Command { |
60c5eb7d XL |
1045 | fn as_inner(&self) -> &imp::Command { |
1046 | &self.inner | |
1047 | } | |
85aaf69f SL |
1048 | } |
1049 | ||
62682a34 | 1050 | impl AsInnerMut<imp::Command> for Command { |
60c5eb7d XL |
1051 | fn as_inner_mut(&mut self) -> &mut imp::Command { |
1052 | &mut self.inner | |
1053 | } | |
85aaf69f SL |
1054 | } |
1055 | ||
1b1a35ee XL |
1056 | /// An iterator over the command arguments. |
1057 | /// | |
1058 | /// This struct is created by [`Command::get_args`]. See its documentation for | |
1059 | /// more. | |
3c0e092e | 1060 | #[must_use = "iterators are lazy and do nothing unless consumed"] |
c295e0f8 | 1061 | #[stable(feature = "command_access", since = "1.57.0")] |
1b1a35ee XL |
1062 | #[derive(Debug)] |
1063 | pub struct CommandArgs<'a> { | |
1064 | inner: imp::CommandArgs<'a>, | |
1065 | } | |
1066 | ||
c295e0f8 | 1067 | #[stable(feature = "command_access", since = "1.57.0")] |
1b1a35ee XL |
1068 | impl<'a> Iterator for CommandArgs<'a> { |
1069 | type Item = &'a OsStr; | |
1070 | fn next(&mut self) -> Option<&'a OsStr> { | |
1071 | self.inner.next() | |
1072 | } | |
1073 | fn size_hint(&self) -> (usize, Option<usize>) { | |
1074 | self.inner.size_hint() | |
1075 | } | |
1076 | } | |
1077 | ||
c295e0f8 | 1078 | #[stable(feature = "command_access", since = "1.57.0")] |
1b1a35ee XL |
1079 | impl<'a> ExactSizeIterator for CommandArgs<'a> { |
1080 | fn len(&self) -> usize { | |
1081 | self.inner.len() | |
1082 | } | |
1083 | fn is_empty(&self) -> bool { | |
1084 | self.inner.is_empty() | |
1085 | } | |
1086 | } | |
1087 | ||
85aaf69f | 1088 | /// The output of a finished process. |
abe05a73 XL |
1089 | /// |
1090 | /// This is returned in a Result by either the [`output`] method of a | |
1091 | /// [`Command`], or the [`wait_with_output`] method of a [`Child`] | |
1092 | /// process. | |
1093 | /// | |
3dfed10e XL |
1094 | /// [`output`]: Command::output |
1095 | /// [`wait_with_output`]: Child::wait_with_output | |
85aaf69f | 1096 | #[derive(PartialEq, Eq, Clone)] |
c34b1796 | 1097 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
1098 | pub struct Output { |
1099 | /// The status (exit code) of the process. | |
c34b1796 | 1100 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
1101 | pub status: ExitStatus, |
1102 | /// The data that the process wrote to stdout. | |
c34b1796 | 1103 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
1104 | pub stdout: Vec<u8>, |
1105 | /// The data that the process wrote to stderr. | |
c34b1796 | 1106 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
1107 | pub stderr: Vec<u8>, |
1108 | } | |
1109 | ||
9cc50fc6 SL |
1110 | // If either stderr or stdout are valid utf8 strings it prints the valid |
1111 | // strings, otherwise it prints the byte sequence instead | |
1112 | #[stable(feature = "process_output_debug", since = "1.7.0")] | |
1113 | impl fmt::Debug for Output { | |
532ac7d7 | 1114 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
9cc50fc6 | 1115 | let stdout_utf8 = str::from_utf8(&self.stdout); |
8faf50e0 | 1116 | let stdout_debug: &dyn fmt::Debug = match stdout_utf8 { |
9cc50fc6 | 1117 | Ok(ref str) => str, |
60c5eb7d | 1118 | Err(_) => &self.stdout, |
9cc50fc6 SL |
1119 | }; |
1120 | ||
1121 | let stderr_utf8 = str::from_utf8(&self.stderr); | |
8faf50e0 | 1122 | let stderr_debug: &dyn fmt::Debug = match stderr_utf8 { |
9cc50fc6 | 1123 | Ok(ref str) => str, |
60c5eb7d | 1124 | Err(_) => &self.stderr, |
9cc50fc6 SL |
1125 | }; |
1126 | ||
1127 | fmt.debug_struct("Output") | |
1128 | .field("status", &self.status) | |
1129 | .field("stdout", stdout_debug) | |
1130 | .field("stderr", stderr_debug) | |
1131 | .finish() | |
1132 | } | |
1133 | } | |
1134 | ||
abe05a73 XL |
1135 | /// Describes what to do with a standard I/O stream for a child process when |
1136 | /// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`]. | |
1137 | /// | |
3dfed10e XL |
1138 | /// [`stdin`]: Command::stdin |
1139 | /// [`stdout`]: Command::stdout | |
1140 | /// [`stderr`]: Command::stderr | |
c34b1796 | 1141 | #[stable(feature = "process", since = "1.0.0")] |
7453a54e | 1142 | pub struct Stdio(imp::Stdio); |
85aaf69f SL |
1143 | |
1144 | impl Stdio { | |
1145 | /// A new pipe should be arranged to connect the parent and child processes. | |
abe05a73 XL |
1146 | /// |
1147 | /// # Examples | |
1148 | /// | |
1149 | /// With stdout: | |
1150 | /// | |
1151 | /// ```no_run | |
1152 | /// use std::process::{Command, Stdio}; | |
1153 | /// | |
1154 | /// let output = Command::new("echo") | |
1155 | /// .arg("Hello, world!") | |
1156 | /// .stdout(Stdio::piped()) | |
1157 | /// .output() | |
1158 | /// .expect("Failed to execute command"); | |
1159 | /// | |
1160 | /// assert_eq!(String::from_utf8_lossy(&output.stdout), "Hello, world!\n"); | |
1161 | /// // Nothing echoed to console | |
1162 | /// ``` | |
1163 | /// | |
1164 | /// With stdin: | |
1165 | /// | |
1166 | /// ```no_run | |
1167 | /// use std::io::Write; | |
1168 | /// use std::process::{Command, Stdio}; | |
1169 | /// | |
1170 | /// let mut child = Command::new("rev") | |
1171 | /// .stdin(Stdio::piped()) | |
1172 | /// .stdout(Stdio::piped()) | |
1173 | /// .spawn() | |
1174 | /// .expect("Failed to spawn child process"); | |
1175 | /// | |
6a06907d XL |
1176 | /// let mut stdin = child.stdin.take().expect("Failed to open stdin"); |
1177 | /// std::thread::spawn(move || { | |
abe05a73 | 1178 | /// stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin"); |
6a06907d | 1179 | /// }); |
abe05a73 XL |
1180 | /// |
1181 | /// let output = child.wait_with_output().expect("Failed to read stdout"); | |
e1599b0c | 1182 | /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH"); |
abe05a73 | 1183 | /// ``` |
6a06907d XL |
1184 | /// |
1185 | /// Writing more than a pipe buffer's worth of input to stdin without also reading | |
1186 | /// stdout and stderr at the same time may cause a deadlock. | |
1187 | /// This is an issue when running any program that doesn't guarantee that it reads | |
1188 | /// its entire stdin before writing more than a pipe buffer's worth of output. | |
1189 | /// The size of a pipe buffer varies on different targets. | |
1190 | /// | |
3c0e092e | 1191 | #[must_use] |
c34b1796 | 1192 | #[stable(feature = "process", since = "1.0.0")] |
60c5eb7d XL |
1193 | pub fn piped() -> Stdio { |
1194 | Stdio(imp::Stdio::MakePipe) | |
1195 | } | |
85aaf69f SL |
1196 | |
1197 | /// The child inherits from the corresponding parent descriptor. | |
abe05a73 XL |
1198 | /// |
1199 | /// # Examples | |
1200 | /// | |
1201 | /// With stdout: | |
1202 | /// | |
1203 | /// ```no_run | |
1204 | /// use std::process::{Command, Stdio}; | |
1205 | /// | |
1206 | /// let output = Command::new("echo") | |
1207 | /// .arg("Hello, world!") | |
1208 | /// .stdout(Stdio::inherit()) | |
1209 | /// .output() | |
1210 | /// .expect("Failed to execute command"); | |
1211 | /// | |
1212 | /// assert_eq!(String::from_utf8_lossy(&output.stdout), ""); | |
1213 | /// // "Hello, world!" echoed to console | |
1214 | /// ``` | |
1215 | /// | |
1216 | /// With stdin: | |
1217 | /// | |
1218 | /// ```no_run | |
1219 | /// use std::process::{Command, Stdio}; | |
a1dfa0c6 | 1220 | /// use std::io::{self, Write}; |
abe05a73 XL |
1221 | /// |
1222 | /// let output = Command::new("rev") | |
1223 | /// .stdin(Stdio::inherit()) | |
1224 | /// .stdout(Stdio::piped()) | |
1225 | /// .output() | |
1226 | /// .expect("Failed to execute command"); | |
1227 | /// | |
a1dfa0c6 XL |
1228 | /// print!("You piped in the reverse of: "); |
1229 | /// io::stdout().write_all(&output.stdout).unwrap(); | |
abe05a73 | 1230 | /// ``` |
3c0e092e | 1231 | #[must_use] |
c34b1796 | 1232 | #[stable(feature = "process", since = "1.0.0")] |
60c5eb7d XL |
1233 | pub fn inherit() -> Stdio { |
1234 | Stdio(imp::Stdio::Inherit) | |
1235 | } | |
85aaf69f SL |
1236 | |
1237 | /// This stream will be ignored. This is the equivalent of attaching the | |
29967ef6 | 1238 | /// stream to `/dev/null`. |
abe05a73 XL |
1239 | /// |
1240 | /// # Examples | |
1241 | /// | |
1242 | /// With stdout: | |
1243 | /// | |
1244 | /// ```no_run | |
1245 | /// use std::process::{Command, Stdio}; | |
1246 | /// | |
1247 | /// let output = Command::new("echo") | |
1248 | /// .arg("Hello, world!") | |
1249 | /// .stdout(Stdio::null()) | |
1250 | /// .output() | |
1251 | /// .expect("Failed to execute command"); | |
1252 | /// | |
1253 | /// assert_eq!(String::from_utf8_lossy(&output.stdout), ""); | |
1254 | /// // Nothing echoed to console | |
1255 | /// ``` | |
1256 | /// | |
1257 | /// With stdin: | |
1258 | /// | |
1259 | /// ```no_run | |
1260 | /// use std::process::{Command, Stdio}; | |
1261 | /// | |
1262 | /// let output = Command::new("rev") | |
1263 | /// .stdin(Stdio::null()) | |
1264 | /// .stdout(Stdio::piped()) | |
1265 | /// .output() | |
1266 | /// .expect("Failed to execute command"); | |
1267 | /// | |
1268 | /// assert_eq!(String::from_utf8_lossy(&output.stdout), ""); | |
1269 | /// // Ignores any piped-in input | |
1270 | /// ``` | |
3c0e092e | 1271 | #[must_use] |
c34b1796 | 1272 | #[stable(feature = "process", since = "1.0.0")] |
60c5eb7d XL |
1273 | pub fn null() -> Stdio { |
1274 | Stdio(imp::Stdio::Null) | |
1275 | } | |
62682a34 SL |
1276 | } |
1277 | ||
7453a54e SL |
1278 | impl FromInner<imp::Stdio> for Stdio { |
1279 | fn from_inner(inner: imp::Stdio) -> Stdio { | |
1280 | Stdio(inner) | |
62682a34 | 1281 | } |
85aaf69f SL |
1282 | } |
1283 | ||
8bb4bdeb | 1284 | #[stable(feature = "std_debug", since = "1.16.0")] |
32a655c1 | 1285 | impl fmt::Debug for Stdio { |
532ac7d7 | 1286 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
cdc7bbd5 | 1287 | f.debug_struct("Stdio").finish_non_exhaustive() |
32a655c1 SL |
1288 | } |
1289 | } | |
1290 | ||
041b39d2 XL |
1291 | #[stable(feature = "stdio_from", since = "1.20.0")] |
1292 | impl From<ChildStdin> for Stdio { | |
5099ac24 | 1293 | /// Converts a [`ChildStdin`] into a [`Stdio`]. |
0bf4aa26 XL |
1294 | /// |
1295 | /// # Examples | |
1296 | /// | |
1297 | /// `ChildStdin` will be converted to `Stdio` using `Stdio::from` under the hood. | |
1298 | /// | |
532ac7d7 | 1299 | /// ```rust,no_run |
0bf4aa26 XL |
1300 | /// use std::process::{Command, Stdio}; |
1301 | /// | |
1302 | /// let reverse = Command::new("rev") | |
1303 | /// .stdin(Stdio::piped()) | |
1304 | /// .spawn() | |
1305 | /// .expect("failed reverse command"); | |
1306 | /// | |
1307 | /// let _echo = Command::new("echo") | |
1308 | /// .arg("Hello, world!") | |
1309 | /// .stdout(reverse.stdin.unwrap()) // Converted into a Stdio here | |
1310 | /// .output() | |
1311 | /// .expect("failed echo command"); | |
1312 | /// | |
1313 | /// // "!dlrow ,olleH" echoed to console | |
1314 | /// ``` | |
041b39d2 XL |
1315 | fn from(child: ChildStdin) -> Stdio { |
1316 | Stdio::from_inner(child.into_inner().into()) | |
1317 | } | |
1318 | } | |
1319 | ||
1320 | #[stable(feature = "stdio_from", since = "1.20.0")] | |
1321 | impl From<ChildStdout> for Stdio { | |
5099ac24 | 1322 | /// Converts a [`ChildStdout`] into a [`Stdio`]. |
0bf4aa26 XL |
1323 | /// |
1324 | /// # Examples | |
1325 | /// | |
1326 | /// `ChildStdout` will be converted to `Stdio` using `Stdio::from` under the hood. | |
1327 | /// | |
532ac7d7 | 1328 | /// ```rust,no_run |
0bf4aa26 XL |
1329 | /// use std::process::{Command, Stdio}; |
1330 | /// | |
1331 | /// let hello = Command::new("echo") | |
1332 | /// .arg("Hello, world!") | |
1333 | /// .stdout(Stdio::piped()) | |
1334 | /// .spawn() | |
1335 | /// .expect("failed echo command"); | |
1336 | /// | |
1337 | /// let reverse = Command::new("rev") | |
1338 | /// .stdin(hello.stdout.unwrap()) // Converted into a Stdio here | |
1339 | /// .output() | |
1340 | /// .expect("failed reverse command"); | |
1341 | /// | |
1342 | /// assert_eq!(reverse.stdout, b"!dlrow ,olleH\n"); | |
1343 | /// ``` | |
041b39d2 XL |
1344 | fn from(child: ChildStdout) -> Stdio { |
1345 | Stdio::from_inner(child.into_inner().into()) | |
1346 | } | |
1347 | } | |
1348 | ||
1349 | #[stable(feature = "stdio_from", since = "1.20.0")] | |
1350 | impl From<ChildStderr> for Stdio { | |
5099ac24 | 1351 | /// Converts a [`ChildStderr`] into a [`Stdio`]. |
0bf4aa26 XL |
1352 | /// |
1353 | /// # Examples | |
1354 | /// | |
1355 | /// ```rust,no_run | |
1356 | /// use std::process::{Command, Stdio}; | |
1357 | /// | |
1358 | /// let reverse = Command::new("rev") | |
1359 | /// .arg("non_existing_file.txt") | |
1360 | /// .stderr(Stdio::piped()) | |
1361 | /// .spawn() | |
1362 | /// .expect("failed reverse command"); | |
1363 | /// | |
1364 | /// let cat = Command::new("cat") | |
1365 | /// .arg("-") | |
1366 | /// .stdin(reverse.stderr.unwrap()) // Converted into a Stdio here | |
1367 | /// .output() | |
1368 | /// .expect("failed echo command"); | |
1369 | /// | |
1370 | /// assert_eq!( | |
1371 | /// String::from_utf8_lossy(&cat.stdout), | |
1372 | /// "rev: cannot open non_existing_file.txt: No such file or directory\n" | |
1373 | /// ); | |
1374 | /// ``` | |
041b39d2 XL |
1375 | fn from(child: ChildStderr) -> Stdio { |
1376 | Stdio::from_inner(child.into_inner().into()) | |
1377 | } | |
1378 | } | |
1379 | ||
1380 | #[stable(feature = "stdio_from", since = "1.20.0")] | |
1381 | impl From<fs::File> for Stdio { | |
5099ac24 | 1382 | /// Converts a [`File`](fs::File) into a [`Stdio`]. |
0bf4aa26 XL |
1383 | /// |
1384 | /// # Examples | |
1385 | /// | |
1386 | /// `File` will be converted to `Stdio` using `Stdio::from` under the hood. | |
1387 | /// | |
1388 | /// ```rust,no_run | |
1389 | /// use std::fs::File; | |
1390 | /// use std::process::Command; | |
1391 | /// | |
1392 | /// // With the `foo.txt` file containing `Hello, world!" | |
1393 | /// let file = File::open("foo.txt").unwrap(); | |
1394 | /// | |
1395 | /// let reverse = Command::new("rev") | |
a1dfa0c6 | 1396 | /// .stdin(file) // Implicit File conversion into a Stdio |
0bf4aa26 XL |
1397 | /// .output() |
1398 | /// .expect("failed reverse command"); | |
1399 | /// | |
1400 | /// assert_eq!(reverse.stdout, b"!dlrow ,olleH"); | |
1401 | /// ``` | |
041b39d2 XL |
1402 | fn from(file: fs::File) -> Stdio { |
1403 | Stdio::from_inner(file.into_inner().into()) | |
1404 | } | |
1405 | } | |
1406 | ||
85aaf69f | 1407 | /// Describes the result of a process after it has terminated. |
7cac9316 | 1408 | /// |
6a06907d | 1409 | /// This `struct` is used to represent the exit status or other termination of a child process. |
7cac9316 | 1410 | /// Child processes are created via the [`Command`] struct and their exit |
dc9dc135 XL |
1411 | /// status is exposed through the [`status`] method, or the [`wait`] method |
1412 | /// of a [`Child`] process. | |
7cac9316 | 1413 | /// |
6a06907d XL |
1414 | /// An `ExitStatus` represents every possible disposition of a process. On Unix this |
1415 | /// is the **wait status**. It is *not* simply an *exit status* (a value passed to `exit`). | |
1416 | /// | |
17df50a5 XL |
1417 | /// For proper error reporting of failed processes, print the value of `ExitStatus` or |
1418 | /// `ExitStatusError` using their implementations of [`Display`](crate::fmt::Display). | |
6a06907d | 1419 | /// |
5e7ed085 FG |
1420 | /// # Differences from `ExitStatus` |
1421 | /// | |
1422 | /// `ExitCode` is intended for terminating the currently running process, via | |
1423 | /// the `Termination` trait, in contrast to [`ExitStatus`], which represents the | |
1424 | /// termination of a child process. These APIs are separate due to platform | |
1425 | /// compatibility differences and their expected usage; it is not generally | |
1426 | /// possible to exactly reproduce an ExitStatus from a child for the current | |
1427 | /// process after the fact. | |
1428 | /// | |
3dfed10e XL |
1429 | /// [`status`]: Command::status |
1430 | /// [`wait`]: Child::wait | |
3c0e092e XL |
1431 | // |
1432 | // We speak slightly loosely (here and in various other places in the stdlib docs) about `exit` | |
1433 | // vs `_exit`. Naming of Unix system calls is not standardised across Unices, so terminology is a | |
1434 | // matter of convention and tradition. For clarity we usually speak of `exit`, even when we might | |
1435 | // mean an underlying system call such as `_exit`. | |
85aaf69f | 1436 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
c34b1796 | 1437 | #[stable(feature = "process", since = "1.0.0")] |
62682a34 | 1438 | pub struct ExitStatus(imp::ExitStatus); |
85aaf69f | 1439 | |
6a06907d XL |
1440 | /// Allows extension traits within `std`. |
1441 | #[unstable(feature = "sealed", issue = "none")] | |
1442 | impl crate::sealed::Sealed for ExitStatus {} | |
1443 | ||
85aaf69f | 1444 | impl ExitStatus { |
17df50a5 XL |
1445 | /// Was termination successful? Returns a `Result`. |
1446 | /// | |
1447 | /// # Examples | |
1448 | /// | |
1449 | /// ``` | |
1450 | /// #![feature(exit_status_error)] | |
1451 | /// # if cfg!(unix) { | |
1452 | /// use std::process::Command; | |
1453 | /// | |
1454 | /// let status = Command::new("ls") | |
1455 | /// .arg("/dev/nonexistent") | |
1456 | /// .status() | |
1457 | /// .expect("ls could not be executed"); | |
1458 | /// | |
5e7ed085 | 1459 | /// println!("ls: {status}"); |
17df50a5 XL |
1460 | /// status.exit_ok().expect_err("/dev/nonexistent could be listed!"); |
1461 | /// # } // cfg!(unix) | |
1462 | /// ``` | |
1463 | #[unstable(feature = "exit_status_error", issue = "84908")] | |
1464 | pub fn exit_ok(&self) -> Result<(), ExitStatusError> { | |
1465 | self.0.exit_ok().map_err(ExitStatusError) | |
1466 | } | |
1467 | ||
3b2f2976 XL |
1468 | /// Was termination successful? Signal termination is not considered a |
1469 | /// success, and success is defined as a zero exit status. | |
5bcae85e SL |
1470 | /// |
1471 | /// # Examples | |
1472 | /// | |
1473 | /// ```rust,no_run | |
1474 | /// use std::process::Command; | |
1475 | /// | |
1476 | /// let status = Command::new("mkdir") | |
1477 | /// .arg("projects") | |
1478 | /// .status() | |
1479 | /// .expect("failed to execute mkdir"); | |
1480 | /// | |
1481 | /// if status.success() { | |
1482 | /// println!("'projects/' directory created"); | |
1483 | /// } else { | |
5e7ed085 | 1484 | /// println!("failed to create 'projects/' directory: {status}"); |
5bcae85e SL |
1485 | /// } |
1486 | /// ``` | |
3c0e092e | 1487 | #[must_use] |
c34b1796 | 1488 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 1489 | pub fn success(&self) -> bool { |
17df50a5 | 1490 | self.0.exit_ok().is_ok() |
85aaf69f SL |
1491 | } |
1492 | ||
9346a6ac | 1493 | /// Returns the exit code of the process, if any. |
85aaf69f | 1494 | /// |
6a06907d XL |
1495 | /// In Unix terms the return value is the **exit status**: the value passed to `exit`, if the |
1496 | /// process finished by calling `exit`. Note that on Unix the exit status is truncated to 8 | |
94222f64 | 1497 | /// bits, and that values that didn't come from a program's call to `exit` may be invented by the |
6a06907d XL |
1498 | /// runtime system (often, for example, 255, 254, 127 or 126). |
1499 | /// | |
1500 | /// On Unix, this will return `None` if the process was terminated by a signal. | |
1501 | /// [`ExitStatusExt`](crate::os::unix::process::ExitStatusExt) is an | |
1502 | /// extension trait for extracting any such signal, and other details, from the `ExitStatus`. | |
7cac9316 XL |
1503 | /// |
1504 | /// # Examples | |
1505 | /// | |
1506 | /// ```no_run | |
1507 | /// use std::process::Command; | |
1508 | /// | |
1509 | /// let status = Command::new("mkdir") | |
1510 | /// .arg("projects") | |
1511 | /// .status() | |
1512 | /// .expect("failed to execute mkdir"); | |
1513 | /// | |
1514 | /// match status.code() { | |
5e7ed085 | 1515 | /// Some(code) => println!("Exited with status code: {code}"), |
7cac9316 XL |
1516 | /// None => println!("Process terminated by signal") |
1517 | /// } | |
1518 | /// ``` | |
3c0e092e | 1519 | #[must_use] |
c34b1796 | 1520 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
1521 | pub fn code(&self) -> Option<i32> { |
1522 | self.0.code() | |
1523 | } | |
1524 | } | |
1525 | ||
62682a34 | 1526 | impl AsInner<imp::ExitStatus> for ExitStatus { |
60c5eb7d XL |
1527 | fn as_inner(&self) -> &imp::ExitStatus { |
1528 | &self.0 | |
1529 | } | |
85aaf69f SL |
1530 | } |
1531 | ||
a7813a04 XL |
1532 | impl FromInner<imp::ExitStatus> for ExitStatus { |
1533 | fn from_inner(s: imp::ExitStatus) -> ExitStatus { | |
1534 | ExitStatus(s) | |
1535 | } | |
1536 | } | |
1537 | ||
c34b1796 | 1538 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 1539 | impl fmt::Display for ExitStatus { |
532ac7d7 | 1540 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
85aaf69f SL |
1541 | self.0.fmt(f) |
1542 | } | |
1543 | } | |
1544 | ||
17df50a5 XL |
1545 | /// Allows extension traits within `std`. |
1546 | #[unstable(feature = "sealed", issue = "none")] | |
1547 | impl crate::sealed::Sealed for ExitStatusError {} | |
1548 | ||
1549 | /// Describes the result of a process after it has failed | |
1550 | /// | |
1551 | /// Produced by the [`.exit_ok`](ExitStatus::exit_ok) method on [`ExitStatus`]. | |
1552 | /// | |
1553 | /// # Examples | |
1554 | /// | |
1555 | /// ``` | |
1556 | /// #![feature(exit_status_error)] | |
1557 | /// # if cfg!(unix) { | |
1558 | /// use std::process::{Command, ExitStatusError}; | |
1559 | /// | |
1560 | /// fn run(cmd: &str) -> Result<(),ExitStatusError> { | |
1561 | /// Command::new(cmd).status().unwrap().exit_ok()?; | |
1562 | /// Ok(()) | |
1563 | /// } | |
1564 | /// | |
1565 | /// run("true").unwrap(); | |
1566 | /// run("false").unwrap_err(); | |
1567 | /// # } // cfg!(unix) | |
1568 | /// ``` | |
1569 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | |
1570 | #[unstable(feature = "exit_status_error", issue = "84908")] | |
1571 | // The definition of imp::ExitStatusError should ideally be such that | |
1572 | // Result<(), imp::ExitStatusError> has an identical representation to imp::ExitStatus. | |
1573 | pub struct ExitStatusError(imp::ExitStatusError); | |
1574 | ||
1575 | #[unstable(feature = "exit_status_error", issue = "84908")] | |
1576 | impl ExitStatusError { | |
1577 | /// Reports the exit code, if applicable, from an `ExitStatusError`. | |
1578 | /// | |
1579 | /// In Unix terms the return value is the **exit status**: the value passed to `exit`, if the | |
1580 | /// process finished by calling `exit`. Note that on Unix the exit status is truncated to 8 | |
1581 | /// bits, and that values that didn't come from a program's call to `exit` may be invented by the | |
1582 | /// runtime system (often, for example, 255, 254, 127 or 126). | |
1583 | /// | |
1584 | /// On Unix, this will return `None` if the process was terminated by a signal. If you want to | |
1585 | /// handle such situations specially, consider using methods from | |
1586 | /// [`ExitStatusExt`](crate::os::unix::process::ExitStatusExt). | |
1587 | /// | |
1588 | /// If the process finished by calling `exit` with a nonzero value, this will return | |
1589 | /// that exit status. | |
1590 | /// | |
1591 | /// If the error was something else, it will return `None`. | |
1592 | /// | |
1593 | /// If the process exited successfully (ie, by calling `exit(0)`), there is no | |
1594 | /// `ExitStatusError`. So the return value from `ExitStatusError::code()` is always nonzero. | |
1595 | /// | |
1596 | /// # Examples | |
1597 | /// | |
1598 | /// ``` | |
1599 | /// #![feature(exit_status_error)] | |
1600 | /// # #[cfg(unix)] { | |
1601 | /// use std::process::Command; | |
1602 | /// | |
1603 | /// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err(); | |
1604 | /// assert_eq!(bad.code(), Some(1)); | |
1605 | /// # } // #[cfg(unix)] | |
1606 | /// ``` | |
3c0e092e | 1607 | #[must_use] |
17df50a5 XL |
1608 | pub fn code(&self) -> Option<i32> { |
1609 | self.code_nonzero().map(Into::into) | |
1610 | } | |
1611 | ||
1612 | /// Reports the exit code, if applicable, from an `ExitStatusError`, as a `NonZero` | |
1613 | /// | |
136023e0 | 1614 | /// This is exactly like [`code()`](Self::code), except that it returns a `NonZeroI32`. |
17df50a5 XL |
1615 | /// |
1616 | /// Plain `code`, returning a plain integer, is provided because is is often more convenient. | |
1617 | /// The returned value from `code()` is indeed also nonzero; use `code_nonzero()` when you want | |
1618 | /// a type-level guarantee of nonzeroness. | |
1619 | /// | |
1620 | /// # Examples | |
1621 | /// | |
1622 | /// ``` | |
1623 | /// #![feature(exit_status_error)] | |
1624 | /// # if cfg!(unix) { | |
17df50a5 XL |
1625 | /// use std::num::NonZeroI32; |
1626 | /// use std::process::Command; | |
1627 | /// | |
1628 | /// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err(); | |
1629 | /// assert_eq!(bad.code_nonzero().unwrap(), NonZeroI32::try_from(1).unwrap()); | |
1630 | /// # } // cfg!(unix) | |
1631 | /// ``` | |
3c0e092e | 1632 | #[must_use] |
17df50a5 XL |
1633 | pub fn code_nonzero(&self) -> Option<NonZeroI32> { |
1634 | self.0.code() | |
1635 | } | |
1636 | ||
1637 | /// Converts an `ExitStatusError` (back) to an `ExitStatus`. | |
3c0e092e | 1638 | #[must_use] |
17df50a5 XL |
1639 | pub fn into_status(&self) -> ExitStatus { |
1640 | ExitStatus(self.0.into()) | |
1641 | } | |
1642 | } | |
1643 | ||
1644 | #[unstable(feature = "exit_status_error", issue = "84908")] | |
1645 | impl Into<ExitStatus> for ExitStatusError { | |
1646 | fn into(self) -> ExitStatus { | |
1647 | ExitStatus(self.0.into()) | |
1648 | } | |
1649 | } | |
1650 | ||
1651 | #[unstable(feature = "exit_status_error", issue = "84908")] | |
1652 | impl fmt::Display for ExitStatusError { | |
1653 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1654 | write!(f, "process exited unsuccessfully: {}", self.into_status()) | |
1655 | } | |
1656 | } | |
1657 | ||
1658 | #[unstable(feature = "exit_status_error", issue = "84908")] | |
1659 | impl crate::error::Error for ExitStatusError {} | |
1660 | ||
5e7ed085 FG |
1661 | /// This type represents the status code the current process can return |
1662 | /// to its parent under normal termination. | |
1663 | /// | |
1664 | /// `ExitCode` is intended to be consumed only by the standard library (via | |
1665 | /// [`Termination::report()`]), and intentionally does not provide accessors like | |
1666 | /// `PartialEq`, `Eq`, or `Hash`. Instead the standard library provides the | |
1667 | /// canonical `SUCCESS` and `FAILURE` exit codes as well as `From<u8> for | |
1668 | /// ExitCode` for constructing other arbitrary exit codes. | |
1669 | /// | |
1670 | /// # Portability | |
0531ce1d XL |
1671 | /// |
1672 | /// Numeric values used in this type don't have portable meanings, and | |
1673 | /// different platforms may mask different amounts of them. | |
1674 | /// | |
1675 | /// For the platform's canonical successful and unsuccessful codes, see | |
1676 | /// the [`SUCCESS`] and [`FAILURE`] associated items. | |
1677 | /// | |
3dfed10e XL |
1678 | /// [`SUCCESS`]: ExitCode::SUCCESS |
1679 | /// [`FAILURE`]: ExitCode::FAILURE | |
0531ce1d | 1680 | /// |
5e7ed085 FG |
1681 | /// # Differences from `ExitStatus` |
1682 | /// | |
1683 | /// `ExitCode` is intended for terminating the currently running process, via | |
1684 | /// the `Termination` trait, in contrast to [`ExitStatus`], which represents the | |
1685 | /// termination of a child process. These APIs are separate due to platform | |
1686 | /// compatibility differences and their expected usage; it is not generally | |
1687 | /// possible to exactly reproduce an ExitStatus from a child for the current | |
1688 | /// process after the fact. | |
1689 | /// | |
1690 | /// # Examples | |
1691 | /// | |
1692 | /// `ExitCode` can be returned from the `main` function of a crate, as it implements | |
1693 | /// [`Termination`]: | |
1694 | /// | |
1695 | /// ``` | |
1696 | /// use std::process::ExitCode; | |
1697 | /// # fn check_foo() -> bool { true } | |
1698 | /// | |
1699 | /// fn main() -> ExitCode { | |
1700 | /// if !check_foo() { | |
1701 | /// return ExitCode::from(42); | |
1702 | /// } | |
0531ce1d | 1703 | /// |
5e7ed085 FG |
1704 | /// ExitCode::SUCCESS |
1705 | /// } | |
1706 | /// ``` | |
0531ce1d | 1707 | #[derive(Clone, Copy, Debug)] |
5e7ed085 | 1708 | #[stable(feature = "process_exitcode", since = "1.61.0")] |
0531ce1d XL |
1709 | pub struct ExitCode(imp::ExitCode); |
1710 | ||
5e7ed085 | 1711 | #[stable(feature = "process_exitcode", since = "1.61.0")] |
0531ce1d | 1712 | impl ExitCode { |
5e7ed085 | 1713 | /// The canonical `ExitCode` for successful termination on this platform. |
0531ce1d XL |
1714 | /// |
1715 | /// Note that a `()`-returning `main` implicitly results in a successful | |
1716 | /// termination, so there's no need to return this from `main` unless | |
1717 | /// you're also returning other possible codes. | |
5e7ed085 | 1718 | #[stable(feature = "process_exitcode", since = "1.61.0")] |
0531ce1d XL |
1719 | pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS); |
1720 | ||
5e7ed085 | 1721 | /// The canonical `ExitCode` for unsuccessful termination on this platform. |
0531ce1d XL |
1722 | /// |
1723 | /// If you're only returning this and `SUCCESS` from `main`, consider | |
1724 | /// instead returning `Err(_)` and `Ok(())` respectively, which will | |
1725 | /// return the same codes (but will also `eprintln!` the error). | |
5e7ed085 | 1726 | #[stable(feature = "process_exitcode", since = "1.61.0")] |
0531ce1d | 1727 | pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE); |
04454e1e FG |
1728 | |
1729 | /// Exit the current process with the given `ExitCode`. | |
1730 | /// | |
1731 | /// Note that this has the same caveats as [`process::exit()`][exit], namely that this function | |
1732 | /// terminates the process immediately, so no destructors on the current stack or any other | |
1733 | /// thread's stack will be run. If a clean shutdown is needed, it is recommended to simply | |
1734 | /// return this ExitCode from the `main` function, as demonstrated in the [type | |
1735 | /// documentation](#examples). | |
1736 | /// | |
1737 | /// # Differences from `process::exit()` | |
1738 | /// | |
1739 | /// `process::exit()` accepts any `i32` value as the exit code for the process; however, there | |
1740 | /// are platforms that only use a subset of that value (see [`process::exit` platform-specific | |
1741 | /// behavior][exit#platform-specific-behavior]). `ExitCode` exists because of this; only | |
1742 | /// `ExitCode`s that are supported by a majority of our platforms can be created, so those | |
1743 | /// problems don't exist (as much) with this method. | |
1744 | /// | |
1745 | /// # Examples | |
1746 | /// | |
1747 | /// ``` | |
1748 | /// #![feature(exitcode_exit_method)] | |
1749 | /// # use std::process::ExitCode; | |
1750 | /// # use std::fmt; | |
1751 | /// # enum UhOhError { GenericProblem, Specific, WithCode { exit_code: ExitCode, _x: () } } | |
1752 | /// # impl fmt::Display for UhOhError { | |
1753 | /// # fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { unimplemented!() } | |
1754 | /// # } | |
1755 | /// // there's no way to gracefully recover from an UhOhError, so we just | |
1756 | /// // print a message and exit | |
1757 | /// fn handle_unrecoverable_error(err: UhOhError) -> ! { | |
1758 | /// eprintln!("UH OH! {err}"); | |
1759 | /// let code = match err { | |
1760 | /// UhOhError::GenericProblem => ExitCode::FAILURE, | |
1761 | /// UhOhError::Specific => ExitCode::from(3), | |
1762 | /// UhOhError::WithCode { exit_code, .. } => exit_code, | |
1763 | /// }; | |
1764 | /// code.exit_process() | |
1765 | /// } | |
1766 | /// ``` | |
1767 | #[unstable(feature = "exitcode_exit_method", issue = "none")] | |
1768 | pub fn exit_process(self) -> ! { | |
1769 | exit(self.to_i32()) | |
1770 | } | |
0531ce1d XL |
1771 | } |
1772 | ||
5099ac24 | 1773 | impl ExitCode { |
5e7ed085 | 1774 | // This is private/perma-unstable because ExitCode is opaque; we don't know that i32 will serve |
5099ac24 FG |
1775 | // all usecases, for example windows seems to use u32, unix uses the 8-15th bits of an i32, we |
1776 | // likely want to isolate users anything that could restrict the platform specific | |
1777 | // representation of an ExitCode | |
1778 | // | |
1779 | // More info: https://internals.rust-lang.org/t/mini-pre-rfc-redesigning-process-exitstatus/5426 | |
5e7ed085 FG |
1780 | /// Convert an `ExitCode` into an i32 |
1781 | #[unstable( | |
1782 | feature = "process_exitcode_internals", | |
1783 | reason = "exposed only for libstd", | |
1784 | issue = "none" | |
1785 | )] | |
5099ac24 | 1786 | #[inline] |
5e7ed085 | 1787 | #[doc(hidden)] |
5099ac24 FG |
1788 | pub fn to_i32(self) -> i32 { |
1789 | self.0.as_i32() | |
1790 | } | |
1791 | } | |
1792 | ||
5e7ed085 | 1793 | #[stable(feature = "process_exitcode", since = "1.61.0")] |
5099ac24 | 1794 | impl From<u8> for ExitCode { |
5e7ed085 | 1795 | /// Construct an `ExitCode` from an arbitrary u8 value. |
5099ac24 FG |
1796 | fn from(code: u8) -> Self { |
1797 | ExitCode(imp::ExitCode::from(code)) | |
1798 | } | |
1799 | } | |
1800 | ||
85aaf69f | 1801 | impl Child { |
83c7162d XL |
1802 | /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`] |
1803 | /// error is returned. | |
1804 | /// | |
136023e0 | 1805 | /// The mapping to [`ErrorKind`]s is not part of the compatibility contract of the function. |
83c7162d XL |
1806 | /// |
1807 | /// This is equivalent to sending a SIGKILL on Unix platforms. | |
a7813a04 XL |
1808 | /// |
1809 | /// # Examples | |
1810 | /// | |
1811 | /// Basic usage: | |
1812 | /// | |
1813 | /// ```no_run | |
1814 | /// use std::process::Command; | |
1815 | /// | |
1816 | /// let mut command = Command::new("yes"); | |
1817 | /// if let Ok(mut child) = command.spawn() { | |
1818 | /// child.kill().expect("command wasn't running"); | |
1819 | /// } else { | |
1820 | /// println!("yes command didn't start"); | |
1821 | /// } | |
1822 | /// ``` | |
83c7162d | 1823 | /// |
3dfed10e XL |
1824 | /// [`ErrorKind`]: io::ErrorKind |
1825 | /// [`InvalidInput`]: io::ErrorKind::InvalidInput | |
c34b1796 | 1826 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f | 1827 | pub fn kill(&mut self) -> io::Result<()> { |
7453a54e | 1828 | self.handle.kill() |
85aaf69f SL |
1829 | } |
1830 | ||
62682a34 | 1831 | /// Returns the OS-assigned process identifier associated with this child. |
a7813a04 XL |
1832 | /// |
1833 | /// # Examples | |
1834 | /// | |
1835 | /// Basic usage: | |
1836 | /// | |
1837 | /// ```no_run | |
1838 | /// use std::process::Command; | |
1839 | /// | |
1840 | /// let mut command = Command::new("ls"); | |
1841 | /// if let Ok(child) = command.spawn() { | |
9fa01778 | 1842 | /// println!("Child's ID is {}", child.id()); |
a7813a04 XL |
1843 | /// } else { |
1844 | /// println!("ls command didn't start"); | |
1845 | /// } | |
1846 | /// ``` | |
3c0e092e | 1847 | #[must_use] |
c1a9b12d | 1848 | #[stable(feature = "process_id", since = "1.3.0")] |
62682a34 SL |
1849 | pub fn id(&self) -> u32 { |
1850 | self.handle.id() | |
1851 | } | |
1852 | ||
9346a6ac | 1853 | /// Waits for the child to exit completely, returning the status that it |
85aaf69f SL |
1854 | /// exited with. This function will continue to have the same return value |
1855 | /// after it has been called at least once. | |
1856 | /// | |
1857 | /// The stdin handle to the child process, if any, will be closed | |
1858 | /// before waiting. This helps avoid deadlock: it ensures that the | |
1859 | /// child does not block waiting for input from the parent, while | |
1860 | /// the parent waits for the child to exit. | |
a7813a04 XL |
1861 | /// |
1862 | /// # Examples | |
1863 | /// | |
1864 | /// Basic usage: | |
1865 | /// | |
1866 | /// ```no_run | |
1867 | /// use std::process::Command; | |
1868 | /// | |
1869 | /// let mut command = Command::new("ls"); | |
1870 | /// if let Ok(mut child) = command.spawn() { | |
1871 | /// child.wait().expect("command wasn't running"); | |
1872 | /// println!("Child has finished its execution!"); | |
1873 | /// } else { | |
1874 | /// println!("ls command didn't start"); | |
1875 | /// } | |
1876 | /// ``` | |
c34b1796 | 1877 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
1878 | pub fn wait(&mut self) -> io::Result<ExitStatus> { |
1879 | drop(self.stdin.take()); | |
7453a54e | 1880 | self.handle.wait().map(ExitStatus) |
85aaf69f SL |
1881 | } |
1882 | ||
32a655c1 SL |
1883 | /// Attempts to collect the exit status of the child if it has already |
1884 | /// exited. | |
1885 | /// | |
a1dfa0c6 | 1886 | /// This function will not block the calling thread and will only |
32a655c1 | 1887 | /// check to see if the child process has exited or not. If the child has |
9fa01778 | 1888 | /// exited then on Unix the process ID is reaped. This function is |
32a655c1 SL |
1889 | /// guaranteed to repeatedly return a successful exit status so long as the |
1890 | /// child has already exited. | |
1891 | /// | |
8bb4bdeb XL |
1892 | /// If the child has exited, then `Ok(Some(status))` is returned. If the |
1893 | /// exit status is not available at this time then `Ok(None)` is returned. | |
1894 | /// If an error occurs, then that error is returned. | |
32a655c1 SL |
1895 | /// |
1896 | /// Note that unlike `wait`, this function will not attempt to drop stdin. | |
1897 | /// | |
1898 | /// # Examples | |
1899 | /// | |
1900 | /// Basic usage: | |
1901 | /// | |
1902 | /// ```no_run | |
32a655c1 SL |
1903 | /// use std::process::Command; |
1904 | /// | |
1905 | /// let mut child = Command::new("ls").spawn().unwrap(); | |
1906 | /// | |
1907 | /// match child.try_wait() { | |
5e7ed085 | 1908 | /// Ok(Some(status)) => println!("exited with: {status}"), |
8bb4bdeb | 1909 | /// Ok(None) => { |
32a655c1 SL |
1910 | /// println!("status not ready yet, let's really wait"); |
1911 | /// let res = child.wait(); | |
5e7ed085 | 1912 | /// println!("result: {res:?}"); |
32a655c1 | 1913 | /// } |
5e7ed085 | 1914 | /// Err(e) => println!("error attempting to wait: {e}"), |
32a655c1 SL |
1915 | /// } |
1916 | /// ``` | |
cc61c64b | 1917 | #[stable(feature = "process_try_wait", since = "1.18.0")] |
8bb4bdeb XL |
1918 | pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> { |
1919 | Ok(self.handle.try_wait()?.map(ExitStatus)) | |
32a655c1 SL |
1920 | } |
1921 | ||
9346a6ac | 1922 | /// Simultaneously waits for the child to exit and collect all remaining |
92a42be0 | 1923 | /// output on the stdout/stderr handles, returning an `Output` |
85aaf69f SL |
1924 | /// instance. |
1925 | /// | |
1926 | /// The stdin handle to the child process, if any, will be closed | |
1927 | /// before waiting. This helps avoid deadlock: it ensures that the | |
1928 | /// child does not block waiting for input from the parent, while | |
1929 | /// the parent waits for the child to exit. | |
a7813a04 XL |
1930 | /// |
1931 | /// By default, stdin, stdout and stderr are inherited from the parent. | |
1932 | /// In order to capture the output into this `Result<Output>` it is | |
1933 | /// necessary to create new pipes between parent and child. Use | |
1934 | /// `stdout(Stdio::piped())` or `stderr(Stdio::piped())`, respectively. | |
1935 | /// | |
1936 | /// # Examples | |
1937 | /// | |
1938 | /// ```should_panic | |
1939 | /// use std::process::{Command, Stdio}; | |
1940 | /// | |
3157f602 XL |
1941 | /// let child = Command::new("/bin/cat") |
1942 | /// .arg("file.txt") | |
1943 | /// .stdout(Stdio::piped()) | |
1944 | /// .spawn() | |
1945 | /// .expect("failed to execute child"); | |
a7813a04 | 1946 | /// |
3157f602 XL |
1947 | /// let output = child |
1948 | /// .wait_with_output() | |
1949 | /// .expect("failed to wait on child"); | |
a7813a04 | 1950 | /// |
3157f602 | 1951 | /// assert!(output.status.success()); |
a7813a04 XL |
1952 | /// ``` |
1953 | /// | |
c34b1796 | 1954 | #[stable(feature = "process", since = "1.0.0")] |
85aaf69f SL |
1955 | pub fn wait_with_output(mut self) -> io::Result<Output> { |
1956 | drop(self.stdin.take()); | |
54a0048b SL |
1957 | |
1958 | let (mut stdout, mut stderr) = (Vec::new(), Vec::new()); | |
1959 | match (self.stdout.take(), self.stderr.take()) { | |
1960 | (None, None) => {} | |
1961 | (Some(mut out), None) => { | |
1962 | let res = out.read_to_end(&mut stdout); | |
1963 | res.unwrap(); | |
1964 | } | |
1965 | (None, Some(mut err)) => { | |
1966 | let res = err.read_to_end(&mut stderr); | |
1967 | res.unwrap(); | |
1968 | } | |
1969 | (Some(out), Some(err)) => { | |
1970 | let res = read2(out.inner, &mut stdout, err.inner, &mut stderr); | |
1971 | res.unwrap(); | |
1972 | } | |
85aaf69f | 1973 | } |
85aaf69f | 1974 | |
54a0048b | 1975 | let status = self.wait()?; |
60c5eb7d | 1976 | Ok(Output { status, stdout, stderr }) |
85aaf69f SL |
1977 | } |
1978 | } | |
1979 | ||
c34b1796 AL |
1980 | /// Terminates the current process with the specified exit code. |
1981 | /// | |
1982 | /// This function will never return and will immediately terminate the current | |
1983 | /// process. The exit code is passed through to the underlying OS and will be | |
1984 | /// available for consumption by another process. | |
1985 | /// | |
1986 | /// Note that because this function never returns, and that it terminates the | |
1987 | /// process, no destructors on the current stack or any other thread's stack | |
1988 | /// will be run. If a clean shutdown is needed it is recommended to only call | |
1989 | /// this function at a known point where there are no more destructors left | |
04454e1e FG |
1990 | /// to run; or, preferably, simply return a type implementing [`Termination`] |
1991 | /// (such as [`ExitCode`] or `Result`) from the `main` function and avoid this | |
1992 | /// function altogether: | |
1993 | /// | |
1994 | /// ``` | |
1995 | /// # use std::io::Error as MyError; | |
1996 | /// fn main() -> Result<(), MyError> { | |
1997 | /// // ... | |
1998 | /// Ok(()) | |
1999 | /// } | |
2000 | /// ``` | |
476ff2be SL |
2001 | /// |
2002 | /// ## Platform-specific behavior | |
2003 | /// | |
2004 | /// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit` | |
2005 | /// will be visible to a parent process inspecting the exit code. On most | |
2006 | /// Unix-like platforms, only the eight least-significant bits are considered. | |
2007 | /// | |
04454e1e FG |
2008 | /// For example, the exit code for this example will be `0` on Linux, but `256` |
2009 | /// on Windows: | |
476ff2be SL |
2010 | /// |
2011 | /// ```no_run | |
2012 | /// use std::process; | |
2013 | /// | |
7cac9316 | 2014 | /// process::exit(0x0100); |
476ff2be | 2015 | /// ``` |
c34b1796 AL |
2016 | #[stable(feature = "rust1", since = "1.0.0")] |
2017 | pub fn exit(code: i32) -> ! { | |
c295e0f8 | 2018 | crate::rt::cleanup(); |
532ac7d7 | 2019 | crate::sys::os::exit(code) |
c34b1796 AL |
2020 | } |
2021 | ||
476ff2be SL |
2022 | /// Terminates the process in an abnormal fashion. |
2023 | /// | |
2024 | /// The function will never return and will immediately terminate the current | |
2025 | /// process in a platform specific "abnormal" manner. | |
2026 | /// | |
2027 | /// Note that because this function never returns, and that it terminates the | |
2028 | /// process, no destructors on the current stack or any other thread's stack | |
ea8adc8c XL |
2029 | /// will be run. |
2030 | /// | |
136023e0 XL |
2031 | /// Rust IO buffers (eg, from `BufWriter`) will not be flushed. |
2032 | /// Likewise, C stdio buffers will (on most platforms) not be flushed. | |
2033 | /// | |
ea8adc8c XL |
2034 | /// This is in contrast to the default behaviour of [`panic!`] which unwinds |
2035 | /// the current thread's stack and calls all destructors. | |
2036 | /// When `panic="abort"` is set, either as an argument to `rustc` or in a | |
2037 | /// crate's Cargo.toml, [`panic!`] and `abort` are similar. However, | |
2038 | /// [`panic!`] will still call the [panic hook] while `abort` will not. | |
2039 | /// | |
2040 | /// If a clean shutdown is needed it is recommended to only call | |
476ff2be SL |
2041 | /// this function at a known point where there are no more destructors left |
2042 | /// to run. | |
cc61c64b | 2043 | /// |
136023e0 XL |
2044 | /// The process's termination will be similar to that from the C `abort()` |
2045 | /// function. On Unix, the process will terminate with signal `SIGABRT`, which | |
2046 | /// typically means that the shell prints "Aborted". | |
2047 | /// | |
cc61c64b XL |
2048 | /// # Examples |
2049 | /// | |
2050 | /// ```no_run | |
2051 | /// use std::process; | |
2052 | /// | |
2053 | /// fn main() { | |
2054 | /// println!("aborting"); | |
2055 | /// | |
2056 | /// process::abort(); | |
2057 | /// | |
2058 | /// // execution never gets here | |
2059 | /// } | |
2060 | /// ``` | |
2061 | /// | |
ea8adc8c | 2062 | /// The `abort` function terminates the process, so the destructor will not |
cc61c64b XL |
2063 | /// get run on the example below: |
2064 | /// | |
2065 | /// ```no_run | |
2066 | /// use std::process; | |
2067 | /// | |
2068 | /// struct HasDrop; | |
2069 | /// | |
2070 | /// impl Drop for HasDrop { | |
2071 | /// fn drop(&mut self) { | |
2072 | /// println!("This will never be printed!"); | |
2073 | /// } | |
2074 | /// } | |
2075 | /// | |
2076 | /// fn main() { | |
2077 | /// let _x = HasDrop; | |
2078 | /// process::abort(); | |
2079 | /// // the destructor implemented for HasDrop will never get run | |
2080 | /// } | |
2081 | /// ``` | |
ea8adc8c | 2082 | /// |
3dfed10e | 2083 | /// [panic hook]: crate::panic::set_hook |
8bb4bdeb | 2084 | #[stable(feature = "process_abort", since = "1.17.0")] |
fc512014 | 2085 | #[cold] |
476ff2be | 2086 | pub fn abort() -> ! { |
f9f354fc | 2087 | crate::sys::abort_internal(); |
476ff2be SL |
2088 | } |
2089 | ||
abe05a73 XL |
2090 | /// Returns the OS-assigned process identifier associated with this process. |
2091 | /// | |
2092 | /// # Examples | |
2093 | /// | |
2094 | /// Basic usage: | |
2095 | /// | |
2096 | /// ```no_run | |
abe05a73 XL |
2097 | /// use std::process; |
2098 | /// | |
2099 | /// println!("My pid is {}", process::id()); | |
2100 | /// ``` | |
2101 | /// | |
2102 | /// | |
3c0e092e | 2103 | #[must_use] |
0531ce1d | 2104 | #[stable(feature = "getpid", since = "1.26.0")] |
abe05a73 | 2105 | pub fn id() -> u32 { |
532ac7d7 | 2106 | crate::sys::os::getpid() |
abe05a73 XL |
2107 | } |
2108 | ||
0531ce1d XL |
2109 | /// A trait for implementing arbitrary return types in the `main` function. |
2110 | /// | |
e1599b0c | 2111 | /// The C-main function only supports to return integers as return type. |
0531ce1d XL |
2112 | /// So, every type implementing the `Termination` trait has to be converted |
2113 | /// to an integer. | |
2114 | /// | |
2115 | /// The default implementations are returning `libc::EXIT_SUCCESS` to indicate | |
2116 | /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned. | |
5e7ed085 FG |
2117 | /// |
2118 | /// Because different runtimes have different specifications on the return value | |
2119 | /// of the `main` function, this trait is likely to be available only on | |
2120 | /// standard library's runtime for convenience. Other runtimes are not required | |
2121 | /// to provide similar functionality. | |
0531ce1d | 2122 | #[cfg_attr(not(test), lang = "termination")] |
5e7ed085 | 2123 | #[stable(feature = "termination_trait_lib", since = "1.61.0")] |
0531ce1d | 2124 | #[rustc_on_unimplemented( |
60c5eb7d XL |
2125 | message = "`main` has invalid return type `{Self}`", |
2126 | label = "`main` can only return types that implement `{Termination}`" | |
2127 | )] | |
0531ce1d XL |
2128 | pub trait Termination { |
2129 | /// Is called to get the representation of the value as status code. | |
2130 | /// This status code is returned to the operating system. | |
5e7ed085 | 2131 | #[stable(feature = "termination_trait_lib", since = "1.61.0")] |
5099ac24 | 2132 | fn report(self) -> ExitCode; |
0531ce1d XL |
2133 | } |
2134 | ||
5e7ed085 | 2135 | #[stable(feature = "termination_trait_lib", since = "1.61.0")] |
0531ce1d | 2136 | impl Termination for () { |
83c7162d | 2137 | #[inline] |
5099ac24 | 2138 | fn report(self) -> ExitCode { |
60c5eb7d XL |
2139 | ExitCode::SUCCESS.report() |
2140 | } | |
0531ce1d XL |
2141 | } |
2142 | ||
5e7ed085 | 2143 | #[stable(feature = "termination_trait_lib", since = "1.61.0")] |
0531ce1d | 2144 | impl<E: fmt::Debug> Termination for Result<(), E> { |
5099ac24 | 2145 | fn report(self) -> ExitCode { |
0531ce1d XL |
2146 | match self { |
2147 | Ok(()) => ().report(), | |
2148 | Err(err) => Err::<!, _>(err).report(), | |
2149 | } | |
2150 | } | |
2151 | } | |
2152 | ||
5e7ed085 | 2153 | #[stable(feature = "termination_trait_lib", since = "1.61.0")] |
0531ce1d | 2154 | impl Termination for ! { |
5099ac24 | 2155 | fn report(self) -> ExitCode { |
60c5eb7d XL |
2156 | self |
2157 | } | |
0531ce1d XL |
2158 | } |
2159 | ||
5e7ed085 | 2160 | #[stable(feature = "termination_trait_lib", since = "1.61.0")] |
0531ce1d | 2161 | impl<E: fmt::Debug> Termination for Result<!, E> { |
5099ac24 | 2162 | fn report(self) -> ExitCode { |
0531ce1d | 2163 | let Err(err) = self; |
5e7ed085 | 2164 | eprintln!("Error: {err:?}"); |
0531ce1d XL |
2165 | ExitCode::FAILURE.report() |
2166 | } | |
2167 | } | |
2168 | ||
5e7ed085 | 2169 | #[stable(feature = "termination_trait_lib", since = "1.61.0")] |
3c0e092e | 2170 | impl<E: fmt::Debug> Termination for Result<Infallible, E> { |
5099ac24 | 2171 | fn report(self) -> ExitCode { |
3c0e092e XL |
2172 | let Err(err) = self; |
2173 | Err::<!, _>(err).report() | |
2174 | } | |
2175 | } | |
2176 | ||
5e7ed085 | 2177 | #[stable(feature = "termination_trait_lib", since = "1.61.0")] |
0531ce1d | 2178 | impl Termination for ExitCode { |
83c7162d | 2179 | #[inline] |
5099ac24 FG |
2180 | fn report(self) -> ExitCode { |
2181 | self | |
0531ce1d XL |
2182 | } |
2183 | } |