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}