brush_core/sys/unix/
commands.rs

1//! Command execution utilities.
2
3pub use std::os::unix::process::CommandExt;
4pub use std::os::unix::process::ExitStatusExt;
5
6use command_fds::{CommandFdExt, FdMapping};
7
8use crate::ShellFd;
9use crate::error;
10use crate::openfiles;
11
12/// Extension trait for injecting file descriptors into commands.
13pub trait CommandFdInjectionExt {
14    /// Injects the given open files as file descriptors into the command.
15    ///
16    /// # Arguments
17    ///
18    /// * `open_files` - A mapping of child file descriptors to open files.
19    fn inject_fds(
20        &mut self,
21        open_files: impl Iterator<Item = (ShellFd, openfiles::OpenFile)>,
22    ) -> Result<(), error::Error>;
23}
24
25impl CommandFdInjectionExt for std::process::Command {
26    fn inject_fds(
27        &mut self,
28        open_files: impl Iterator<Item = (ShellFd, openfiles::OpenFile)>,
29    ) -> Result<(), error::Error> {
30        let fd_mappings = open_files
31            .map(|(child_fd, open_file)| FdMapping {
32                child_fd,
33                parent_fd: open_file.into_owned_fd().unwrap(),
34            })
35            .collect();
36        self.fd_mappings(fd_mappings)
37            .map_err(|_e| error::ErrorKind::ChildCreationFailure)?;
38
39        Ok(())
40    }
41}
42
43/// Extension trait for arranging for commands to take the foreground.
44pub trait CommandFgControlExt {
45    /// Arranges for the command to take the foreground when it is executed.
46    fn take_foreground(&mut self);
47}
48
49impl CommandFgControlExt for std::process::Command {
50    fn take_foreground(&mut self) {
51        // SAFETY:
52        // This arranges for a provided function to run in the context of
53        // the forked process before it exec's the target command. In general,
54        // rust can't guarantee safety of code running in such a context.
55        unsafe {
56            self.pre_exec(setup_process_before_exec);
57        }
58    }
59}
60
61fn setup_process_before_exec() -> Result<(), std::io::Error> {
62    use crate::sys;
63
64    sys::terminal::move_self_to_foreground().map_err(std::io::Error::other)?;
65    Ok(())
66}