1 use std::cell::RefCell;
2 use std::env;
3 use std::error::Error;
4 use std::ffi::{OsStr, OsString};
5 use std::fmt;
6 use std::fs::File;
7 use std::io;
8 use std::rc::Rc;
9 use std::result;
10 use std::time::Duration;
11 
12 use crate::communicate;
13 use crate::os_common::{ExitStatus, StandardStream};
14 
15 use self::ChildState::*;
16 
17 pub use self::os::ext as os_ext;
18 pub use self::os::make_pipe;
19 pub use communicate::Communicator;
20 
21 /// Interface to a running subprocess.
22 ///
23 /// `Popen` is the parent's interface to a created subprocess.  The
24 /// child process is started in the constructor, so owning a `Popen`
25 /// value indicates that the specified program has been successfully
26 /// launched.  To prevent accumulation of zombie processes, the child
27 /// is waited upon when a `Popen` goes out of scope, which can be
28 /// prevented using the [`detach`] method.
29 ///
30 /// Depending on how the subprocess was configured, its input, output, and
31 /// error streams can be connected to the parent and available as [`stdin`],
32 /// [`stdout`], and [`stderr`] public fields.  If you need to read the output
33 /// and errors into memory (or provide input as a memory slice), use the
34 /// [`communicate`] family of methods.
35 ///
36 /// `Popen` instances can be obtained with the [`create`] method, or
37 /// using the [`popen`] method of the [`Exec`] type.  Subprocesses
38 /// can be connected into pipes, most easily achieved using using
39 /// [`Exec`].
40 ///
41 /// [`Exec`]: struct.Exec.html
42 /// [`popen`]: struct.Exec.html#method.popen
43 /// [`stdin`]: struct.Popen.html#structfield.stdin
44 /// [`stdout`]: struct.Popen.html#structfield.stdout
45 /// [`stderr`]: struct.Popen.html#structfield.stderr
46 /// [`create`]: struct.Popen.html#method.create
47 /// [`communicate`]: struct.Popen.html#method.communicate
48 /// [`detach`]: struct.Popen.html#method.detach
49 
50 #[derive(Debug)]
51 pub struct Popen {
52     /// If `stdin` was specified as `Redirection::Pipe`, this will
53     /// contain a writeble `File` connected to the standard input of
54     /// the child process.
55     pub stdin: Option<File>,
56 
57     /// If `stdout` was specified as `Redirection::Pipe`, this will
58     /// contain a readable `File` connected to the standard output of
59     /// the child process.
60     pub stdout: Option<File>,
61 
62     /// If `stderr` was specified as `Redirection::Pipe`, this will
63     /// contain a readable `File` connected to the standard error of
64     /// the child process.
65     pub stderr: Option<File>,
66 
67     child_state: ChildState,
68     detached: bool,
69 }
70 
71 #[derive(Debug)]
72 enum ChildState {
73     Preparing, // only during construction
74     Running { pid: u32, ext: os::ExtChildState },
75     Finished(ExitStatus),
76 }
77 
78 /// Options for [`Popen::create`].
79 ///
80 /// When constructing `PopenConfig`, always use the [`Default`] trait,
81 /// such as:
82 ///
83 /// ```
84 /// # use subprocess::*;
85 /// # let argv = &["true"];
86 /// Popen::create(argv, PopenConfig {
87 ///      stdout: Redirection::Pipe,
88 ///      detached: true,
89 ///      // ... other fields you want to override ...
90 ///      ..Default::default()
91 /// })
92 /// # .unwrap();
93 /// ```
94 ///
95 /// This ensures that fields added later do not break existing code.
96 ///
97 /// An alternative to using `PopenConfig` directly is creating
98 /// processes using [`Exec`], a builder for `Popen`.
99 ///
100 /// [`Popen::create`]: struct.Popen.html#method.create
101 /// [`Exec`]: struct.Exec.html
102 /// [`Default`]: https://doc.rust-lang.org/core/default/trait.Default.html
103 
104 #[derive(Debug)]
105 pub struct PopenConfig {
106     /// How to configure the executed program's standard input.
107     pub stdin: Redirection,
108     /// How to configure the executed program's standard output.
109     pub stdout: Redirection,
110     /// How to configure the executed program's standard error.
111     pub stderr: Redirection,
112     /// Whether the `Popen` instance is initially detached.
113     pub detached: bool,
114 
115     /// Executable to run.
116     ///
117     /// If provided, this executable will be used to run the program
118     /// instead of `argv[0]`.  However, `argv[0]` will still be passed
119     /// to the subprocess, which will see that as `argv[0]`.  On some
120     /// Unix systems, `ps` will show the string passed as `argv[0]`,
121     /// even though `executable` is actually running.
122     pub executable: Option<OsString>,
123 
124     /// Environment variables to pass to the subprocess.
125     ///
126     /// If this is None, environment variables are inherited from the calling
127     /// process. Otherwise, the specified variables are used instead.
128     ///
129     /// Duplicates are eliminated, with the value taken from the
130     /// variable appearing later in the vector.
131     pub env: Option<Vec<(OsString, OsString)>>,
132 
133     /// Initial current working directory of the subprocess.
134     ///
135     /// None means inherit the working directory from the parent.
136     pub cwd: Option<OsString>,
137 
138     /// Set user ID for the subprocess.
139     ///
140     /// If specified, calls `setuid()` before execing the child process.
141     #[cfg(unix)]
142     pub setuid: Option<u32>,
143 
144     /// Set group ID for the subprocess.
145     ///
146     /// If specified, calls `setgid()` before execing the child process.
147     ///
148     /// Not to be confused with similarly named `setpgid`.
149     #[cfg(unix)]
150     pub setgid: Option<u32>,
151 
152     /// Make the subprocess belong to a new process group.
153     ///
154     /// If specified, calls `setpgid(0, 0)` before execing the child process.
155     ///
156     /// Not to be confused with similarly named `setgid`.
157     #[cfg(unix)]
158     pub setpgid: bool,
159 
160     // Add this field to force construction using ..Default::default() for
161     // backward compatibility.  Unfortunately we can't mark this non-public
162     // because then ..Default::default() wouldn't work either.
163     #[doc(hidden)]
164     pub _use_default_to_construct: (),
165 }
166 
167 impl PopenConfig {
168     /// Clone the underlying [`PopenConfig`], or return an error.
169     ///
170     /// This is guaranteed not to fail as long as no
171     /// [`Redirection::File`] variant is used for one of the standard
172     /// streams.  Otherwise, it fails if `File::try_clone` fails on
173     /// one of the `Redirection`s.
174     ///
175     /// [`PopenConfig`]: struct.PopenConfig.html
176     /// [`Redirection::File`]: enum.Redirection.html#variant.File
try_clone(&self) -> io::Result<PopenConfig>177     pub fn try_clone(&self) -> io::Result<PopenConfig> {
178         Ok(PopenConfig {
179             stdin: self.stdin.try_clone()?,
180             stdout: self.stdout.try_clone()?,
181             stderr: self.stderr.try_clone()?,
182             detached: self.detached,
183             executable: self.executable.as_ref().cloned(),
184             env: self.env.clone(),
185             cwd: self.cwd.clone(),
186             #[cfg(unix)]
187             setuid: self.setuid,
188             #[cfg(unix)]
189             setgid: self.setgid,
190             #[cfg(unix)]
191             setpgid: self.setpgid,
192             _use_default_to_construct: (),
193         })
194     }
195 
196     /// Returns the environment of the current process.
197     ///
198     /// The returned value is in the format accepted by the `env`
199     /// member of `PopenConfig`.
current_env() -> Vec<(OsString, OsString)>200     pub fn current_env() -> Vec<(OsString, OsString)> {
201         env::vars_os().collect()
202     }
203 }
204 
205 impl Default for PopenConfig {
default() -> PopenConfig206     fn default() -> PopenConfig {
207         PopenConfig {
208             stdin: Redirection::None,
209             stdout: Redirection::None,
210             stderr: Redirection::None,
211             detached: false,
212             executable: None,
213             env: None,
214             cwd: None,
215             #[cfg(unix)]
216             setuid: None,
217             #[cfg(unix)]
218             setgid: None,
219             #[cfg(unix)]
220             setpgid: false,
221             _use_default_to_construct: (),
222         }
223     }
224 }
225 
226 /// Instruction what to do with a stream in the child process.
227 ///
228 /// `Redirection` values are used for the `stdin`, `stdout`, and
229 /// `stderr` field of the `PopenConfig` struct.  They tell
230 /// `Popen::create` how to set up the standard streams in the child
231 /// process and the corresponding fields of the `Popen` struct in the
232 /// parent.
233 
234 #[derive(Debug)]
235 pub enum Redirection {
236     /// Do nothing with the stream.
237     ///
238     /// The stream is typically inherited from the parent.  The field
239     /// in `Popen` corresponding to the stream will be `None`.
240     None,
241 
242     /// Redirect the stream to a pipe.
243     ///
244     /// This variant requests that a stream be redirected to a
245     /// unidirectional pipe.  One end of the pipe is passed to the
246     /// child process and configured as one of its standard streams,
247     /// and the other end is available to the parent for communicating
248     /// with the child.
249     ///
250     /// The field with `Popen` corresponding to the stream will be
251     /// `Some(file)`, `File` being the parent's end of the pipe.
252     Pipe,
253 
254     /// Merge the stream to the other output stream.
255     ///
256     /// This variant is only valid when configuring redirection of
257     /// standard output and standard error.  Using
258     /// `Redirection::Merge` for `PopenConfig::stderr` requests the
259     /// child's stderr to refer to the same underlying file as the
260     /// child's stdout (which may or may not itself be redirected),
261     /// equivalent to the `2>&1` operator of the Bourne shell.
262     /// Analogously, using `Redirection::Merge` for
263     /// `PopenConfig::stdout` is equivalent to `1>&2` in the shell.
264     ///
265     /// Specifying `Redirection::Merge` for `PopenConfig::stdin` or
266     /// specifying it for both `stdout` and `stderr` is invalid and
267     /// will cause `Popen::create` to return
268     /// `Err(PopenError::LogicError)`.
269     ///
270     /// The field in `Popen` corresponding to the stream will be
271     /// `None`.
272     Merge,
273 
274     /// Redirect the stream to the specified open `File`.
275     ///
276     /// This does not create a pipe, it simply spawns the child so
277     /// that the specified stream sees that file.  The child can read
278     /// from or write to the provided file on its own, without any
279     /// intervention by the parent.
280     ///
281     /// The field in `Popen` corresponding to the stream will be
282     /// `None`.
283     File(File),
284 
285     /// Like `File`, but the file is specified as `Rc`.
286     ///
287     /// This allows the same file to be used in multiple redirections.
288     RcFile(Rc<File>),
289 }
290 
291 impl Redirection {
292     /// Clone the underlying `Redirection`, or return an error.
293     ///
294     /// Can fail in `File` variant.
try_clone(&self) -> io::Result<Redirection>295     pub fn try_clone(&self) -> io::Result<Redirection> {
296         Ok(match *self {
297             Redirection::None => Redirection::None,
298             Redirection::Pipe => Redirection::Pipe,
299             Redirection::Merge => Redirection::Merge,
300             Redirection::File(ref f) => Redirection::File(f.try_clone()?),
301             Redirection::RcFile(ref f) => Redirection::RcFile(Rc::clone(&f)),
302         })
303     }
304 }
305 
306 impl Popen {
307     /// Execute an external program in a new process.
308     ///
309     /// `argv` is a slice containing the program followed by its
310     /// arguments, such as `&["ps", "x"]`. `config` specifies details
311     /// how to create and interface to the process.
312     ///
313     /// For example, this launches the `cargo update` command:
314     ///
315     /// ```no_run
316     /// # use subprocess::*;
317     /// # fn dummy() -> Result<()> {
318     /// Popen::create(&["cargo", "update"], PopenConfig::default())?;
319     /// # Ok(())
320     /// # }
321     /// ```
322     ///
323     /// # Errors
324     ///
325     /// If the external program cannot be executed for any reason, an
326     /// error is returned.  The most typical reason for execution to
327     /// fail is that the program is missing on the `PATH`, but other
328     /// errors are also possible.  Note that this is distinct from the
329     /// program running and then exiting with a failure code - this
330     /// can be detected by calling the `wait` method to obtain its
331     /// exit status.
create(argv: &[impl AsRef<OsStr>], config: PopenConfig) -> Result<Popen>332     pub fn create(argv: &[impl AsRef<OsStr>], config: PopenConfig) -> Result<Popen> {
333         if argv.is_empty() {
334             return Err(PopenError::LogicError("argv must not be empty"));
335         }
336         let argv: Vec<OsString> = argv.iter().map(|p| p.as_ref().to_owned()).collect();
337         let mut inst = Popen {
338             stdin: None,
339             stdout: None,
340             stderr: None,
341             child_state: ChildState::Preparing,
342             detached: config.detached,
343         };
344         inst.os_start(argv, config)?;
345         Ok(inst)
346     }
347 
348     // Create the pipes requested by stdin, stdout, and stderr from
349     // the PopenConfig used to construct us, and return the Files to
350     // be given to the child process.
351     //
352     // For Redirection::Pipe, this stores the parent end of the pipe
353     // to the appropriate self.std* field, and returns the child end
354     // of the pipe.
355     //
356     // For Redirection::File, this transfers the ownership of the File
357     // to the corresponding child.
setup_streams( &mut self, stdin: Redirection, stdout: Redirection, stderr: Redirection, ) -> Result<(Option<Rc<File>>, Option<Rc<File>>, Option<Rc<File>>)>358     fn setup_streams(
359         &mut self,
360         stdin: Redirection,
361         stdout: Redirection,
362         stderr: Redirection,
363     ) -> Result<(Option<Rc<File>>, Option<Rc<File>>, Option<Rc<File>>)> {
364         fn prepare_pipe(
365             parent_writes: bool,
366             parent_ref: &mut Option<File>,
367             child_ref: &mut Option<Rc<File>>,
368         ) -> Result<()> {
369             // Store the parent's end of the pipe into the given
370             // reference, and store the child end.
371             let (read, write) = os::make_pipe()?;
372             let (parent_end, child_end) = if parent_writes {
373                 (write, read)
374             } else {
375                 (read, write)
376             };
377             os::set_inheritable(&parent_end, false)?;
378             *parent_ref = Some(parent_end);
379             *child_ref = Some(Rc::new(child_end));
380             Ok(())
381         }
382         fn prepare_file(file: File, child_ref: &mut Option<Rc<File>>) -> io::Result<()> {
383             // Make the File inheritable and store it for use in the child.
384             os::set_inheritable(&file, true)?;
385             *child_ref = Some(Rc::new(file));
386             Ok(())
387         }
388         fn prepare_rc_file(file: Rc<File>, child_ref: &mut Option<Rc<File>>) -> io::Result<()> {
389             // Like prepare_file, but for Rc<File>
390             os::set_inheritable(&file, true)?;
391             *child_ref = Some(file);
392             Ok(())
393         }
394         fn reuse_stream(
395             dest: &mut Option<Rc<File>>,
396             src: &mut Option<Rc<File>>,
397             src_id: StandardStream,
398         ) -> io::Result<()> {
399             // For Redirection::Merge, make stdout and stderr refer to
400             // the same File.  If the file is unavailable, use the
401             // appropriate system output stream.
402             if src.is_none() {
403                 *src = Some(get_standard_stream(src_id)?);
404             }
405             *dest = Some(Rc::clone(src.as_ref().unwrap()));
406             Ok(())
407         }
408 
409         enum MergeKind {
410             ErrToOut, // 2>&1
411             OutToErr, // 1>&2
412             None,
413         }
414         let mut merge: MergeKind = MergeKind::None;
415 
416         let (mut child_stdin, mut child_stdout, mut child_stderr) = (None, None, None);
417 
418         match stdin {
419             Redirection::Pipe => prepare_pipe(true, &mut self.stdin, &mut child_stdin)?,
420             Redirection::File(file) => prepare_file(file, &mut child_stdin)?,
421             Redirection::RcFile(file) => prepare_rc_file(file, &mut child_stdin)?,
422             Redirection::Merge => {
423                 return Err(PopenError::LogicError(
424                     "Redirection::Merge not valid for stdin",
425                 ));
426             }
427             Redirection::None => (),
428         };
429         match stdout {
430             Redirection::Pipe => prepare_pipe(false, &mut self.stdout, &mut child_stdout)?,
431             Redirection::File(file) => prepare_file(file, &mut child_stdout)?,
432             Redirection::RcFile(file) => prepare_rc_file(file, &mut child_stdout)?,
433             Redirection::Merge => merge = MergeKind::OutToErr,
434             Redirection::None => (),
435         };
436         match stderr {
437             Redirection::Pipe => prepare_pipe(false, &mut self.stderr, &mut child_stderr)?,
438             Redirection::File(file) => prepare_file(file, &mut child_stderr)?,
439             Redirection::RcFile(file) => prepare_rc_file(file, &mut child_stderr)?,
440             Redirection::Merge => merge = MergeKind::ErrToOut,
441             Redirection::None => (),
442         };
443 
444         // Handle Redirection::Merge after creating the output child
445         // streams.  Merge by cloning the child stream, or the
446         // appropriate standard stream if we don't have a child stream
447         // requested using Redirection::Pipe or Redirection::File.  In
448         // other words, 2>&1 (ErrToOut) is implemented by making
449         // child_stderr point to a dup of child_stdout, or of the OS's
450         // stdout stream.
451         match merge {
452             MergeKind::ErrToOut => {
453                 reuse_stream(&mut child_stderr, &mut child_stdout, StandardStream::Output)?
454             }
455             MergeKind::OutToErr => {
456                 reuse_stream(&mut child_stdout, &mut child_stderr, StandardStream::Error)?
457             }
458             MergeKind::None => (),
459         }
460 
461         Ok((child_stdin, child_stdout, child_stderr))
462     }
463 
464     /// Mark the process as detached.
465     ///
466     /// This method has no effect on the OS level, it simply tells
467     /// `Popen` not to wait for the subprocess to finish when going
468     /// out of scope.  If the child process has already finished, or
469     /// if it is guaranteed to finish before `Popen` goes out of
470     /// scope, calling `detach` has no effect.
detach(&mut self)471     pub fn detach(&mut self) {
472         self.detached = true;
473     }
474 
475     /// Return the PID of the subprocess, if it is known to be still running.
476     ///
477     /// Note that this method won't actually *check* whether the child
478     /// process is still running, it will only return the information
479     /// last set using one of `create`, `wait`, `wait_timeout`, or
480     /// `poll`.  For a newly created `Popen`, `pid()` always returns
481     /// `Some`.
pid(&self) -> Option<u32>482     pub fn pid(&self) -> Option<u32> {
483         match self.child_state {
484             Running { pid, .. } => Some(pid),
485             _ => None,
486         }
487     }
488 
489     /// Return the exit status of the subprocess, if it is known to have finished.
490     ///
491     /// Note that this method won't actually *check* whether the child
492     /// process has finished, it only returns the previously available
493     /// information.  To check or wait for the process to finish, call
494     /// `wait`, `wait_timeout`, or `poll`.
exit_status(&self) -> Option<ExitStatus>495     pub fn exit_status(&self) -> Option<ExitStatus> {
496         match self.child_state {
497             Finished(exit_status) => Some(exit_status),
498             _ => None,
499         }
500     }
501 
502     /// Prepare to communicate with the subprocess.
503     ///
504     /// Communicating refers to unattended data exchange with the subprocess.
505     /// During communication the given `input_data` is written to the
506     /// subprocess's standard input which is then closed, while simultaneously
507     /// its standard output and error streams are read until end-of-file is
508     /// reached.
509     ///
510     /// The difference between this and simply writing input data to
511     /// `self.stdin` and then reading output from `self.stdout` and
512     /// `self.stderr` is that the reading and the writing are performed
513     /// simultaneously.  A naive implementation that writes and then reads has
514     /// an issue when the subprocess responds to part of the input by
515     /// providing output.  The output must be read for the subprocess to
516     /// accept further input, but the parent process is still blocked on
517     /// writing the rest of the input daata.  Since neither process can
518     /// proceed, a deadlock occurs.  This is why a correct implementation must
519     /// write and read at the same time.
520     ///
521     /// This method does not perform the actual communication, it just sets it
522     /// up and returns a [`Communicator`].  Call the [`read`] or
523     /// [`read_string`] method on the `Communicator` to exchange data with the
524     /// subprocess.
525     ///
526     /// Compared to `communicate()` and `communicate_bytes()`, the
527     /// `Communicator` provides more control, such as timeout, read size
528     /// limit, and the ability to retrieve captured output in case of read
529     /// error.
530     ///
531     /// [`Communicator`]: struct.Communicator.html
532     /// [`read`]: struct.Communicator.html#method.read
533     /// [`read_string`]: struct.Communicator.html#method.read_string
communicate_start(&mut self, input_data: Option<Vec<u8>>) -> Communicator534     pub fn communicate_start(&mut self, input_data: Option<Vec<u8>>) -> Communicator {
535         communicate::communicate(
536             self.stdin.take(),
537             self.stdout.take(),
538             self.stderr.take(),
539             input_data,
540         )
541     }
542 
543     /// Feed the subprocess with input data and capture its output.
544     ///
545     /// This will write the provided `input_data` to the subprocess's standard
546     /// input, and simultaneously read its standard output and error.  The
547     /// output and error contents are returned as a pair of `Option<Vec<u8>>`.
548     /// The `None` options correspond to streams not specified as
549     /// `Redirection::Pipe` when creating the subprocess.
550     ///
551     /// This implementation reads and writes simultaneously, avoiding deadlock
552     /// in case the subprocess starts writing output before reading the whole
553     /// input - see [`communicate_start()`] for details.
554     ///
555     /// Note that this method does not wait for the subprocess to finish, only
556     /// to close its output/error streams.  It is rare but possible for the
557     /// program to continue running after having closed the streams, in which
558     /// case `Popen::Drop` will wait for it to finish.  If such a wait is
559     /// undesirable, it can be prevented by waiting explicitly using `wait()`,
560     /// by detaching the process using `detach()`, or by terminating it with
561     /// `terminate()`.
562     ///
563     /// For additional control over communication, such as timeout and size
564     /// limit, call [`communicate_start()`].
565     ///
566     /// # Panics
567     ///
568     /// If `input_data` is provided and `stdin` was not redirected to a pipe.
569     /// Also, if `input_data` is not provided and `stdin` was redirected to a
570     /// pipe.
571     ///
572     /// # Errors
573     ///
574     /// * `Err(::std::io::Error)` if a system call fails
575     ///
576     /// [`communicate_start()`]: struct.Popen.html#method.communicate_start
communicate_bytes( &mut self, input_data: Option<&[u8]>, ) -> io::Result<(Option<Vec<u8>>, Option<Vec<u8>>)>577     pub fn communicate_bytes(
578         &mut self,
579         input_data: Option<&[u8]>,
580     ) -> io::Result<(Option<Vec<u8>>, Option<Vec<u8>>)> {
581         self.communicate_start(input_data.map(|i| i.to_vec()))
582             .read()
583             .map_err(|e| e.error)
584     }
585 
586     /// Feed the subprocess with data and capture its output as string.
587     ///
588     /// This is a convenience method equivalent to [`communicate_bytes`], but
589     /// with input as `&str` and output as `String`.  Invalid UTF-8 sequences,
590     /// if found, are replaced with the the `U+FFFD` Unicode replacement
591     /// character.
592     ///
593     /// # Panics
594     ///
595     /// The same as with `communicate_bytes`.
596     ///
597     /// # Errors
598     ///
599     /// * `Err(::std::io::Error)` if a system call fails
600     ///
601     /// [`communicate_bytes`]: struct.Popen.html#method.communicate_bytes
communicate( &mut self, input_data: Option<&str>, ) -> io::Result<(Option<String>, Option<String>)>602     pub fn communicate(
603         &mut self,
604         input_data: Option<&str>,
605     ) -> io::Result<(Option<String>, Option<String>)> {
606         self.communicate_start(input_data.map(|s| s.as_bytes().to_vec()))
607             .read_string()
608             .map_err(|e| e.error)
609     }
610 
611     /// Check whether the process is still running, without blocking or errors.
612     ///
613     /// This checks whether the process is still running and if it
614     /// is still running, `None` is returned, otherwise
615     /// `Some(exit_status)`.  This method is guaranteed not to block
616     /// and is exactly equivalent to
617     /// `wait_timeout(Duration::from_secs(0)).unwrap_or(None)`.
poll(&mut self) -> Option<ExitStatus>618     pub fn poll(&mut self) -> Option<ExitStatus> {
619         self.wait_timeout(Duration::from_secs(0)).unwrap_or(None)
620     }
621 
622     /// Wait for the process to finish, and return its exit status.
623     ///
624     /// If the process has already finished, it will exit immediately,
625     /// returning the exit status.  Calling `wait` after that will
626     /// return the cached exit status without executing any system
627     /// calls.
628     ///
629     /// # Errors
630     ///
631     /// Returns an `Err` if a system call fails in an unpredicted way.
632     /// This should not happen in normal usage.
wait(&mut self) -> Result<ExitStatus>633     pub fn wait(&mut self) -> Result<ExitStatus> {
634         self.os_wait()
635     }
636 
637     /// Wait for the process to finish, timing out after the specified duration.
638     ///
639     /// This function behaves like `wait()`, except that the caller
640     /// will be blocked for roughly no longer than `dur`.  It returns
641     /// `Ok(None)` if the timeout is known to have elapsed.
642     ///
643     /// On Unix-like systems, timeout is implemented by calling
644     /// `waitpid(..., WNOHANG)` in a loop with adaptive sleep
645     /// intervals between iterations.
wait_timeout(&mut self, dur: Duration) -> Result<Option<ExitStatus>>646     pub fn wait_timeout(&mut self, dur: Duration) -> Result<Option<ExitStatus>> {
647         self.os_wait_timeout(dur)
648     }
649 
650     /// Terminate the subprocess.
651     ///
652     /// On Unix-like systems, this sends the `SIGTERM` signal to the
653     /// child process, which can be caught by the child in order to
654     /// perform cleanup before exiting.  On Windows, it is equivalent
655     /// to `kill()`.
terminate(&mut self) -> io::Result<()>656     pub fn terminate(&mut self) -> io::Result<()> {
657         self.os_terminate()
658     }
659 
660     /// Kill the subprocess.
661     ///
662     /// On Unix-like systems, this sends the `SIGKILL` signal to the
663     /// child process, which cannot be caught.
664     ///
665     /// On Windows, it invokes [`TerminateProcess`] on the process
666     /// handle with equivalent semantics.
667     ///
668     /// [`TerminateProcess`]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686714(v=vs.85).aspx
kill(&mut self) -> io::Result<()>669     pub fn kill(&mut self) -> io::Result<()> {
670         self.os_kill()
671     }
672 }
673 
674 trait PopenOs {
os_start(&mut self, argv: Vec<OsString>, config: PopenConfig) -> Result<()>675     fn os_start(&mut self, argv: Vec<OsString>, config: PopenConfig) -> Result<()>;
os_wait(&mut self) -> Result<ExitStatus>676     fn os_wait(&mut self) -> Result<ExitStatus>;
os_wait_timeout(&mut self, dur: Duration) -> Result<Option<ExitStatus>>677     fn os_wait_timeout(&mut self, dur: Duration) -> Result<Option<ExitStatus>>;
os_terminate(&mut self) -> io::Result<()>678     fn os_terminate(&mut self) -> io::Result<()>;
os_kill(&mut self) -> io::Result<()>679     fn os_kill(&mut self) -> io::Result<()>;
680 }
681 
682 #[cfg(unix)]
683 mod os {
684     use super::*;
685 
686     use crate::posix;
687     use std::collections::HashSet;
688     use std::ffi::OsString;
689     use std::fs::File;
690     use std::io::{self, Read, Write};
691     use std::os::unix::io::AsRawFd;
692     use std::time::{Duration, Instant};
693 
694     use crate::os_common::ExitStatus;
695     use crate::unix::PopenExt;
696 
697     pub type ExtChildState = ();
698 
699     impl super::PopenOs for Popen {
os_start(&mut self, argv: Vec<OsString>, config: PopenConfig) -> Result<()>700         fn os_start(&mut self, argv: Vec<OsString>, config: PopenConfig) -> Result<()> {
701             let mut exec_fail_pipe = posix::pipe()?;
702             set_inheritable(&exec_fail_pipe.0, false)?;
703             set_inheritable(&exec_fail_pipe.1, false)?;
704             {
705                 let child_ends = self.setup_streams(config.stdin, config.stdout, config.stderr)?;
706                 let child_env = config.env.as_deref().map(format_env);
707                 let cmd_to_exec = config.executable.as_ref().unwrap_or(&argv[0]);
708                 let just_exec = posix::prep_exec(cmd_to_exec, &argv, child_env.as_deref())?;
709                 unsafe {
710                     // unsafe because after the call to fork() the
711                     // child is not allowed to allocate
712                     match posix::fork()? {
713                         Some(child_pid) => {
714                             self.child_state = Running {
715                                 pid: child_pid,
716                                 ext: (),
717                             };
718                         }
719                         None => {
720                             drop(exec_fail_pipe.0);
721                             let result = Popen::do_exec(
722                                 just_exec,
723                                 child_ends,
724                                 config.cwd.as_deref(),
725                                 config.setuid,
726                                 config.setgid,
727                                 config.setpgid,
728                             );
729                             // If we are here, it means that exec has failed.  Notify
730                             // the parent and exit.
731                             let error_code = match result {
732                                 Ok(()) => unreachable!(),
733                                 Err(e) => e.raw_os_error().unwrap_or(-1),
734                             } as u32;
735                             exec_fail_pipe
736                                 .1
737                                 .write_all(&[
738                                     error_code as u8,
739                                     (error_code >> 8) as u8,
740                                     (error_code >> 16) as u8,
741                                     (error_code >> 24) as u8,
742                                 ])
743                                 .ok();
744                             posix::_exit(127);
745                         }
746                     }
747                 }
748             }
749             drop(exec_fail_pipe.1);
750             let mut error_buf = [0u8; 4];
751             let read_cnt = exec_fail_pipe.0.read(&mut error_buf)?;
752             if read_cnt == 0 {
753                 Ok(())
754             } else if read_cnt == 4 {
755                 let error_code: u32 = error_buf[0] as u32
756                     | (error_buf[1] as u32) << 8
757                     | (error_buf[2] as u32) << 16
758                     | (error_buf[3] as u32) << 24;
759                 Err(PopenError::from(io::Error::from_raw_os_error(
760                     error_code as i32,
761                 )))
762             } else {
763                 Err(PopenError::LogicError("invalid read_count from exec pipe"))
764             }
765         }
766 
os_wait(&mut self) -> Result<ExitStatus>767         fn os_wait(&mut self) -> Result<ExitStatus> {
768             while let Running { .. } = self.child_state {
769                 self.waitpid(true)?;
770             }
771             Ok(self.exit_status().unwrap())
772         }
773 
os_wait_timeout(&mut self, dur: Duration) -> Result<Option<ExitStatus>>774         fn os_wait_timeout(&mut self, dur: Duration) -> Result<Option<ExitStatus>> {
775             use std::cmp::min;
776 
777             if let Finished(exit_status) = self.child_state {
778                 return Ok(Some(exit_status));
779             }
780 
781             let deadline = Instant::now() + dur;
782             // double delay at every iteration, maxing at 100ms
783             let mut delay = Duration::from_millis(1);
784 
785             loop {
786                 self.waitpid(false)?;
787                 if let Finished(exit_status) = self.child_state {
788                     return Ok(Some(exit_status));
789                 }
790                 let now = Instant::now();
791                 if now >= deadline {
792                     return Ok(None);
793                 }
794                 let remaining = deadline.duration_since(now);
795                 ::std::thread::sleep(min(delay, remaining));
796                 delay = min(delay * 2, Duration::from_millis(100));
797             }
798         }
799 
os_terminate(&mut self) -> io::Result<()>800         fn os_terminate(&mut self) -> io::Result<()> {
801             self.send_signal(posix::SIGTERM)
802         }
803 
os_kill(&mut self) -> io::Result<()>804         fn os_kill(&mut self) -> io::Result<()> {
805             self.send_signal(posix::SIGKILL)
806         }
807     }
808 
format_env(env: &[(OsString, OsString)]) -> Vec<OsString>809     fn format_env(env: &[(OsString, OsString)]) -> Vec<OsString> {
810         // Convert Vec of (key, val) pairs to Vec of key=val, as required by
811         // execvpe.  Eliminate dups, in favor of later-appearing entries.
812         let mut seen = HashSet::<&OsStr>::new();
813         let mut formatted: Vec<_> = env
814             .iter()
815             .rev()
816             .filter(|&(k, _)| seen.insert(k))
817             .map(|(k, v)| {
818                 let mut fmt = k.clone();
819                 fmt.push("=");
820                 fmt.push(v);
821                 fmt
822             })
823             .collect();
824         formatted.reverse();
825         formatted
826     }
827 
828     trait PopenOsImpl: super::PopenOs {
do_exec( just_exec: impl FnOnce() -> io::Result<()>, child_ends: (Option<Rc<File>>, Option<Rc<File>>, Option<Rc<File>>), cwd: Option<&OsStr>, setuid: Option<u32>, setgid: Option<u32>, setpgid: bool, ) -> io::Result<()>829         fn do_exec(
830             just_exec: impl FnOnce() -> io::Result<()>,
831             child_ends: (Option<Rc<File>>, Option<Rc<File>>, Option<Rc<File>>),
832             cwd: Option<&OsStr>,
833             setuid: Option<u32>,
834             setgid: Option<u32>,
835             setpgid: bool,
836         ) -> io::Result<()>;
waitpid(&mut self, block: bool) -> io::Result<()>837         fn waitpid(&mut self, block: bool) -> io::Result<()>;
838     }
839 
840     impl PopenOsImpl for Popen {
do_exec( just_exec: impl FnOnce() -> io::Result<()>, child_ends: (Option<Rc<File>>, Option<Rc<File>>, Option<Rc<File>>), cwd: Option<&OsStr>, setuid: Option<u32>, setgid: Option<u32>, setpgid: bool, ) -> io::Result<()>841         fn do_exec(
842             just_exec: impl FnOnce() -> io::Result<()>,
843             child_ends: (Option<Rc<File>>, Option<Rc<File>>, Option<Rc<File>>),
844             cwd: Option<&OsStr>,
845             setuid: Option<u32>,
846             setgid: Option<u32>,
847             setpgid: bool,
848         ) -> io::Result<()> {
849             if let Some(cwd) = cwd {
850                 env::set_current_dir(cwd)?;
851             }
852 
853             let (stdin, stdout, stderr) = child_ends;
854             if let Some(stdin) = stdin {
855                 if stdin.as_raw_fd() != 0 {
856                     posix::dup2(stdin.as_raw_fd(), 0)?;
857                 }
858             }
859             if let Some(stdout) = stdout {
860                 if stdout.as_raw_fd() != 1 {
861                     posix::dup2(stdout.as_raw_fd(), 1)?;
862                 }
863             }
864             if let Some(stderr) = stderr {
865                 if stderr.as_raw_fd() != 2 {
866                     posix::dup2(stderr.as_raw_fd(), 2)?;
867                 }
868             }
869             posix::reset_sigpipe()?;
870 
871             if let Some(uid) = setuid {
872                 posix::setuid(uid)?;
873             }
874             if let Some(gid) = setgid {
875                 posix::setgid(gid)?;
876             }
877             if setpgid {
878                 posix::setpgid(0, 0)?;
879             }
880             just_exec()?;
881             unreachable!();
882         }
883 
waitpid(&mut self, block: bool) -> io::Result<()>884         fn waitpid(&mut self, block: bool) -> io::Result<()> {
885             match self.child_state {
886                 Preparing => panic!("child_state == Preparing"),
887                 Running { pid, .. } => {
888                     match posix::waitpid(pid, if block { 0 } else { posix::WNOHANG }) {
889                         Err(e) => {
890                             if let Some(errno) = e.raw_os_error() {
891                                 if errno == posix::ECHILD {
892                                     // Someone else has waited for the child
893                                     // (another thread, a signal handler...).
894                                     // The PID no longer exists and we cannot
895                                     // find its exit status.
896                                     self.child_state = Finished(ExitStatus::Undetermined);
897                                     return Ok(());
898                                 }
899                             }
900                             return Err(e);
901                         }
902                         Ok((pid_out, exit_status)) => {
903                             if pid_out == pid {
904                                 self.child_state = Finished(exit_status);
905                             }
906                         }
907                     }
908                 }
909                 Finished(..) => (),
910             }
911             Ok(())
912         }
913     }
914 
set_inheritable(f: &File, inheritable: bool) -> io::Result<()>915     pub fn set_inheritable(f: &File, inheritable: bool) -> io::Result<()> {
916         if inheritable {
917             // Unix pipes are inheritable by default.
918         } else {
919             let fd = f.as_raw_fd();
920             let old = posix::fcntl(fd, posix::F_GETFD, None)?;
921             posix::fcntl(fd, posix::F_SETFD, Some(old | posix::FD_CLOEXEC))?;
922         }
923         Ok(())
924     }
925 
926     /// Create a pipe.
927     ///
928     /// This is a safe wrapper over `libc::pipe` or
929     /// `winapi::um::namedpipeapi::CreatePipe`, depending on the operating
930     /// system.
make_pipe() -> io::Result<(File, File)>931     pub fn make_pipe() -> io::Result<(File, File)> {
932         posix::pipe()
933     }
934 
935     pub mod ext {
936         use crate::popen::ChildState::*;
937         use crate::popen::Popen;
938         use crate::posix;
939         use std::io;
940 
941         /// Unix-specific extension methods for `Popen`
942         pub trait PopenExt {
943             /// Send the specified signal to the child process.
944             ///
945             /// The signal numbers are best obtained from the [`libc`]
946             /// crate.
947             ///
948             /// If the child process is known to have finished (due to e.g.
949             /// a previous call to [`wait`] or [`poll`]), this will do
950             /// nothing and return `Ok`.
951             ///
952             /// [`poll`]: ../struct.Popen.html#method.poll
953             /// [`wait`]: ../struct.Popen.html#method.wait
954             /// [`libc`]: https://docs.rs/libc/
send_signal(&self, signal: i32) -> io::Result<()>955             fn send_signal(&self, signal: i32) -> io::Result<()>;
956         }
957         impl PopenExt for Popen {
send_signal(&self, signal: i32) -> io::Result<()>958             fn send_signal(&self, signal: i32) -> io::Result<()> {
959                 match self.child_state {
960                     Preparing => panic!("child_state == Preparing"),
961                     Running { pid, .. } => posix::kill(pid, signal),
962                     Finished(..) => Ok(()),
963                 }
964             }
965         }
966     }
967 }
968 
969 #[cfg(windows)]
970 mod os {
971     use super::*;
972 
973     use std::collections::HashSet;
974     use std::env;
975     use std::ffi::{OsStr, OsString};
976     use std::fs::{self, File};
977     use std::io;
978     use std::os::windows::ffi::{OsStrExt, OsStringExt};
979     use std::os::windows::io::{AsRawHandle, RawHandle};
980     use std::time::Duration;
981 
982     use crate::os_common::{ExitStatus, StandardStream};
983     use crate::win32;
984 
985     #[derive(Debug)]
986     pub struct ExtChildState(win32::Handle);
987 
988     impl super::PopenOs for Popen {
os_start(&mut self, argv: Vec<OsString>, config: PopenConfig) -> Result<()>989         fn os_start(&mut self, argv: Vec<OsString>, config: PopenConfig) -> Result<()> {
990             fn raw(opt: &Option<Rc<File>>) -> Option<RawHandle> {
991                 opt.as_ref().map(|f| f.as_raw_handle())
992             }
993             let (mut child_stdin, mut child_stdout, mut child_stderr) =
994                 self.setup_streams(config.stdin, config.stdout, config.stderr)?;
995             ensure_child_stream(&mut child_stdin, StandardStream::Input)?;
996             ensure_child_stream(&mut child_stdout, StandardStream::Output)?;
997             ensure_child_stream(&mut child_stderr, StandardStream::Error)?;
998             let cmdline = assemble_cmdline(argv)?;
999             let env_block = config.env.map(|env| format_env_block(&env));
1000             // CreateProcess doesn't search for appname in the PATH.
1001             // We do it ourselves to match the Unix behavior.
1002             let executable = config.executable.map(locate_in_path);
1003             let (handle, pid) = win32::CreateProcess(
1004                 executable.as_ref().map(OsString::as_ref),
1005                 &cmdline,
1006                 &env_block,
1007                 &config.cwd.as_deref(),
1008                 true,
1009                 0,
1010                 raw(&child_stdin),
1011                 raw(&child_stdout),
1012                 raw(&child_stderr),
1013                 win32::STARTF_USESTDHANDLES,
1014             )?;
1015             self.child_state = Running {
1016                 pid: pid as u32,
1017                 ext: ExtChildState(handle),
1018             };
1019             Ok(())
1020         }
1021 
os_wait(&mut self) -> Result<ExitStatus>1022         fn os_wait(&mut self) -> Result<ExitStatus> {
1023             self.wait_handle(None)?;
1024             match self.child_state {
1025                 Preparing => panic!("child_state == Preparing"),
1026                 Finished(exit_status) => Ok(exit_status),
1027                 // Since we invoked wait_handle without timeout, exit
1028                 // status should exist at this point.  The only way
1029                 // for it not to exist would be if something strange
1030                 // happened, like WaitForSingleObject returning
1031                 // something other than OBJECT_0.
1032                 Running { .. } => Err(PopenError::LogicError("Failed to obtain exit status")),
1033             }
1034         }
1035 
os_wait_timeout(&mut self, dur: Duration) -> Result<Option<ExitStatus>>1036         fn os_wait_timeout(&mut self, dur: Duration) -> Result<Option<ExitStatus>> {
1037             if let Finished(exit_status) = self.child_state {
1038                 return Ok(Some(exit_status));
1039             }
1040             self.wait_handle(Some(dur))?;
1041             Ok(self.exit_status())
1042         }
1043 
os_terminate(&mut self) -> io::Result<()>1044         fn os_terminate(&mut self) -> io::Result<()> {
1045             let mut new_child_state = None;
1046             if let Running {
1047                 ext: ExtChildState(ref handle),
1048                 ..
1049             } = self.child_state
1050             {
1051                 match win32::TerminateProcess(handle, 1) {
1052                     Err(err) => {
1053                         if err.raw_os_error() != Some(win32::ERROR_ACCESS_DENIED as i32) {
1054                             return Err(err);
1055                         }
1056                         let rc = win32::GetExitCodeProcess(handle)?;
1057                         if rc == win32::STILL_ACTIVE {
1058                             return Err(err);
1059                         }
1060                         new_child_state = Some(Finished(ExitStatus::Exited(rc)));
1061                     }
1062                     Ok(_) => (),
1063                 }
1064             }
1065             if let Some(new_child_state) = new_child_state {
1066                 self.child_state = new_child_state;
1067             }
1068             Ok(())
1069         }
1070 
os_kill(&mut self) -> io::Result<()>1071         fn os_kill(&mut self) -> io::Result<()> {
1072             self.terminate()
1073         }
1074     }
1075 
format_env_block(env: &[(OsString, OsString)]) -> Vec<u16>1076     fn format_env_block(env: &[(OsString, OsString)]) -> Vec<u16> {
1077         fn to_uppercase(s: &OsStr) -> OsString {
1078             OsString::from_wide(
1079                 &s.encode_wide()
1080                     .map(|c| {
1081                         if c < 128 {
1082                             (c as u8 as char).to_ascii_uppercase() as u16
1083                         } else {
1084                             c
1085                         }
1086                     })
1087                     .collect::<Vec<_>>(),
1088             )
1089         }
1090         let mut pruned: Vec<_> = {
1091             let mut seen = HashSet::<OsString>::new();
1092             env.iter()
1093                 .rev()
1094                 .filter(|&(k, _)| seen.insert(to_uppercase(k)))
1095                 .collect()
1096         };
1097         pruned.reverse();
1098         let mut block = vec![];
1099         for (k, v) in pruned {
1100             block.extend(k.encode_wide());
1101             block.push('=' as u16);
1102             block.extend(v.encode_wide());
1103             block.push(0);
1104         }
1105         block.push(0);
1106         block
1107     }
1108 
1109     trait PopenOsImpl {
wait_handle(&mut self, timeout: Option<Duration>) -> io::Result<Option<ExitStatus>>1110         fn wait_handle(&mut self, timeout: Option<Duration>) -> io::Result<Option<ExitStatus>>;
1111     }
1112 
1113     impl PopenOsImpl for Popen {
wait_handle(&mut self, timeout: Option<Duration>) -> io::Result<Option<ExitStatus>>1114         fn wait_handle(&mut self, timeout: Option<Duration>) -> io::Result<Option<ExitStatus>> {
1115             let mut new_child_state = None;
1116             if let Running {
1117                 ext: ExtChildState(ref handle),
1118                 ..
1119             } = self.child_state
1120             {
1121                 let event = win32::WaitForSingleObject(handle, timeout)?;
1122                 if let win32::WaitEvent::OBJECT_0 = event {
1123                     let exit_code = win32::GetExitCodeProcess(handle)?;
1124                     new_child_state = Some(Finished(ExitStatus::Exited(exit_code)));
1125                 }
1126             }
1127             if let Some(new_child_state) = new_child_state {
1128                 self.child_state = new_child_state;
1129             }
1130             Ok(self.exit_status())
1131         }
1132     }
1133 
ensure_child_stream(stream: &mut Option<Rc<File>>, which: StandardStream) -> io::Result<()>1134     fn ensure_child_stream(stream: &mut Option<Rc<File>>, which: StandardStream) -> io::Result<()> {
1135         // If no stream is sent to CreateProcess, the child doesn't
1136         // get a valid stream.  This results in e.g.
1137         // Exec("sh").arg("-c").arg("echo foo >&2").stream_stderr()
1138         // failing because the shell tries to redirect stdout to
1139         // stderr, but fails because it didn't receive a valid stdout.
1140         if stream.is_none() {
1141             *stream = Some(get_standard_stream(which)?);
1142         }
1143         Ok(())
1144     }
1145 
set_inheritable(f: &File, inheritable: bool) -> io::Result<()>1146     pub fn set_inheritable(f: &File, inheritable: bool) -> io::Result<()> {
1147         win32::SetHandleInformation(
1148             f,
1149             win32::HANDLE_FLAG_INHERIT,
1150             if inheritable { 1 } else { 0 },
1151         )?;
1152         Ok(())
1153     }
1154 
1155     /// Create a pipe.
1156     ///
1157     /// This is a safe wrapper over `libc::pipe` or
1158     /// `winapi::um::namedpipeapi::CreatePipe`, depending on the operating
1159     /// system.
make_pipe() -> io::Result<(File, File)>1160     pub fn make_pipe() -> io::Result<(File, File)> {
1161         win32::CreatePipe(true)
1162     }
1163 
locate_in_path(executable: OsString) -> OsString1164     fn locate_in_path(executable: OsString) -> OsString {
1165         if let Some(path) = env::var_os("PATH") {
1166             for path in env::split_paths(&path) {
1167                 let path = path
1168                     .join(&executable)
1169                     .with_extension(::std::env::consts::EXE_EXTENSION);
1170                 if fs::metadata(&path).is_ok() {
1171                     return path.into_os_string();
1172                 }
1173             }
1174         }
1175         executable
1176     }
1177 
assemble_cmdline(argv: Vec<OsString>) -> io::Result<OsString>1178     fn assemble_cmdline(argv: Vec<OsString>) -> io::Result<OsString> {
1179         let mut cmdline = vec![];
1180         let mut is_first = true;
1181         for arg in argv {
1182             if !is_first {
1183                 cmdline.push(' ' as u16);
1184             } else {
1185                 is_first = false;
1186             }
1187             if arg.encode_wide().any(|c| c == 0) {
1188                 return Err(io::Error::from_raw_os_error(
1189                     win32::ERROR_BAD_PATHNAME as i32,
1190                 ));
1191             }
1192             append_quoted(&arg, &mut cmdline);
1193         }
1194         Ok(OsString::from_wide(&cmdline))
1195     }
1196 
1197     // Translated from ArgvQuote at http://tinyurl.com/zmgtnls
append_quoted(arg: &OsStr, cmdline: &mut Vec<u16>)1198     fn append_quoted(arg: &OsStr, cmdline: &mut Vec<u16>) {
1199         if !arg.is_empty()
1200             && !arg.encode_wide().any(|c| {
1201                 c == ' ' as u16
1202                     || c == '\t' as u16
1203                     || c == '\n' as u16
1204                     || c == '\x0b' as u16
1205                     || c == '\"' as u16
1206             })
1207         {
1208             cmdline.extend(arg.encode_wide());
1209             return;
1210         }
1211         cmdline.push('"' as u16);
1212 
1213         let arg: Vec<_> = arg.encode_wide().collect();
1214         let mut i = 0;
1215         while i < arg.len() {
1216             let mut num_backslashes = 0;
1217             while i < arg.len() && arg[i] == '\\' as u16 {
1218                 i += 1;
1219                 num_backslashes += 1;
1220             }
1221 
1222             if i == arg.len() {
1223                 for _ in 0..num_backslashes * 2 {
1224                     cmdline.push('\\' as u16);
1225                 }
1226                 break;
1227             } else if arg[i] == b'"' as u16 {
1228                 for _ in 0..num_backslashes * 2 + 1 {
1229                     cmdline.push('\\' as u16);
1230                 }
1231                 cmdline.push(arg[i]);
1232             } else {
1233                 for _ in 0..num_backslashes {
1234                     cmdline.push('\\' as u16);
1235                 }
1236                 cmdline.push(arg[i]);
1237             }
1238             i += 1;
1239         }
1240         cmdline.push('"' as u16);
1241     }
1242 
1243     pub mod ext {}
1244 }
1245 
1246 impl Drop for Popen {
1247     // Wait for the process to exit.  To avoid the wait, call
1248     // detach().
drop(&mut self)1249     fn drop(&mut self) {
1250         if let (false, &Running { .. }) = (self.detached, &self.child_state) {
1251             // Should we log error if one occurs during drop()?
1252             self.wait().ok();
1253         }
1254     }
1255 }
1256 
1257 thread_local! {
1258     static STREAMS: RefCell<[Option<Rc<File>>; 3]> = RefCell::default();
1259 }
1260 
1261 #[cfg(unix)]
1262 use crate::posix::make_standard_stream;
1263 #[cfg(windows)]
1264 use crate::win32::make_standard_stream;
1265 
get_standard_stream(which: StandardStream) -> io::Result<Rc<File>>1266 fn get_standard_stream(which: StandardStream) -> io::Result<Rc<File>> {
1267     STREAMS.with(|streams| {
1268         if let Some(ref stream) = streams.borrow()[which as usize] {
1269             return Ok(Rc::clone(&stream));
1270         }
1271         let stream = make_standard_stream(which)?;
1272         streams.borrow_mut()[which as usize] = Some(Rc::clone(&stream));
1273         Ok(stream)
1274     })
1275 }
1276 
1277 /// Error in [`Popen`] calls.
1278 ///
1279 /// [`Popen`]: struct.Popen.html
1280 
1281 #[derive(Debug)]
1282 #[non_exhaustive]
1283 pub enum PopenError {
1284     /// An IO system call failed while executing the requested operation.
1285     IoError(io::Error),
1286     /// A logical error was made, e.g. invalid arguments detected at run-time.
1287     LogicError(&'static str),
1288 }
1289 
1290 impl From<io::Error> for PopenError {
from(err: io::Error) -> PopenError1291     fn from(err: io::Error) -> PopenError {
1292         PopenError::IoError(err)
1293     }
1294 }
1295 
1296 impl From<communicate::CommunicateError> for PopenError {
from(err: communicate::CommunicateError) -> PopenError1297     fn from(err: communicate::CommunicateError) -> PopenError {
1298         PopenError::IoError(err.error)
1299     }
1300 }
1301 
1302 impl Error for PopenError {
source(&self) -> Option<&(dyn Error + 'static)>1303     fn source(&self) -> Option<&(dyn Error + 'static)> {
1304         match *self {
1305             PopenError::IoError(ref err) => Some(err),
1306             PopenError::LogicError(_msg) => None,
1307         }
1308     }
1309 }
1310 
1311 impl fmt::Display for PopenError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1312     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1313         match *self {
1314             PopenError::IoError(ref err) => fmt::Display::fmt(err, f),
1315             PopenError::LogicError(desc) => f.write_str(desc),
1316         }
1317     }
1318 }
1319 
1320 /// Result returned by calls in the `subprocess` crate in places where
1321 /// `::std::io::Result` does not suffice.
1322 pub type Result<T> = result::Result<T, PopenError>;
1323