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