#![feature(iter_intersperse)] use std::{ env, ffi::OsString, fs, os::unix::{ ffi::{OsStrExt, OsStringExt}, process::CommandExt, }, process::Command, }; fn main() { let mut child_env = vec![]; for (key, value) in env::vars_os() { let key_bytes: Vec<_> = key.as_bytes().into(); if key_bytes.ends_with(b"_FILE") && !value.is_empty() { match fs::read(&value) { Ok(content) => { let key = OsString::from_vec(key_bytes[0..key_bytes.len() - 5].to_owned()); child_env.push((key, OsString::from_vec(content))); } Err(error) => { panic!( "failed to read contents of {value:?} (specified by ${}): {error:?}", key.to_string_lossy() ) } } } else { child_env.push((key, value)) } } let mut args = env::args().skip(1); if let Some(cmd) = args.next() { let collected: Vec<_> = args.collect(); let mut child = Command::new(&cmd); child.env_clear().envs(child_env); for arg in &collected { child.arg(arg); } let err = child.exec(); // Ideally should not return panic!("error running command {cmd} with args {collected:?}: {err}"); } else { panic!("no command given"); } }