]> git.proxmox.com Git - rustc.git/blob - src/libstd/process.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / libstd / process.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! A module for working with processes.
12 //!
13 //! # Examples
14 //!
15 //! Basic usage where we try to execute the `cat` shell command:
16 //!
17 //! ```should_panic
18 //! use std::process::Command;
19 //!
20 //! let mut child = Command::new("/bin/cat")
21 //! .arg("file.txt")
22 //! .spawn()
23 //! .expect("failed to execute child");
24 //!
25 //! let ecode = child.wait()
26 //! .expect("failed to wait on child");
27 //!
28 //! assert!(ecode.success());
29 //! ```
30 //!
31 //! Calling a command with input and reading its output:
32 //!
33 //! ```no_run
34 //! use std::process::{Command, Stdio};
35 //! use std::io::Write;
36 //!
37 //! let mut child = Command::new("/bin/cat")
38 //! .stdin(Stdio::piped())
39 //! .stdout(Stdio::piped())
40 //! .spawn()
41 //! .expect("failed to execute child");
42 //!
43 //! {
44 //! // limited borrow of stdin
45 //! let stdin = child.stdin.as_mut().expect("failed to get stdin");
46 //! stdin.write_all(b"test").expect("failed to write to stdin");
47 //! }
48 //!
49 //! let output = child
50 //! .wait_with_output()
51 //! .expect("failed to wait on child");
52 //!
53 //! assert_eq!(b"test", output.stdout.as_slice());
54 //! ```
55
56 #![stable(feature = "process", since = "1.0.0")]
57
58 use io::prelude::*;
59
60 use ffi::OsStr;
61 use fmt;
62 use io;
63 use path::Path;
64 use str;
65 use sys::pipe::{read2, AnonPipe};
66 use sys::process as imp;
67 use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
68
69 /// Representation of a running or exited child process.
70 ///
71 /// This structure is used to represent and manage child processes. A child
72 /// process is created via the [`Command`] struct, which configures the
73 /// spawning process and can itself be constructed using a builder-style
74 /// interface.
75 ///
76 /// # Examples
77 ///
78 /// ```should_panic
79 /// use std::process::Command;
80 ///
81 /// let mut child = Command::new("/bin/cat")
82 /// .arg("file.txt")
83 /// .spawn()
84 /// .expect("failed to execute child");
85 ///
86 /// let ecode = child.wait()
87 /// .expect("failed to wait on child");
88 ///
89 /// assert!(ecode.success());
90 /// ```
91 ///
92 /// # Note
93 ///
94 /// Take note that there is no implementation of [`Drop`] for child processes,
95 /// so if you do not ensure the `Child` has exited then it will continue to
96 /// run, even after the `Child` handle to the child process has gone out of
97 /// scope.
98 ///
99 /// Calling [`wait`][`wait`] (or other functions that wrap around it) will make
100 /// the parent process wait until the child has actually exited before
101 /// continuing.
102 ///
103 /// [`Command`]: struct.Command.html
104 /// [`Drop`]: ../../core/ops/trait.Drop.html
105 /// [`wait`]: #method.wait
106 #[stable(feature = "process", since = "1.0.0")]
107 pub struct Child {
108 handle: imp::Process,
109
110 /// The handle for writing to the child's stdin, if it has been captured
111 #[stable(feature = "process", since = "1.0.0")]
112 pub stdin: Option<ChildStdin>,
113
114 /// The handle for reading from the child's stdout, if it has been captured
115 #[stable(feature = "process", since = "1.0.0")]
116 pub stdout: Option<ChildStdout>,
117
118 /// The handle for reading from the child's stderr, if it has been captured
119 #[stable(feature = "process", since = "1.0.0")]
120 pub stderr: Option<ChildStderr>,
121 }
122
123 impl AsInner<imp::Process> for Child {
124 fn as_inner(&self) -> &imp::Process { &self.handle }
125 }
126
127 impl FromInner<(imp::Process, imp::StdioPipes)> for Child {
128 fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child {
129 Child {
130 handle: handle,
131 stdin: io.stdin.map(ChildStdin::from_inner),
132 stdout: io.stdout.map(ChildStdout::from_inner),
133 stderr: io.stderr.map(ChildStderr::from_inner),
134 }
135 }
136 }
137
138 impl IntoInner<imp::Process> for Child {
139 fn into_inner(self) -> imp::Process { self.handle }
140 }
141
142 #[stable(feature = "std_debug", since = "1.16.0")]
143 impl fmt::Debug for Child {
144 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145 f.debug_struct("Child")
146 .field("stdin", &self.stdin)
147 .field("stdout", &self.stdout)
148 .field("stderr", &self.stderr)
149 .finish()
150 }
151 }
152
153 /// A handle to a child process's stdin. This struct is used in the [`stdin`]
154 /// field on [`Child`].
155 ///
156 /// [`Child`]: struct.Child.html
157 /// [`stdin`]: struct.Child.html#structfield.stdin
158 #[stable(feature = "process", since = "1.0.0")]
159 pub struct ChildStdin {
160 inner: AnonPipe
161 }
162
163 #[stable(feature = "process", since = "1.0.0")]
164 impl Write for ChildStdin {
165 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
166 self.inner.write(buf)
167 }
168
169 fn flush(&mut self) -> io::Result<()> {
170 Ok(())
171 }
172 }
173
174 impl AsInner<AnonPipe> for ChildStdin {
175 fn as_inner(&self) -> &AnonPipe { &self.inner }
176 }
177
178 impl IntoInner<AnonPipe> for ChildStdin {
179 fn into_inner(self) -> AnonPipe { self.inner }
180 }
181
182 impl FromInner<AnonPipe> for ChildStdin {
183 fn from_inner(pipe: AnonPipe) -> ChildStdin {
184 ChildStdin { inner: pipe }
185 }
186 }
187
188 #[stable(feature = "std_debug", since = "1.16.0")]
189 impl fmt::Debug for ChildStdin {
190 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
191 f.pad("ChildStdin { .. }")
192 }
193 }
194
195 /// A handle to a child process's stdout. This struct is used in the [`stdout`]
196 /// field on [`Child`].
197 ///
198 /// [`Child`]: struct.Child.html
199 /// [`stdout`]: struct.Child.html#structfield.stdout
200 #[stable(feature = "process", since = "1.0.0")]
201 pub struct ChildStdout {
202 inner: AnonPipe
203 }
204
205 #[stable(feature = "process", since = "1.0.0")]
206 impl Read for ChildStdout {
207 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
208 self.inner.read(buf)
209 }
210 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
211 self.inner.read_to_end(buf)
212 }
213 }
214
215 impl AsInner<AnonPipe> for ChildStdout {
216 fn as_inner(&self) -> &AnonPipe { &self.inner }
217 }
218
219 impl IntoInner<AnonPipe> for ChildStdout {
220 fn into_inner(self) -> AnonPipe { self.inner }
221 }
222
223 impl FromInner<AnonPipe> for ChildStdout {
224 fn from_inner(pipe: AnonPipe) -> ChildStdout {
225 ChildStdout { inner: pipe }
226 }
227 }
228
229 #[stable(feature = "std_debug", since = "1.16.0")]
230 impl fmt::Debug for ChildStdout {
231 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
232 f.pad("ChildStdout { .. }")
233 }
234 }
235
236 /// A handle to a child process's stderr. This struct is used in the [`stderr`]
237 /// field on [`Child`].
238 ///
239 /// [`Child`]: struct.Child.html
240 /// [`stderr`]: struct.Child.html#structfield.stderr
241 #[stable(feature = "process", since = "1.0.0")]
242 pub struct ChildStderr {
243 inner: AnonPipe
244 }
245
246 #[stable(feature = "process", since = "1.0.0")]
247 impl Read for ChildStderr {
248 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
249 self.inner.read(buf)
250 }
251 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
252 self.inner.read_to_end(buf)
253 }
254 }
255
256 impl AsInner<AnonPipe> for ChildStderr {
257 fn as_inner(&self) -> &AnonPipe { &self.inner }
258 }
259
260 impl IntoInner<AnonPipe> for ChildStderr {
261 fn into_inner(self) -> AnonPipe { self.inner }
262 }
263
264 impl FromInner<AnonPipe> for ChildStderr {
265 fn from_inner(pipe: AnonPipe) -> ChildStderr {
266 ChildStderr { inner: pipe }
267 }
268 }
269
270 #[stable(feature = "std_debug", since = "1.16.0")]
271 impl fmt::Debug for ChildStderr {
272 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
273 f.pad("ChildStderr { .. }")
274 }
275 }
276
277 /// A process builder, providing fine-grained control
278 /// over how a new process should be spawned.
279 ///
280 /// A default configuration can be
281 /// generated using `Command::new(program)`, where `program` gives a path to the
282 /// program to be executed. Additional builder methods allow the configuration
283 /// to be changed (for example, by adding arguments) prior to spawning:
284 ///
285 /// ```
286 /// use std::process::Command;
287 ///
288 /// let output = if cfg!(target_os = "windows") {
289 /// Command::new("cmd")
290 /// .args(&["/C", "echo hello"])
291 /// .output()
292 /// .expect("failed to execute process")
293 /// } else {
294 /// Command::new("sh")
295 /// .arg("-c")
296 /// .arg("echo hello")
297 /// .output()
298 /// .expect("failed to execute process")
299 /// };
300 ///
301 /// let hello = output.stdout;
302 /// ```
303 #[stable(feature = "process", since = "1.0.0")]
304 pub struct Command {
305 inner: imp::Command,
306 }
307
308 impl Command {
309 /// Constructs a new `Command` for launching the program at
310 /// path `program`, with the following default configuration:
311 ///
312 /// * No arguments to the program
313 /// * Inherit the current process's environment
314 /// * Inherit the current process's working directory
315 /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
316 ///
317 /// Builder methods are provided to change these defaults and
318 /// otherwise configure the process.
319 ///
320 /// If `program` is not an absolute path, the `PATH` will be searched in
321 /// an OS-defined way.
322 ///
323 /// The search path to be used may be controlled by setting the
324 /// `PATH` environment variable on the Command,
325 /// but this has some implementation limitations on Windows
326 /// (see https://github.com/rust-lang/rust/issues/37519).
327 ///
328 /// # Examples
329 ///
330 /// Basic usage:
331 ///
332 /// ```no_run
333 /// use std::process::Command;
334 ///
335 /// Command::new("sh")
336 /// .spawn()
337 /// .expect("sh command failed to start");
338 /// ```
339 #[stable(feature = "process", since = "1.0.0")]
340 pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
341 Command { inner: imp::Command::new(program.as_ref()) }
342 }
343
344 /// Add an argument to pass to the program.
345 ///
346 /// # Examples
347 ///
348 /// Basic usage:
349 ///
350 /// ```no_run
351 /// use std::process::Command;
352 ///
353 /// Command::new("ls")
354 /// .arg("-l")
355 /// .arg("-a")
356 /// .spawn()
357 /// .expect("ls command failed to start");
358 /// ```
359 #[stable(feature = "process", since = "1.0.0")]
360 pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
361 self.inner.arg(arg.as_ref());
362 self
363 }
364
365 /// Add multiple arguments to pass to the program.
366 ///
367 /// # Examples
368 ///
369 /// Basic usage:
370 ///
371 /// ```no_run
372 /// use std::process::Command;
373 ///
374 /// Command::new("ls")
375 /// .args(&["-l", "-a"])
376 /// .spawn()
377 /// .expect("ls command failed to start");
378 /// ```
379 #[stable(feature = "process", since = "1.0.0")]
380 pub fn args<I, S>(&mut self, args: I) -> &mut Command
381 where I: IntoIterator<Item=S>, S: AsRef<OsStr>
382 {
383 for arg in args {
384 self.arg(arg.as_ref());
385 }
386 self
387 }
388
389 /// Inserts or updates an environment variable mapping.
390 ///
391 /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
392 /// and case-sensitive on all other platforms.
393 ///
394 /// # Examples
395 ///
396 /// Basic usage:
397 ///
398 /// ```no_run
399 /// use std::process::Command;
400 ///
401 /// Command::new("ls")
402 /// .env("PATH", "/bin")
403 /// .spawn()
404 /// .expect("ls command failed to start");
405 /// ```
406 #[stable(feature = "process", since = "1.0.0")]
407 pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
408 where K: AsRef<OsStr>, V: AsRef<OsStr>
409 {
410 self.inner.env(key.as_ref(), val.as_ref());
411 self
412 }
413
414 /// Add or update multiple environment variable mappings.
415 ///
416 /// # Examples
417 ///
418 /// Basic usage:
419 /// ```no_run
420 /// use std::process::{Command, Stdio};
421 /// use std::env;
422 /// use std::collections::HashMap;
423 ///
424 /// let filtered_env : HashMap<String, String> =
425 /// env::vars().filter(|&(ref k, _)|
426 /// k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH"
427 /// ).collect();
428 ///
429 /// Command::new("printenv")
430 /// .stdin(Stdio::null())
431 /// .stdout(Stdio::inherit())
432 /// .env_clear()
433 /// .envs(&filtered_env)
434 /// .spawn()
435 /// .expect("printenv failed to start");
436 /// ```
437 #[unstable(feature = "command_envs", issue = "38526")]
438 pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
439 where I: IntoIterator<Item=(K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>
440 {
441 for (ref key, ref val) in vars {
442 self.inner.env(key.as_ref(), val.as_ref());
443 }
444 self
445 }
446
447 /// Removes an environment variable mapping.
448 ///
449 /// # Examples
450 ///
451 /// Basic usage:
452 ///
453 /// ```no_run
454 /// use std::process::Command;
455 ///
456 /// Command::new("ls")
457 /// .env_remove("PATH")
458 /// .spawn()
459 /// .expect("ls command failed to start");
460 /// ```
461 #[stable(feature = "process", since = "1.0.0")]
462 pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
463 self.inner.env_remove(key.as_ref());
464 self
465 }
466
467 /// Clears the entire environment map for the child process.
468 ///
469 /// # Examples
470 ///
471 /// Basic usage:
472 ///
473 /// ```no_run
474 /// use std::process::Command;
475 ///
476 /// Command::new("ls")
477 /// .env_clear()
478 /// .spawn()
479 /// .expect("ls command failed to start");
480 /// ```
481 #[stable(feature = "process", since = "1.0.0")]
482 pub fn env_clear(&mut self) -> &mut Command {
483 self.inner.env_clear();
484 self
485 }
486
487 /// Sets the working directory for the child process.
488 ///
489 /// # Examples
490 ///
491 /// Basic usage:
492 ///
493 /// ```no_run
494 /// use std::process::Command;
495 ///
496 /// Command::new("ls")
497 /// .current_dir("/bin")
498 /// .spawn()
499 /// .expect("ls command failed to start");
500 /// ```
501 #[stable(feature = "process", since = "1.0.0")]
502 pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
503 self.inner.cwd(dir.as_ref().as_ref());
504 self
505 }
506
507 /// Configuration for the child process's stdin handle (file descriptor 0).
508 ///
509 /// # Examples
510 ///
511 /// Basic usage:
512 ///
513 /// ```no_run
514 /// use std::process::{Command, Stdio};
515 ///
516 /// Command::new("ls")
517 /// .stdin(Stdio::null())
518 /// .spawn()
519 /// .expect("ls command failed to start");
520 /// ```
521 #[stable(feature = "process", since = "1.0.0")]
522 pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
523 self.inner.stdin(cfg.0);
524 self
525 }
526
527 /// Configuration for the child process's stdout handle (file descriptor 1).
528 ///
529 /// # Examples
530 ///
531 /// Basic usage:
532 ///
533 /// ```no_run
534 /// use std::process::{Command, Stdio};
535 ///
536 /// Command::new("ls")
537 /// .stdout(Stdio::null())
538 /// .spawn()
539 /// .expect("ls command failed to start");
540 /// ```
541 #[stable(feature = "process", since = "1.0.0")]
542 pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
543 self.inner.stdout(cfg.0);
544 self
545 }
546
547 /// Configuration for the child process's stderr handle (file descriptor 2).
548 ///
549 /// # Examples
550 ///
551 /// Basic usage:
552 ///
553 /// ```no_run
554 /// use std::process::{Command, Stdio};
555 ///
556 /// Command::new("ls")
557 /// .stderr(Stdio::null())
558 /// .spawn()
559 /// .expect("ls command failed to start");
560 /// ```
561 #[stable(feature = "process", since = "1.0.0")]
562 pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
563 self.inner.stderr(cfg.0);
564 self
565 }
566
567 /// Executes the command as a child process, returning a handle to it.
568 ///
569 /// By default, stdin, stdout and stderr are inherited from the parent.
570 ///
571 /// # Examples
572 ///
573 /// Basic usage:
574 ///
575 /// ```no_run
576 /// use std::process::Command;
577 ///
578 /// Command::new("ls")
579 /// .spawn()
580 /// .expect("ls command failed to start");
581 /// ```
582 #[stable(feature = "process", since = "1.0.0")]
583 pub fn spawn(&mut self) -> io::Result<Child> {
584 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
585 }
586
587 /// Executes the command as a child process, waiting for it to finish and
588 /// collecting all of its output.
589 ///
590 /// By default, stdin, stdout and stderr are captured (and used to
591 /// provide the resulting output).
592 ///
593 /// # Examples
594 ///
595 /// ```should_panic
596 /// use std::process::Command;
597 /// let output = Command::new("/bin/cat")
598 /// .arg("file.txt")
599 /// .output()
600 /// .expect("failed to execute process");
601 ///
602 /// println!("status: {}", output.status);
603 /// println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
604 /// println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
605 ///
606 /// assert!(output.status.success());
607 /// ```
608 #[stable(feature = "process", since = "1.0.0")]
609 pub fn output(&mut self) -> io::Result<Output> {
610 self.inner.spawn(imp::Stdio::MakePipe, false).map(Child::from_inner)
611 .and_then(|p| p.wait_with_output())
612 }
613
614 /// Executes a command as a child process, waiting for it to finish and
615 /// collecting its exit status.
616 ///
617 /// By default, stdin, stdout and stderr are inherited from the parent.
618 ///
619 /// # Examples
620 ///
621 /// ```should_panic
622 /// use std::process::Command;
623 ///
624 /// let status = Command::new("/bin/cat")
625 /// .arg("file.txt")
626 /// .status()
627 /// .expect("failed to execute process");
628 ///
629 /// println!("process exited with: {}", status);
630 ///
631 /// assert!(status.success());
632 /// ```
633 #[stable(feature = "process", since = "1.0.0")]
634 pub fn status(&mut self) -> io::Result<ExitStatus> {
635 self.inner.spawn(imp::Stdio::Inherit, true).map(Child::from_inner)
636 .and_then(|mut p| p.wait())
637 }
638 }
639
640 #[stable(feature = "rust1", since = "1.0.0")]
641 impl fmt::Debug for Command {
642 /// Format the program and arguments of a Command for display. Any
643 /// non-utf8 data is lossily converted using the utf8 replacement
644 /// character.
645 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
646 self.inner.fmt(f)
647 }
648 }
649
650 impl AsInner<imp::Command> for Command {
651 fn as_inner(&self) -> &imp::Command { &self.inner }
652 }
653
654 impl AsInnerMut<imp::Command> for Command {
655 fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner }
656 }
657
658 /// The output of a finished process.
659 #[derive(PartialEq, Eq, Clone)]
660 #[stable(feature = "process", since = "1.0.0")]
661 pub struct Output {
662 /// The status (exit code) of the process.
663 #[stable(feature = "process", since = "1.0.0")]
664 pub status: ExitStatus,
665 /// The data that the process wrote to stdout.
666 #[stable(feature = "process", since = "1.0.0")]
667 pub stdout: Vec<u8>,
668 /// The data that the process wrote to stderr.
669 #[stable(feature = "process", since = "1.0.0")]
670 pub stderr: Vec<u8>,
671 }
672
673 // If either stderr or stdout are valid utf8 strings it prints the valid
674 // strings, otherwise it prints the byte sequence instead
675 #[stable(feature = "process_output_debug", since = "1.7.0")]
676 impl fmt::Debug for Output {
677 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
678
679 let stdout_utf8 = str::from_utf8(&self.stdout);
680 let stdout_debug: &fmt::Debug = match stdout_utf8 {
681 Ok(ref str) => str,
682 Err(_) => &self.stdout
683 };
684
685 let stderr_utf8 = str::from_utf8(&self.stderr);
686 let stderr_debug: &fmt::Debug = match stderr_utf8 {
687 Ok(ref str) => str,
688 Err(_) => &self.stderr
689 };
690
691 fmt.debug_struct("Output")
692 .field("status", &self.status)
693 .field("stdout", stdout_debug)
694 .field("stderr", stderr_debug)
695 .finish()
696 }
697 }
698
699 /// Describes what to do with a standard I/O stream for a child process.
700 #[stable(feature = "process", since = "1.0.0")]
701 pub struct Stdio(imp::Stdio);
702
703 impl Stdio {
704 /// A new pipe should be arranged to connect the parent and child processes.
705 #[stable(feature = "process", since = "1.0.0")]
706 pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) }
707
708 /// The child inherits from the corresponding parent descriptor.
709 #[stable(feature = "process", since = "1.0.0")]
710 pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) }
711
712 /// This stream will be ignored. This is the equivalent of attaching the
713 /// stream to `/dev/null`
714 #[stable(feature = "process", since = "1.0.0")]
715 pub fn null() -> Stdio { Stdio(imp::Stdio::Null) }
716 }
717
718 impl FromInner<imp::Stdio> for Stdio {
719 fn from_inner(inner: imp::Stdio) -> Stdio {
720 Stdio(inner)
721 }
722 }
723
724 #[stable(feature = "std_debug", since = "1.16.0")]
725 impl fmt::Debug for Stdio {
726 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
727 f.pad("Stdio { .. }")
728 }
729 }
730
731 /// Describes the result of a process after it has terminated.
732 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
733 #[stable(feature = "process", since = "1.0.0")]
734 pub struct ExitStatus(imp::ExitStatus);
735
736 impl ExitStatus {
737 /// Was termination successful? Signal termination not considered a success,
738 /// and success is defined as a zero exit status.
739 ///
740 /// # Examples
741 ///
742 /// ```rust,no_run
743 /// use std::process::Command;
744 ///
745 /// let status = Command::new("mkdir")
746 /// .arg("projects")
747 /// .status()
748 /// .expect("failed to execute mkdir");
749 ///
750 /// if status.success() {
751 /// println!("'projects/' directory created");
752 /// } else {
753 /// println!("failed to create 'projects/' directory");
754 /// }
755 /// ```
756 #[stable(feature = "process", since = "1.0.0")]
757 pub fn success(&self) -> bool {
758 self.0.success()
759 }
760
761 /// Returns the exit code of the process, if any.
762 ///
763 /// On Unix, this will return `None` if the process was terminated
764 /// by a signal; `std::os::unix` provides an extension trait for
765 /// extracting the signal and other details from the `ExitStatus`.
766 #[stable(feature = "process", since = "1.0.0")]
767 pub fn code(&self) -> Option<i32> {
768 self.0.code()
769 }
770 }
771
772 impl AsInner<imp::ExitStatus> for ExitStatus {
773 fn as_inner(&self) -> &imp::ExitStatus { &self.0 }
774 }
775
776 impl FromInner<imp::ExitStatus> for ExitStatus {
777 fn from_inner(s: imp::ExitStatus) -> ExitStatus {
778 ExitStatus(s)
779 }
780 }
781
782 #[stable(feature = "process", since = "1.0.0")]
783 impl fmt::Display for ExitStatus {
784 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
785 self.0.fmt(f)
786 }
787 }
788
789 impl Child {
790 /// Forces the child to exit. This is equivalent to sending a
791 /// SIGKILL on unix platforms.
792 ///
793 /// # Examples
794 ///
795 /// Basic usage:
796 ///
797 /// ```no_run
798 /// use std::process::Command;
799 ///
800 /// let mut command = Command::new("yes");
801 /// if let Ok(mut child) = command.spawn() {
802 /// child.kill().expect("command wasn't running");
803 /// } else {
804 /// println!("yes command didn't start");
805 /// }
806 /// ```
807 #[stable(feature = "process", since = "1.0.0")]
808 pub fn kill(&mut self) -> io::Result<()> {
809 self.handle.kill()
810 }
811
812 /// Returns the OS-assigned process identifier associated with this child.
813 ///
814 /// # Examples
815 ///
816 /// Basic usage:
817 ///
818 /// ```no_run
819 /// use std::process::Command;
820 ///
821 /// let mut command = Command::new("ls");
822 /// if let Ok(child) = command.spawn() {
823 /// println!("Child's id is {}", child.id());
824 /// } else {
825 /// println!("ls command didn't start");
826 /// }
827 /// ```
828 #[stable(feature = "process_id", since = "1.3.0")]
829 pub fn id(&self) -> u32 {
830 self.handle.id()
831 }
832
833 /// Waits for the child to exit completely, returning the status that it
834 /// exited with. This function will continue to have the same return value
835 /// after it has been called at least once.
836 ///
837 /// The stdin handle to the child process, if any, will be closed
838 /// before waiting. This helps avoid deadlock: it ensures that the
839 /// child does not block waiting for input from the parent, while
840 /// the parent waits for the child to exit.
841 ///
842 /// # Examples
843 ///
844 /// Basic usage:
845 ///
846 /// ```no_run
847 /// use std::process::Command;
848 ///
849 /// let mut command = Command::new("ls");
850 /// if let Ok(mut child) = command.spawn() {
851 /// child.wait().expect("command wasn't running");
852 /// println!("Child has finished its execution!");
853 /// } else {
854 /// println!("ls command didn't start");
855 /// }
856 /// ```
857 #[stable(feature = "process", since = "1.0.0")]
858 pub fn wait(&mut self) -> io::Result<ExitStatus> {
859 drop(self.stdin.take());
860 self.handle.wait().map(ExitStatus)
861 }
862
863 /// Attempts to collect the exit status of the child if it has already
864 /// exited.
865 ///
866 /// This function will not block the calling thread and will only advisorily
867 /// check to see if the child process has exited or not. If the child has
868 /// exited then on Unix the process id is reaped. This function is
869 /// guaranteed to repeatedly return a successful exit status so long as the
870 /// child has already exited.
871 ///
872 /// If the child has exited, then `Ok(Some(status))` is returned. If the
873 /// exit status is not available at this time then `Ok(None)` is returned.
874 /// If an error occurs, then that error is returned.
875 ///
876 /// Note that unlike `wait`, this function will not attempt to drop stdin.
877 ///
878 /// # Examples
879 ///
880 /// Basic usage:
881 ///
882 /// ```no_run
883 /// #![feature(process_try_wait)]
884 ///
885 /// use std::process::Command;
886 ///
887 /// let mut child = Command::new("ls").spawn().unwrap();
888 ///
889 /// match child.try_wait() {
890 /// Ok(Some(status)) => println!("exited with: {}", status),
891 /// Ok(None) => {
892 /// println!("status not ready yet, let's really wait");
893 /// let res = child.wait();
894 /// println!("result: {:?}", res);
895 /// }
896 /// Err(e) => println!("error attempting to wait: {}", e),
897 /// }
898 /// ```
899 #[unstable(feature = "process_try_wait", issue = "38903")]
900 pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
901 Ok(self.handle.try_wait()?.map(ExitStatus))
902 }
903
904 /// Simultaneously waits for the child to exit and collect all remaining
905 /// output on the stdout/stderr handles, returning an `Output`
906 /// instance.
907 ///
908 /// The stdin handle to the child process, if any, will be closed
909 /// before waiting. This helps avoid deadlock: it ensures that the
910 /// child does not block waiting for input from the parent, while
911 /// the parent waits for the child to exit.
912 ///
913 /// By default, stdin, stdout and stderr are inherited from the parent.
914 /// In order to capture the output into this `Result<Output>` it is
915 /// necessary to create new pipes between parent and child. Use
916 /// `stdout(Stdio::piped())` or `stderr(Stdio::piped())`, respectively.
917 ///
918 /// # Examples
919 ///
920 /// ```should_panic
921 /// use std::process::{Command, Stdio};
922 ///
923 /// let child = Command::new("/bin/cat")
924 /// .arg("file.txt")
925 /// .stdout(Stdio::piped())
926 /// .spawn()
927 /// .expect("failed to execute child");
928 ///
929 /// let output = child
930 /// .wait_with_output()
931 /// .expect("failed to wait on child");
932 ///
933 /// assert!(output.status.success());
934 /// ```
935 ///
936 #[stable(feature = "process", since = "1.0.0")]
937 pub fn wait_with_output(mut self) -> io::Result<Output> {
938 drop(self.stdin.take());
939
940 let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
941 match (self.stdout.take(), self.stderr.take()) {
942 (None, None) => {}
943 (Some(mut out), None) => {
944 let res = out.read_to_end(&mut stdout);
945 res.unwrap();
946 }
947 (None, Some(mut err)) => {
948 let res = err.read_to_end(&mut stderr);
949 res.unwrap();
950 }
951 (Some(out), Some(err)) => {
952 let res = read2(out.inner, &mut stdout, err.inner, &mut stderr);
953 res.unwrap();
954 }
955 }
956
957 let status = self.wait()?;
958 Ok(Output {
959 status: status,
960 stdout: stdout,
961 stderr: stderr,
962 })
963 }
964 }
965
966 /// Terminates the current process with the specified exit code.
967 ///
968 /// This function will never return and will immediately terminate the current
969 /// process. The exit code is passed through to the underlying OS and will be
970 /// available for consumption by another process.
971 ///
972 /// Note that because this function never returns, and that it terminates the
973 /// process, no destructors on the current stack or any other thread's stack
974 /// will be run. If a clean shutdown is needed it is recommended to only call
975 /// this function at a known point where there are no more destructors left
976 /// to run.
977 ///
978 /// ## Platform-specific behavior
979 ///
980 /// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit`
981 /// will be visible to a parent process inspecting the exit code. On most
982 /// Unix-like platforms, only the eight least-significant bits are considered.
983 ///
984 /// # Examples
985 ///
986 /// Due to this function’s behavior regarding destructors, a conventional way
987 /// to use the function is to extract the actual computation to another
988 /// function and compute the exit code from its return value:
989 ///
990 /// ```
991 /// use std::io::{self, Write};
992 ///
993 /// fn run_app() -> Result<(), ()> {
994 /// // Application logic here
995 /// Ok(())
996 /// }
997 ///
998 /// fn main() {
999 /// ::std::process::exit(match run_app() {
1000 /// Ok(_) => 0,
1001 /// Err(err) => {
1002 /// writeln!(io::stderr(), "error: {:?}", err).unwrap();
1003 /// 1
1004 /// }
1005 /// });
1006 /// }
1007 /// ```
1008 ///
1009 /// Due to [platform-specific behavior], the exit code for this example will be
1010 /// `0` on Linux, but `256` on Windows:
1011 ///
1012 /// ```no_run
1013 /// use std::process;
1014 ///
1015 /// process::exit(0x0f00);
1016 /// ```
1017 ///
1018 /// [platform-specific behavior]: #platform-specific-behavior
1019 #[stable(feature = "rust1", since = "1.0.0")]
1020 pub fn exit(code: i32) -> ! {
1021 ::sys_common::cleanup();
1022 ::sys::os::exit(code)
1023 }
1024
1025 /// Terminates the process in an abnormal fashion.
1026 ///
1027 /// The function will never return and will immediately terminate the current
1028 /// process in a platform specific "abnormal" manner.
1029 ///
1030 /// Note that because this function never returns, and that it terminates the
1031 /// process, no destructors on the current stack or any other thread's stack
1032 /// will be run. If a clean shutdown is needed it is recommended to only call
1033 /// this function at a known point where there are no more destructors left
1034 /// to run.
1035 #[stable(feature = "process_abort", since = "1.17.0")]
1036 pub fn abort() -> ! {
1037 unsafe { ::sys::abort_internal() };
1038 }
1039
1040 #[cfg(all(test, not(target_os = "emscripten")))]
1041 mod tests {
1042 use io::prelude::*;
1043
1044 use io::ErrorKind;
1045 use str;
1046 use super::{Command, Output, Stdio};
1047
1048 // FIXME(#10380) these tests should not all be ignored on android.
1049
1050 #[test]
1051 #[cfg_attr(target_os = "android", ignore)]
1052 fn smoke() {
1053 let p = if cfg!(target_os = "windows") {
1054 Command::new("cmd").args(&["/C", "exit 0"]).spawn()
1055 } else {
1056 Command::new("true").spawn()
1057 };
1058 assert!(p.is_ok());
1059 let mut p = p.unwrap();
1060 assert!(p.wait().unwrap().success());
1061 }
1062
1063 #[test]
1064 #[cfg_attr(target_os = "android", ignore)]
1065 fn smoke_failure() {
1066 match Command::new("if-this-is-a-binary-then-the-world-has-ended").spawn() {
1067 Ok(..) => panic!(),
1068 Err(..) => {}
1069 }
1070 }
1071
1072 #[test]
1073 #[cfg_attr(target_os = "android", ignore)]
1074 fn exit_reported_right() {
1075 let p = if cfg!(target_os = "windows") {
1076 Command::new("cmd").args(&["/C", "exit 1"]).spawn()
1077 } else {
1078 Command::new("false").spawn()
1079 };
1080 assert!(p.is_ok());
1081 let mut p = p.unwrap();
1082 assert!(p.wait().unwrap().code() == Some(1));
1083 drop(p.wait());
1084 }
1085
1086 #[test]
1087 #[cfg(unix)]
1088 #[cfg_attr(target_os = "android", ignore)]
1089 fn signal_reported_right() {
1090 use os::unix::process::ExitStatusExt;
1091
1092 let mut p = Command::new("/bin/sh")
1093 .arg("-c").arg("read a")
1094 .stdin(Stdio::piped())
1095 .spawn().unwrap();
1096 p.kill().unwrap();
1097 match p.wait().unwrap().signal() {
1098 Some(9) => {},
1099 result => panic!("not terminated by signal 9 (instead, {:?})",
1100 result),
1101 }
1102 }
1103
1104 pub fn run_output(mut cmd: Command) -> String {
1105 let p = cmd.spawn();
1106 assert!(p.is_ok());
1107 let mut p = p.unwrap();
1108 assert!(p.stdout.is_some());
1109 let mut ret = String::new();
1110 p.stdout.as_mut().unwrap().read_to_string(&mut ret).unwrap();
1111 assert!(p.wait().unwrap().success());
1112 return ret;
1113 }
1114
1115 #[test]
1116 #[cfg_attr(target_os = "android", ignore)]
1117 fn stdout_works() {
1118 if cfg!(target_os = "windows") {
1119 let mut cmd = Command::new("cmd");
1120 cmd.args(&["/C", "echo foobar"]).stdout(Stdio::piped());
1121 assert_eq!(run_output(cmd), "foobar\r\n");
1122 } else {
1123 let mut cmd = Command::new("echo");
1124 cmd.arg("foobar").stdout(Stdio::piped());
1125 assert_eq!(run_output(cmd), "foobar\n");
1126 }
1127 }
1128
1129 #[test]
1130 #[cfg_attr(any(windows, target_os = "android"), ignore)]
1131 fn set_current_dir_works() {
1132 let mut cmd = Command::new("/bin/sh");
1133 cmd.arg("-c").arg("pwd")
1134 .current_dir("/")
1135 .stdout(Stdio::piped());
1136 assert_eq!(run_output(cmd), "/\n");
1137 }
1138
1139 #[test]
1140 #[cfg_attr(any(windows, target_os = "android"), ignore)]
1141 fn stdin_works() {
1142 let mut p = Command::new("/bin/sh")
1143 .arg("-c").arg("read line; echo $line")
1144 .stdin(Stdio::piped())
1145 .stdout(Stdio::piped())
1146 .spawn().unwrap();
1147 p.stdin.as_mut().unwrap().write("foobar".as_bytes()).unwrap();
1148 drop(p.stdin.take());
1149 let mut out = String::new();
1150 p.stdout.as_mut().unwrap().read_to_string(&mut out).unwrap();
1151 assert!(p.wait().unwrap().success());
1152 assert_eq!(out, "foobar\n");
1153 }
1154
1155
1156 #[test]
1157 #[cfg_attr(target_os = "android", ignore)]
1158 #[cfg(unix)]
1159 fn uid_works() {
1160 use os::unix::prelude::*;
1161 use libc;
1162 let mut p = Command::new("/bin/sh")
1163 .arg("-c").arg("true")
1164 .uid(unsafe { libc::getuid() })
1165 .gid(unsafe { libc::getgid() })
1166 .spawn().unwrap();
1167 assert!(p.wait().unwrap().success());
1168 }
1169
1170 #[test]
1171 #[cfg_attr(target_os = "android", ignore)]
1172 #[cfg(unix)]
1173 fn uid_to_root_fails() {
1174 use os::unix::prelude::*;
1175 use libc;
1176
1177 // if we're already root, this isn't a valid test. Most of the bots run
1178 // as non-root though (android is an exception).
1179 if unsafe { libc::getuid() == 0 } { return }
1180 assert!(Command::new("/bin/ls").uid(0).gid(0).spawn().is_err());
1181 }
1182
1183 #[test]
1184 #[cfg_attr(target_os = "android", ignore)]
1185 fn test_process_status() {
1186 let mut status = if cfg!(target_os = "windows") {
1187 Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap()
1188 } else {
1189 Command::new("false").status().unwrap()
1190 };
1191 assert!(status.code() == Some(1));
1192
1193 status = if cfg!(target_os = "windows") {
1194 Command::new("cmd").args(&["/C", "exit 0"]).status().unwrap()
1195 } else {
1196 Command::new("true").status().unwrap()
1197 };
1198 assert!(status.success());
1199 }
1200
1201 #[test]
1202 fn test_process_output_fail_to_start() {
1203 match Command::new("/no-binary-by-this-name-should-exist").output() {
1204 Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
1205 Ok(..) => panic!()
1206 }
1207 }
1208
1209 #[test]
1210 #[cfg_attr(target_os = "android", ignore)]
1211 fn test_process_output_output() {
1212 let Output {status, stdout, stderr}
1213 = if cfg!(target_os = "windows") {
1214 Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap()
1215 } else {
1216 Command::new("echo").arg("hello").output().unwrap()
1217 };
1218 let output_str = str::from_utf8(&stdout).unwrap();
1219
1220 assert!(status.success());
1221 assert_eq!(output_str.trim().to_string(), "hello");
1222 assert_eq!(stderr, Vec::new());
1223 }
1224
1225 #[test]
1226 #[cfg_attr(target_os = "android", ignore)]
1227 fn test_process_output_error() {
1228 let Output {status, stdout, stderr}
1229 = if cfg!(target_os = "windows") {
1230 Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap()
1231 } else {
1232 Command::new("mkdir").arg(".").output().unwrap()
1233 };
1234
1235 assert!(status.code() == Some(1));
1236 assert_eq!(stdout, Vec::new());
1237 assert!(!stderr.is_empty());
1238 }
1239
1240 #[test]
1241 #[cfg_attr(target_os = "android", ignore)]
1242 fn test_finish_once() {
1243 let mut prog = if cfg!(target_os = "windows") {
1244 Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
1245 } else {
1246 Command::new("false").spawn().unwrap()
1247 };
1248 assert!(prog.wait().unwrap().code() == Some(1));
1249 }
1250
1251 #[test]
1252 #[cfg_attr(target_os = "android", ignore)]
1253 fn test_finish_twice() {
1254 let mut prog = if cfg!(target_os = "windows") {
1255 Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
1256 } else {
1257 Command::new("false").spawn().unwrap()
1258 };
1259 assert!(prog.wait().unwrap().code() == Some(1));
1260 assert!(prog.wait().unwrap().code() == Some(1));
1261 }
1262
1263 #[test]
1264 #[cfg_attr(target_os = "android", ignore)]
1265 fn test_wait_with_output_once() {
1266 let prog = if cfg!(target_os = "windows") {
1267 Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap()
1268 } else {
1269 Command::new("echo").arg("hello").stdout(Stdio::piped()).spawn().unwrap()
1270 };
1271
1272 let Output {status, stdout, stderr} = prog.wait_with_output().unwrap();
1273 let output_str = str::from_utf8(&stdout).unwrap();
1274
1275 assert!(status.success());
1276 assert_eq!(output_str.trim().to_string(), "hello");
1277 assert_eq!(stderr, Vec::new());
1278 }
1279
1280 #[cfg(all(unix, not(target_os="android")))]
1281 pub fn env_cmd() -> Command {
1282 Command::new("env")
1283 }
1284 #[cfg(target_os="android")]
1285 pub fn env_cmd() -> Command {
1286 let mut cmd = Command::new("/system/bin/sh");
1287 cmd.arg("-c").arg("set");
1288 cmd
1289 }
1290
1291 #[cfg(windows)]
1292 pub fn env_cmd() -> Command {
1293 let mut cmd = Command::new("cmd");
1294 cmd.arg("/c").arg("set");
1295 cmd
1296 }
1297
1298 #[test]
1299 fn test_inherit_env() {
1300 use env;
1301
1302 let result = env_cmd().output().unwrap();
1303 let output = String::from_utf8(result.stdout).unwrap();
1304
1305 for (ref k, ref v) in env::vars() {
1306 // don't check android RANDOM variables
1307 if cfg!(target_os = "android") && *k == "RANDOM" {
1308 continue
1309 }
1310
1311 // Windows has hidden environment variables whose names start with
1312 // equals signs (`=`). Those do not show up in the output of the
1313 // `set` command.
1314 assert!((cfg!(windows) && k.starts_with("=")) ||
1315 k.starts_with("DYLD") ||
1316 output.contains(&format!("{}={}", *k, *v)) ||
1317 output.contains(&format!("{}='{}'", *k, *v)),
1318 "output doesn't contain `{}={}`\n{}",
1319 k, v, output);
1320 }
1321 }
1322
1323 #[test]
1324 fn test_override_env() {
1325 use env;
1326
1327 // In some build environments (such as chrooted Nix builds), `env` can
1328 // only be found in the explicitly-provided PATH env variable, not in
1329 // default places such as /bin or /usr/bin. So we need to pass through
1330 // PATH to our sub-process.
1331 let mut cmd = env_cmd();
1332 cmd.env_clear().env("RUN_TEST_NEW_ENV", "123");
1333 if let Some(p) = env::var_os("PATH") {
1334 cmd.env("PATH", &p);
1335 }
1336 let result = cmd.output().unwrap();
1337 let output = String::from_utf8_lossy(&result.stdout).to_string();
1338
1339 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1340 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1341 }
1342
1343 #[test]
1344 fn test_add_to_env() {
1345 let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
1346 let output = String::from_utf8_lossy(&result.stdout).to_string();
1347
1348 assert!(output.contains("RUN_TEST_NEW_ENV=123"),
1349 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
1350 }
1351
1352 // Regression tests for #30858.
1353 #[test]
1354 fn test_interior_nul_in_progname_is_error() {
1355 match Command::new("has-some-\0\0s-inside").spawn() {
1356 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1357 Ok(_) => panic!(),
1358 }
1359 }
1360
1361 #[test]
1362 fn test_interior_nul_in_arg_is_error() {
1363 match Command::new("echo").arg("has-some-\0\0s-inside").spawn() {
1364 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1365 Ok(_) => panic!(),
1366 }
1367 }
1368
1369 #[test]
1370 fn test_interior_nul_in_args_is_error() {
1371 match Command::new("echo").args(&["has-some-\0\0s-inside"]).spawn() {
1372 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1373 Ok(_) => panic!(),
1374 }
1375 }
1376
1377 #[test]
1378 fn test_interior_nul_in_current_dir_is_error() {
1379 match Command::new("echo").current_dir("has-some-\0\0s-inside").spawn() {
1380 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1381 Ok(_) => panic!(),
1382 }
1383 }
1384
1385 // Regression tests for #30862.
1386 #[test]
1387 fn test_interior_nul_in_env_key_is_error() {
1388 match env_cmd().env("has-some-\0\0s-inside", "value").spawn() {
1389 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1390 Ok(_) => panic!(),
1391 }
1392 }
1393
1394 #[test]
1395 fn test_interior_nul_in_env_value_is_error() {
1396 match env_cmd().env("key", "has-some-\0\0s-inside").spawn() {
1397 Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
1398 Ok(_) => panic!(),
1399 }
1400 }
1401
1402 /// Test that process creation flags work by debugging a process.
1403 /// Other creation flags make it hard or impossible to detect
1404 /// behavioral changes in the process.
1405 #[test]
1406 #[cfg(windows)]
1407 fn test_creation_flags() {
1408 use os::windows::process::CommandExt;
1409 use sys::c::{BOOL, DWORD, INFINITE};
1410 #[repr(C, packed)]
1411 struct DEBUG_EVENT {
1412 pub event_code: DWORD,
1413 pub process_id: DWORD,
1414 pub thread_id: DWORD,
1415 // This is a union in the real struct, but we don't
1416 // need this data for the purposes of this test.
1417 pub _junk: [u8; 164],
1418 }
1419
1420 extern "system" {
1421 fn WaitForDebugEvent(lpDebugEvent: *mut DEBUG_EVENT, dwMilliseconds: DWORD) -> BOOL;
1422 fn ContinueDebugEvent(dwProcessId: DWORD, dwThreadId: DWORD,
1423 dwContinueStatus: DWORD) -> BOOL;
1424 }
1425
1426 const DEBUG_PROCESS: DWORD = 1;
1427 const EXIT_PROCESS_DEBUG_EVENT: DWORD = 5;
1428 const DBG_EXCEPTION_NOT_HANDLED: DWORD = 0x80010001;
1429
1430 let mut child = Command::new("cmd")
1431 .creation_flags(DEBUG_PROCESS)
1432 .stdin(Stdio::piped()).spawn().unwrap();
1433 child.stdin.take().unwrap().write_all(b"exit\r\n").unwrap();
1434 let mut events = 0;
1435 let mut event = DEBUG_EVENT {
1436 event_code: 0,
1437 process_id: 0,
1438 thread_id: 0,
1439 _junk: [0; 164],
1440 };
1441 loop {
1442 if unsafe { WaitForDebugEvent(&mut event as *mut DEBUG_EVENT, INFINITE) } == 0 {
1443 panic!("WaitForDebugEvent failed!");
1444 }
1445 events += 1;
1446
1447 if event.event_code == EXIT_PROCESS_DEBUG_EVENT {
1448 break;
1449 }
1450
1451 if unsafe { ContinueDebugEvent(event.process_id,
1452 event.thread_id,
1453 DBG_EXCEPTION_NOT_HANDLED) } == 0 {
1454 panic!("ContinueDebugEvent failed!");
1455 }
1456 }
1457 assert!(events > 0);
1458 }
1459 }