use crate::to_str;
use libc::{read, utmpx};
use std::{
fs::File,
io::{BufRead, BufReader, Error},
mem,
os::unix::prelude::*,
};
pub fn get_logged_users() -> Result<Vec<String>, Error> {
let utmp_file = File::open("/var/run/utmp")?;
let mut users: Vec<String> = Vec::new();
let mut buffer = std::mem::MaybeUninit::<utmpx>::uninit();
while unsafe {
read(
utmp_file.as_raw_fd(),
buffer.as_mut_ptr().cast(),
mem::size_of::<utmpx>(),
)
} != 0
{
let cbuffer = unsafe { buffer.assume_init() };
let cuser: &[libc::c_char] = &cbuffer.ut_user;
if cuser[0] != 0 && cbuffer.ut_type == libc::USER_PROCESS {
let csuser = to_str(cuser.as_ptr().cast()).trim_matches('\0').to_owned();
users.push(csuser);
}
}
Ok(users)
}
const UID_MIN: u16 = 1000;
const UID_MAX: u16 = 60000;
pub fn get_users() -> Result<Vec<String>, Error> {
let file = File::open("/etc/passwd")?;
let mut users: Vec<String> = Vec::new();
let mut file = BufReader::with_capacity(2048, file);
let mut line = String::with_capacity(128);
while file.read_line(&mut line)? != 0 {
let mut parts = line.splitn(4, ':');
let username = match parts.next() {
Some(name) => name,
None => {
line.clear();
continue;
}
};
if let Some(id) = parts.nth(1) {
if let Ok(parsed) = id.parse::<u16>() {
if (UID_MIN..UID_MAX).contains(&parsed) {
users.push(username.to_owned());
}
}
}
line.clear();
}
Ok(users)
}