Skip to content

Commit 60af1b5

Browse files
committed
rust: intercept wrapper finds the right executable
1 parent 744ccc3 commit 60af1b5

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

rust/intercept/src/bin/wrapper.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::path::{Path, PathBuf};
2727
fn main() -> Result<()> {
2828
env_logger::init();
2929
// Find out what is the executable name the execution was started with
30-
let executable = std::env::args().next().unwrap();
30+
let executable = file_name_from_arguments()?;
3131
log::info!("Executable as called: {:?}", executable);
3232
// Read the PATH variable and find the next executable with the same name
3333
let real_executable = next_in_path(&executable)?;
@@ -48,19 +48,43 @@ fn main() -> Result<()> {
4848
std::process::exit(status.code().unwrap_or(1));
4949
}
5050

51+
/// Get the file name of the executable from the arguments.
52+
///
53+
/// Since the executable will be called via soft link, the first argument
54+
/// will be the name of the soft link. This function returns the file name
55+
/// of the soft link.
56+
fn file_name_from_arguments() -> Result<PathBuf> {
57+
std::env::args().next()
58+
.ok_or_else(|| anyhow::anyhow!("Cannot get first argument"))
59+
.and_then(|arg| match PathBuf::from(arg).file_name() {
60+
Some(file_name) => Ok(PathBuf::from(file_name)),
61+
None => Err(anyhow::anyhow!("Cannot get the file name from the argument")),
62+
})
63+
}
64+
5165
/// Find the next executable in the PATH variable.
5266
///
5367
/// The function reads the PATH variable and tries to find the next executable
5468
/// with the same name as the given executable. It returns the path to the
5569
/// executable.
56-
fn next_in_path(executable: &String) -> Result<PathBuf> {
70+
fn next_in_path(target: &Path) -> Result<PathBuf> {
5771
let path = std::env::var("PATH")?;
72+
log::debug!("PATH: {}", path);
73+
// The `current_exe` is a canonical path to the current executable.
5874
let current_exe = std::env::current_exe()?;
5975

6076
path.split(':')
61-
.map(|dir| Path::new(dir).join(&executable))
62-
.filter(|path| path.is_file())// TODO: check if it is executable
63-
.filter(|path| path != &current_exe)
77+
.map(|dir| Path::new(dir).join(target))
78+
.filter(|path| path.is_file()) // TODO: check if it is executable
79+
.filter(|path| {
80+
// We need to compare it with the real path of the candidate executable to avoid
81+
// calling the same executable again.
82+
let real_path = match path.canonicalize() {
83+
Ok(path) => path,
84+
Err(_) => return false,
85+
};
86+
real_path != current_exe
87+
})
6488
.nth(0)
6589
.ok_or_else(|| anyhow::anyhow!("Cannot find the real executable"))
6690
}

0 commit comments

Comments
 (0)