use std::fs; use std::os::linux::fs::MetadataExt; use std::os::unix::prelude::PermissionsExt; use std::time::SystemTime; use nix::unistd; use serde_json::Value; const PERSIST_TIME: u64 = 60 * 3; pub fn get_persist(user: &str) -> bool { let json = match get_terminal_config() { Some(data) => data, None => return false }; let timestamp = match json[user].as_u64() { Some(data) => data, None => return false }; return now() - timestamp < PERSIST_TIME && timestamp < now(); } pub fn set_persist(user: &str) { let mut json = match get_terminal_config() { Some(data) => data, None => return }; json[user] = Value::from(now()); let id = match get_terminal_process() { Some(data) => data, None => return }; match write_terminal_config(&id, &json.to_string()) { Ok(_) => {}, Err(e) => { eprintln!("Internal Error: {}", e) } }; } fn get_terminal_process() -> Option { let id: i32 = match std::process::id().try_into() { Ok(data) => data, Err(_) => return None }; let stat = match procinfo::pid::stat(id) { Ok(data) => data, Err(_) => return None }; Some(stat.session) } fn get_terminal_config() -> Option { let id = match get_terminal_process() { Some(data) => data, None => return None }; if !is_file_root(&path(&id)) { return None; } let data = match std::fs::read_to_string(path(&id)) { Ok(data) => data, Err(_) => "{}".to_string() }; let json: Value = match serde_json::from_str(&data) { Ok(data) => data, Err(_) => return None }; Some(json) } fn write_terminal_config(id: &i32, data: &str) -> Result<(), Box> { std::fs::create_dir_all("/var/run/crab")?; make_file_root("/var/run/crab")?; std::fs::write(path(&id), "")?; make_file_root(&path(&id))?; std::fs::write(path(&id), data)?; Ok(()) } fn make_file_root(path: &str) -> Result<(), Box> { unistd::chown(std::path::Path::new(path), Some(unistd::Uid::from(0)), Some(unistd::Gid::from(0)))?; let metadata = std::fs::metadata(path)?; let mut perms = metadata.permissions(); perms.set_mode(0o100600); fs::set_permissions(path, perms)?; Ok(()) } fn is_file_root(path: &str) -> bool { let metadata = match std::fs::metadata(path) { Ok(data) => data, Err(e) => { if let Some(err) = e.raw_os_error() { return err == 2; } return true } }; let perms = metadata.permissions(); return perms.mode() == 0o100600 && metadata.st_uid() == 0 && metadata.st_gid() == 0; } fn now() -> u64 { return SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); } fn path(id: &i32) -> String { return format!("/var/run/crab/{}", id); }