Skip to main content

soar_utils/
system.rs

1use std::env;
2
3use nix::unistd::{geteuid, User};
4
5/// Retrieves the platform string in the format `ARCH-OS`.
6///
7/// This function combines the architecture (e.g., `x86_64`) and the operating
8/// system (e.g., `linux`) into a single string to identify the platform.
9pub fn platform() -> String {
10    format!("{}-{}", std::env::consts::ARCH, &std::env::consts::OS)
11}
12
13trait UsernameSource {
14    fn env_var(&self, key: &str) -> Option<String>;
15    fn uid_name(&self) -> Option<String>;
16}
17
18struct SystemSource;
19
20impl UsernameSource for SystemSource {
21    fn env_var(&self, key: &str) -> Option<String> {
22        env::var(key).ok()
23    }
24
25    fn uid_name(&self) -> Option<String> {
26        User::from_uid(geteuid())
27            .ok()
28            .and_then(|u| u.map(|u| u.name))
29    }
30}
31
32fn get_username_with<S: UsernameSource>(src: &S) -> String {
33    src.env_var("USER")
34        .or_else(|| src.env_var("LOGNAME"))
35        .or_else(|| src.uid_name())
36        .expect("Couldn't determine username.")
37}
38
39/// Returns the username of the current user.
40///
41/// This function first checks the `USER` and `LOGNAME` environment variables. If not set, it
42/// falls back to fetching the username using the effective user ID.
43///
44/// # Panics
45///
46/// This function will panic if it cannot determine the username.
47pub fn get_username() -> String {
48    get_username_with(&SystemSource)
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    struct AlwaysNone;
56    impl UsernameSource for AlwaysNone {
57        fn env_var(&self, _: &str) -> Option<String> {
58            None
59        }
60
61        fn uid_name(&self) -> Option<String> {
62            None
63        }
64    }
65
66    #[test]
67    fn test_platform() {
68        #[cfg(target_arch = "x86_64")]
69        #[cfg(target_os = "linux")]
70        assert_eq!(platform(), "x86_64-linux");
71
72        #[cfg(target_arch = "aarch64")]
73        #[cfg(target_os = "linux")]
74        assert_eq!(platform(), "aarch64-linux");
75    }
76
77    #[test]
78    #[should_panic(expected = "Couldn't determine username.")]
79    fn test_fails_when_all_sources_missing() {
80        get_username_with(&AlwaysNone);
81    }
82
83    #[test]
84    fn test_get_username() {
85        let username = get_username();
86        assert!(!username.is_empty());
87    }
88
89    #[test]
90    fn test_get_username_missing_env_vars() {
91        env::remove_var("USER");
92        env::remove_var("LOGNAME");
93
94        let username = get_username();
95        assert!(!username.is_empty());
96    }
97}