From 32fa7cbda8afc17da644088ad726cec62ac3228d Mon Sep 17 00:00:00 2001 From: Diego Giagio Date: Mon, 15 Oct 2018 02:25:19 +0200 Subject: [PATCH] Honor the exit code from the child in the parent --- warp-runner/src/executor.rs | 33 ++++++++++++++++--------- warp-runner/src/main.rs | 49 ++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/warp-runner/src/executor.rs b/warp-runner/src/executor.rs index 757da82..7af2978 100644 --- a/warp-runner/src/executor.rs +++ b/warp-runner/src/executor.rs @@ -2,6 +2,7 @@ use std::env; use std::process::Command; use std::process::Stdio; use std::path::Path; +use std::io; #[cfg(target_family = "windows")] const PATH_SEPARATOR: char = ';'; @@ -9,23 +10,31 @@ const PATH_SEPARATOR: char = ';'; #[cfg(target_family = "unix")] const PATH_SEPARATOR: char = ':'; -pub fn execute(path: &Path, prog: &str) { - let path_str = path.as_os_str().to_os_string().into_string().unwrap(); - let path_env = match env::var("PATH") { - Ok(p) => format!("{}{}{}", &path_str, PATH_SEPARATOR, &p), - _ => path_str - }; +pub fn execute(target: &Path) -> io::Result { + let target_dir = target.parent() + .and_then(|dir| dir.to_str()) + .expect("Unable to construct target directory"); + let target_file_name = target.file_name() + .and_then(|file_name| file_name.to_str()) + .expect("Unable to identify target file name"); + trace!("target={:?}", target); + trace!("target_dir={:?}", target_dir); + trace!("target_file_name={:?}", target_file_name); + + let current_path_env = env::var("PATH").unwrap_or(String::new()); + let path_env = format!("{}{}{}", target_dir, PATH_SEPARATOR, current_path_env); + trace!("path_env={:?}", path_env); let args: Vec = env::args().skip(1).collect(); - trace!("PATH={:?} prog={:?} args={:?}", path_env, prog, args); - Command::new(prog) + trace!("args={:?}", args); + + Ok(Command::new(target_file_name) .env("PATH", path_env) .args(args) .stdin(Stdio::inherit()) .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) - .spawn() - .unwrap_or_else(|_| panic!("{} failed to start", prog)) - .wait() - .unwrap_or_else(|_| panic!("{} failed to wait", prog)); + .spawn()? + .wait()? + .code().unwrap_or(1)) } diff --git a/warp-runner/src/main.rs b/warp-runner/src/main.rs index f198199..f711f4c 100644 --- a/warp-runner/src/main.rs +++ b/warp-runner/src/main.rs @@ -1,40 +1,40 @@ extern crate dirs; - #[macro_use] extern crate log; extern crate simple_logger; +use log::Level; use std::env; use std::error::Error; use std::ffi::*; use std::fs; use std::io; use std::path::*; -use log::Level; +use std::process; mod extractor; mod executor; -static PROG_BUF: &'static [u8] = b"tVQhhsFFlGGD3oWV4lEPST8I8FEPP54IM0q7daes4E1y3p2U2wlJRYmWmjPYfkhZ0PlT14Ls0j8fdDkoj33f2BlRJavLj3mWGibJsGt5uLAtrCDtvxikZ8UX2mQDCrgE\0"; +static TARGET_FILE_NAME_BUF: &'static [u8] = b"tVQhhsFFlGGD3oWV4lEPST8I8FEPP54IM0q7daes4E1y3p2U2wlJRYmWmjPYfkhZ0PlT14Ls0j8fdDkoj33f2BlRJavLj3mWGibJsGt5uLAtrCDtvxikZ8UX2mQDCrgE\0"; -fn prog() -> &'static str { - let nul_pos = PROG_BUF.iter() +fn target_file_name() -> &'static str { + let nul_pos = TARGET_FILE_NAME_BUF.iter() .position(|elem| *elem == b'\0') - .expect("PROG_BUF has no NUL terminator"); + .expect("TARGET_FILE_NAME_BUF has no NUL terminator"); - let slice = &PROG_BUF[..(nul_pos + 1)]; + let slice = &TARGET_FILE_NAME_BUF[..(nul_pos + 1)]; CStr::from_bytes_with_nul(slice) - .expect("Can't convert PROG_BUF slice to CStr") + .expect("Can't convert TARGET_FILE_NAME_BUF slice to CStr") .to_str() - .expect("Can't convert PROG_BUF CStr to str") + .expect("Can't convert TARGET_FILE_NAME_BUF CStr to str") } -fn cache_path(prog: &str) -> PathBuf { +fn cache_path(target: &str) -> PathBuf { dirs::data_local_dir() .expect("No data local dir found") .join("warp") .join("packages") - .join(prog) + .join(target) } fn extract(exe_path: &Path, cache_path: &Path) -> io::Result<()> { @@ -48,26 +48,35 @@ fn main() -> Result<(), Box> { simple_logger::init_with_level(Level::Trace)?; } - let prog = prog(); - let cache_path = cache_path(prog); - let exe_path = env::current_exe()?; - trace!("prog={:?}, cache_path={:?}, exe_path={:?}", prog, cache_path, exe_path); + let self_path = env::current_exe()?; + let self_file_name = self_path.file_name().unwrap(); + let cache_path = cache_path(&self_file_name.to_string_lossy()); + + trace!("self_path={:?}", self_path); + trace!("self_file_name={:?}", self_file_name); + trace!("cache_path={:?}", cache_path); + + let target_file_name = target_file_name(); + let target_path = cache_path.join(target_file_name); + + trace!("target_exec={:?}", target_file_name); + trace!("target_path={:?}", target_path); match fs::metadata(&cache_path) { Ok(cache) => { - if cache.modified()? >= fs::metadata(&exe_path)?.modified()? { + if cache.modified()? >= fs::metadata(&self_path)?.modified()? { trace!("cache is up-to-date"); } else { trace!("cache is outdated"); - extract(&exe_path, &cache_path)?; + extract(&self_path, &cache_path)?; } } Err(_) => { trace!("cache not found"); - extract(&exe_path, &cache_path)?; + extract(&self_path, &cache_path)?; } } - executor::execute(&cache_path, &prog); - Ok(()) + let exit_code = executor::execute(&target_path)?; + process::exit(exit_code); }