use std::{ffi::CStr, fs::File, io::{self, Read}}; use toml::Value; use xcb::x; pub const BSCREENSAVER_WM_CLASS: &[u8] = b"bscreensaver\0Bscreensaver\0"; pub fn init_logging(env_name: &str) { env_logger::builder() .format_timestamp_millis() .parse_env(env_name) .init(); } pub fn load_configuration() -> anyhow::Result> { match xdg::BaseDirectories::new()?.find_config_file("bscreensaver.toml") { None => Ok(None), Some(config_path) => { let mut f = File::open(config_path)?; let mut config = String::new(); f.read_to_string(&mut config)?; drop(f); let config_toml = config.parse::()?; Ok(Some(config_toml)) }, } } pub fn create_atom(conn: &xcb::Connection, name: &[u8]) -> xcb::Result { let cookie = conn.send_request(&x::InternAtom { only_if_exists: false, name, }); Ok(conn.wait_for_reply(cookie)?.atom()) } pub fn destroy_gc(conn: &xcb::Connection, gc: x::Gcontext) -> xcb::Result<()> { conn.send_and_check_request(&x::FreeGc { gc, })?; Ok(()) } pub fn destroy_window(conn: &xcb::Connection, window: x::Window) -> xcb::Result<()> { conn.send_and_check_request(&x::DestroyWindow { window, })?; Ok(()) } pub fn get_username() -> io::Result { // SAFETY: libc must be sane let uid = unsafe { libc::getuid() }; // SAFETY: libc must be sane let pwd = unsafe { libc::getpwuid(uid) }; // SAFETY: null-check occurs on same line if pwd.is_null() || unsafe { *pwd }.pw_name.is_null() { Err(io::Error::new(io::ErrorKind::NotFound, "Username not found".to_string())) } else { // SAFETY: libc must be sane; null checks performed above let cstr = unsafe { CStr::from_ptr((*pwd).pw_name) }; cstr.to_str() .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8 data in username".to_string())) .map(|s| s.to_string()) } }