Skip to main content

coreutils_rs/users/
core.rs

1/// users -- print the user names of users currently logged in
2///
3/// Reads utmpx records and prints a sorted, space-separated list of login names
4/// for all USER_PROCESS entries.
5use std::ffi::CStr;
6
7/// Retrieve a sorted list of currently logged-in user names from utmpx.
8///
9/// # Safety
10/// Uses libc's setutxent/getutxent/endutxent which are not thread-safe.
11/// This function must not be called concurrently.
12pub fn get_users() -> Vec<String> {
13    let mut users = Vec::new();
14
15    // SAFETY: setutxent/getutxent/endutxent are standard POSIX functions.
16    // We call them sequentially and do not hold pointers across calls.
17    unsafe {
18        libc::setutxent();
19        loop {
20            let entry = libc::getutxent();
21            if entry.is_null() {
22                break;
23            }
24            let entry = &*entry;
25            if entry.ut_type == libc::USER_PROCESS {
26                let name = CStr::from_ptr(entry.ut_user.as_ptr())
27                    .to_string_lossy()
28                    .to_string();
29                if !name.is_empty() {
30                    users.push(name);
31                }
32            }
33        }
34        libc::endutxent();
35    }
36
37    users.sort();
38    users
39}
40
41/// Format the user list as a single space-separated line (matching GNU users output).
42pub fn format_users(users: &[String]) -> String {
43    users.join(" ")
44}