use std::{
io::{stdout, Write},
process::ExitCode,
};
use nix::{libc::pid_t, unistd::Pid};
use serde_json::json;
use syd::{
fd::open_static_proc,
proc::{proc_cmdline, proc_comm, proc_stat, proc_status},
};
#[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()?;
open_static_proc()?;
let pid = match std::env::args().nth(1).map(|arg| arg.parse::<pid_t>()) {
Some(Ok(pid)) => Pid::from_raw(pid),
None => Pid::this(),
Some(Err(_)) => {
help();
return Ok(ExitCode::SUCCESS);
}
};
let comm = proc_comm(pid)?;
let cmdline = proc_cmdline(pid)?;
let stat = proc_stat(pid)?;
let status = proc_status(pid)?;
#[expect(clippy::disallowed_methods)]
let status = json!({
"pid": pid.as_raw(),
"tgid": status.pid.as_raw(),
"comm": comm,
"cmdline": cmdline,
"umask": status.umask.bits(),
"tty_nr": stat.tty_nr,
"start_brk": stat.startbrk,
"startstack": stat.startstack,
"num_threads": stat.num_threads,
"sig": {
"blocked": status.sig_blocked,
"caught": status.sig_caught,
"ignored": status.sig_ignored,
"pending_thread": status.sig_pending_thread,
"pending_process": status.sig_pending_process,
},
});
#[expect(clippy::disallowed_methods)]
let mut status = serde_json::to_string(&status).expect("JSON");
status.push('\n');
stdout().write_all(status.as_bytes())?;
Ok(ExitCode::SUCCESS)
}
fn help() {
println!("Usage: syd-stat [PID]");
println!("Print detailed information about the given process process or current process.");
}