running_process_platform_internal/
platform_linux_cmdline.rs1
2 use std::os::unix::ffi::OsStringExt;
6
7 pub fn read_process_argv(pid: u32) -> std::io::Result<Vec<std::ffi::OsString>> {
9 if pid == 0 {
10 return Err(std::io::Error::new(
11 std::io::ErrorKind::InvalidInput,
12 "pid 0 is the kernel scheduler  not queryable",
13 ));
14 }
15 let path = format!("/proc/{pid}/cmdline");
16 let bytes = std::fs::read(&path)?;
17 if bytes.is_empty() {
19 return Ok(Vec::new());
20 }
21 let bytes = bytes.strip_suffix(&[0]).unwrap_or(&bytes);
22 Ok(bytes
23 .split(|byte| *byte == 0)
24 .map(|argument| std::ffi::OsString::from_vec(argument.to_vec()))
25 .collect())
26 }
27
28 pub fn read_process_cmdline(pid: u32) -> std::io::Result<String> {
33 Ok(render_display(&read_process_argv(pid)?))
34 }
35
36 fn render_display(argv: &[std::ffi::OsString]) -> String {
37 argv.iter()
38 .map(|argument| argument.to_string_lossy())
39 .collect::<Vec<_>>()
40 .join(" ")
41 }
42
43 #[cfg(test)]
44 mod tests {
45 use super::render_display;
46 use std::os::unix::ffi::OsStringExt;
47
48 #[test]
49 fn display_is_separate_from_structured_argv() {
50 let argv = vec![
51 std::ffi::OsString::from("tool"),
52 std::ffi::OsString::from("has space"),
53 std::ffi::OsString::from("quote\""),
54 std::ffi::OsString::new(),
55 std::ffi::OsString::from_vec(b"back\\slash".to_vec()),
56 ];
57 assert_eq!(render_display(&argv), "tool has space quote\" back\\slash");
58 assert_eq!(argv[3], std::ffi::OsString::new());
59 }
60 }