bootc_internal_utils/
reexec.rs

1use std::os::unix::process::CommandExt;
2use std::path::PathBuf;
3use std::process::Command;
4
5use anyhow::Result;
6
7/// Environment variable holding a reference to our original binary
8pub const ORIG: &str = "_BOOTC_ORIG_EXE";
9
10/// Return the path to our own executable. In some cases (SELinux) we may have
11/// performed a re-exec with a temporary copy of the binary and
12/// this environment variable will hold the path to the original binary.
13pub fn executable_path() -> Result<PathBuf> {
14    if let Some(p) = std::env::var_os(ORIG) {
15        Ok(p.into())
16    } else {
17        std::env::current_exe().map_err(Into::into)
18    }
19}
20
21/// Re-execute the current process if the provided environment variable is not set.
22pub fn reexec_with_guardenv(k: &str, prefix_args: &[&str]) -> Result<()> {
23    if std::env::var_os(k).is_some() {
24        tracing::trace!("Skipping re-exec due to env var {k}");
25        return Ok(());
26    }
27    let self_exe = executable_path()?;
28    let mut prefix_args = prefix_args.iter();
29    let mut cmd = if let Some(p) = prefix_args.next() {
30        let mut c = Command::new(p);
31        c.args(prefix_args);
32        c.arg(self_exe);
33        c
34    } else {
35        Command::new(self_exe)
36    };
37    cmd.env(k, "1");
38    cmd.args(std::env::args_os().skip(1));
39    cmd.arg0(crate::NAME);
40    tracing::debug!("Re-executing current process for {k}");
41    Err(cmd.exec().into())
42}