use std::{
env,
fs::canonicalize,
os::unix::process::CommandExt,
process::{Command, ExitCode, Stdio},
};
use nix::{
errno::Errno,
sys::{
signal::Signal,
stat::{umask, Mode},
},
};
use syd::{
compat::{set_name, set_pdeathsig},
err::{err2no, SydResult},
path::XPathBuf,
};
#[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;
fn which(command: &str, realpath: bool) -> SydResult<XPathBuf> {
let out = Command::new("which")
.arg(command)
.output()
.map(|o| o.stdout)?;
if out.is_empty() {
return Err(Errno::ENOENT.into());
}
let bin = String::from_utf8_lossy(&out);
let bin = bin.trim();
Ok(if realpath {
canonicalize(bin).map(XPathBuf::from)?
} else {
XPathBuf::from(bin)
})
}
syd::main! {
syd::set_sigpipe_dfl()?;
let opt_debug = env::var_os("SYD_LDD_DEBUG").is_some();
let syd = if which("syd", false).is_ok() {
"syd"
} else {
eprintln!("Syd not found in PATH!");
return Ok(ExitCode::from(Errno::ENOENT as i32 as u8));
};
let argv: Vec<String> = std::env::args().skip(1).collect();
let list: Vec<String> = argv
.clone()
.into_iter()
.filter(|arg| !arg.starts_with('-'))
.map(|arg| canonicalize(&arg).map(|p| {
let dst = XPathBuf::from(p);
format!("-mallow/lpath,read,exec+{dst}")
}))
.collect::<Result<_, _>>()?;
let mut lock = Vec::new();
for item in &list {
lock.push(item.replacen("-mallow/lpath,", "-mallow/lock/", 1));
}
let mut cmd = Command::new(syd);
cmd.stdin(Stdio::null());
cmd.stdout(Stdio::inherit());
cmd.stderr(Stdio::inherit());
unsafe {
cmd.pre_exec(|| {
let _ = set_name(c"syd_ldd");
set_pdeathsig(Some(Signal::SIGKILL))?;
umask(Mode::from_bits_truncate(0o777));
Ok(())
})
};
cmd.arg("-pldd");
cmd.arg("-plinux");
cmd.arg("-plandlock");
cmd.arg("-prand");
cmd.arg("-pnomagic");
cmd.arg("-pnopie");
if !opt_debug {
cmd.arg("-mlog/level:error");
} else {
cmd.arg("-pdebug");
}
cmd.args(list);
cmd.args(lock);
cmd.args(["--", "ldd"]);
cmd.args(&argv);
if opt_debug {
eprintln!("+ {cmd:?}");
}
let error = cmd.exec();
Ok(ExitCode::from(err2no(&error) as i32 as u8))
}