use std::default::Default;
use std::ffi::CStr;
use std::fs;
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug, Default)]
pub struct Uptime {
pub system: f64,
pub idle: f64,
}
impl Uptime {
fn new() -> Uptime {
let mut result = Uptime {
..Default::default()
};
let contents =
fs::read_to_string("/proc/uptime").expect("Something went wrong reading /proc/uptime");
let vals: Vec<&str> = contents.trim().split(" ").collect();
result.system = Self::parse(vals[0]);
result.idle = Self::parse(vals[1]);
result
}
fn parse(val: &str) -> f64 {
val.parse::<f64>().unwrap()
}
}
pub fn uptime() -> Uptime {
Uptime::new()
}
pub fn boot_time() -> u64 {
match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(n) => {
let result = n.as_secs() as f64 - uptime().system;
return result.round() as u64;
}
Err(_) => {
return 0;
}
}
}
#[derive(Debug)]
pub struct User {
pub name: String,
pub terminal: Option<String>,
pub host: Option<String>,
pub started: i32,
pub pid: Option<i32>,
}
pub fn users() -> Vec<User> {
let mut result: Vec<User> = vec![];
loop {
let utmpx = unsafe { libc::getutxent() };
if utmpx.is_null() {
break;
}
if unsafe { (*utmpx).ut_type } == libc::USER_PROCESS {
let name = cstr_to_string(unsafe { (*utmpx).ut_user.as_ptr() });
let terminal = cstr_to_string(unsafe { (*utmpx).ut_line.as_ptr() });
let host = cstr_to_string(unsafe { (*utmpx).ut_host.as_ptr() });
let user = User {
name: name,
terminal: Some(terminal),
host: Some(host),
started: unsafe { (*utmpx).ut_tv.tv_sec },
pid: unsafe { Some((*utmpx).ut_pid) },
};
result.push(user);
}
}
result
}
fn cstr_to_string(str_ptr: *const libc::c_char) -> String {
let cstr = unsafe { CStr::from_ptr(str_ptr) };
cstr.to_string_lossy().into_owned()
}
#[cfg(test)]
mod tests {
#[test]
fn test_uptime_struct() {
let uptime = super::Uptime::new();
assert!(uptime.system > 0.0);
assert!(uptime.idle > 0.0);
}
}