discover daemon state dir from cmdline when environ is unreadable

When the daemon runs as a different user (e.g. via systemd), the client
cannot read /proc/<pid>/environ due to permissions. Fall back to
parsing the cmdline for -D / --state-dir flags, which are world-readable.

Fixes 'error: no logs for <service>' when client and daemon run as
different users.

v0.1.1
This commit is contained in:
Niko Marmeladkov 2026-07-07 13:52:13 +03:00
parent 032f0ded69
commit e4aea785ee
Signed by untrusted user who does not match committer: Niko
GPG key ID: E3B955F9442D44E3
2 changed files with 32 additions and 7 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "rss" name = "rss"
version = "0.1.0" version = "0.1.1"
edition = "2021" edition = "2021"
[dependencies] [dependencies]

View file

@ -30,16 +30,41 @@ fn discover_daemon_state_dir() -> Option<PathBuf> {
if !args.contains(&"daemon") { if !args.contains(&"daemon") {
continue; continue;
} }
let environ = std::fs::read(format!("/proc/{}/environ", pid)).ok()?; // Try RSS_STATE_DIR from environ first
for var in environ.split(|&b| b == 0) { if let Ok(environ) = std::fs::read(format!("/proc/{}/environ", pid)) {
if let Ok(var_str) = std::str::from_utf8(var) { for var in environ.split(|&b| b == 0) {
if let Some(val) = var_str.strip_prefix("RSS_STATE_DIR=") { if let Ok(var_str) = std::str::from_utf8(var) {
if !val.is_empty() { if let Some(val) = var_str.strip_prefix("RSS_STATE_DIR=") {
return Some(PathBuf::from(val)); if !val.is_empty() {
return Some(PathBuf::from(val));
}
} }
} }
} }
} }
// Fallback: parse cmdline for -D / --state-dir (works across users)
let mut i = 0;
while i < args.len() {
let next = if args[i] == "-D" || args[i] == "--state-dir" {
args.get(i + 1).map(|s| s.to_string())
} else if let Some(val) = args[i].strip_prefix("--state-dir=") {
Some(val.to_string())
} else if let Some(val) = args[i].strip_prefix("-D") {
if val.is_empty() {
args.get(i + 1).map(|s| s.to_string())
} else {
Some(val.to_string())
}
} else {
None
};
if let Some(dir) = next {
if !dir.is_empty() {
return Some(PathBuf::from(dir));
}
}
i += 1;
}
} }
None None
} }