use std::{
collections::VecDeque,
os::unix::process::CommandExt,
process::{Command, ExitCode, Stdio},
};
use nix::{
fcntl::{open, OFlag},
libc::pid_t,
sys::stat::Mode,
unistd::Pid,
};
use syd::{path::XPathBuf, proc::proc_environ_read, syslog::LogLevel};
#[cfg(all(
not(coverage),
not(feature = "prof"),
not(target_os = "android"),
not(target_arch = "riscv64"),
target_page_size_4k,
target_pointer_width = "64"
))]
#[global_allocator]
static GLOBAL: hardened_malloc::HardenedMalloc = hardened_malloc::HardenedMalloc;
#[cfg(feature = "prof")]
#[global_allocator]
static GLOBAL: tcmalloc::TCMalloc = tcmalloc::TCMalloc;
syd::main! {
syd::set_sigpipe_dfl()?;
syd::log::log_init_simple(LogLevel::Warn)?;
let mut args: VecDeque<_> = std::env::args().skip(1).collect();
let pid = match args.pop_front().as_deref() {
None | Some("-h") => {
help();
return Ok(ExitCode::SUCCESS);
}
Some("-e") => {
let _var = if let Some(var) = args.pop_front() {
var
} else {
eprintln!("Error: -e requires an argument!");
return Ok(ExitCode::FAILURE);
};
#[cfg(target_os = "android")]
{
eprintln!("Error: -e is not supported on Android!");
return Ok(ExitCode::FAILURE);
}
#[cfg(not(target_os = "android"))]
match syd::wordexp::WordExp::expand(&_var, true, dur::Duration::from_secs(3)) {
Ok(val) => {
print!("{val}");
return Ok(ExitCode::SUCCESS);
}
Err(err) => {
eprintln!("Error: {err}");
std::process::exit(err.into());
}
};
}
Some(pid) => match pid.parse::<pid_t>().map(Pid::from_raw) {
Ok(pid) => pid,
Err(error) => {
eprintln!("Invalid PID: {error}");
return Ok(ExitCode::FAILURE);
}
},
};
let mut pfd = XPathBuf::from("/proc");
pfd.push_pid(pid);
pfd.push(b"environ");
#[expect(clippy::disallowed_methods)]
let pfd = open(&pfd, OFlag::O_RDONLY, Mode::empty())?.into();
let environ = match proc_environ_read(pfd) {
Ok(environ) => environ,
Err(error) => {
eprintln!("syd-env: {error}");
return Ok(ExitCode::FAILURE);
}
};
let error = Command::new("env")
.args(args)
.env_clear()
.envs(&environ)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.exec();
eprintln!("syd-env: {error}");
Ok(ExitCode::FAILURE)
}
fn help() {
println!("Usage: syd-env pid [-i] [name=value]... {{command [arg...]}}");
println!("Run a command with the environment of the process with the given PID.");
}