use std::env;
use std::fs::File;
use std::io::{Error, ErrorKind, Result};
mod common;
mod lastlog;
mod utmp;
pub use common::{LoginTime, Module, Record};
pub use lastlog::LastLog;
pub use utmp::Utmp;
static ENV: &str = "LASTLOG";
#[inline]
fn modules() -> Vec<Box<dyn Module>> {
vec![Box::new(utmp::Utmp {}), Box::new(lastlog::LastLog {})]
}
fn get_module() -> Result<(Box<dyn Module>, String)> {
if let Ok(path) = env::var(ENV) {
let Ok(mut f) = File::open(&path) else {
return Err(Error::new(ErrorKind::InvalidInput, "invalid env path"));
};
for module in modules().into_iter() {
if module.is_valid(&mut f) {
return Ok((module, path));
}
}
}
for module in modules().into_iter() {
let Ok(path) = module.primary_file() else { continue };
return Ok((module, path.to_owned()));
}
Err(Error::new(
ErrorKind::NotFound,
"no operating lastlog modules found",
))
}
pub fn iter_accounts() -> Result<Vec<Record>> {
let (module, path) = get_module()?;
module.iter_accounts(&path)
}
pub fn search_uid(uid: u32) -> Result<Record> {
let (module, path) = get_module()?;
module.search_uid(uid, &path)
}
pub fn search_username(username: &str) -> Result<Record> {
let (module, path) = get_module()?;
module.search_username(username, &path)
}
#[cfg(feature = "libc")]
pub fn search_self() -> Result<Record> {
let (module, path) = get_module()?;
let uid = unsafe { libc::getuid() };
module.search_uid(uid, &path)
}