subprocess/
popen.rs

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