diff --git a/src/colors.rs b/src/colors.rs index 7c65944..07ab9bd 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -1,4 +1,4 @@ -use std::sync::LazyLock; +use std::{env, sync::LazyLock}; pub struct Colors { pub reset: &'static str, @@ -37,8 +37,8 @@ impl Colors { } pub static COLORS: LazyLock = LazyLock::new(|| { - const NO_COLOR: *const libc::c_char = c"NO_COLOR".as_ptr(); - let is_no_color = unsafe { !libc::getenv(NO_COLOR).is_null() }; + // Check for NO_COLOR once at startup + let is_no_color = env::var("NO_COLOR").is_ok(); Colors::new(is_no_color) }); diff --git a/src/desktop.rs b/src/desktop.rs index 501e967..561be03 100644 --- a/src/desktop.rs +++ b/src/desktop.rs @@ -1,27 +1,22 @@ -use std::{ffi::CStr, fmt::Write}; +use std::fmt::Write; #[must_use] #[cfg_attr(feature = "hotpath", hotpath::measure)] pub fn get_desktop_info() -> String { // Retrieve the environment variables and handle Result types - let desktop_str = unsafe { - let ptr = libc::getenv(c"XDG_CURRENT_DESKTOP".as_ptr()); - if ptr.is_null() { - "Unknown" - } else { - let s = CStr::from_ptr(ptr).to_str().unwrap_or("Unknown"); - s.strip_prefix("none+").unwrap_or(s) - } + let desktop_env = std::env::var("XDG_CURRENT_DESKTOP"); + let display_backend = std::env::var("XDG_SESSION_TYPE"); + + let desktop_str = match desktop_env { + Err(_) => "Unknown", + Ok(ref s) if s.starts_with("none+") => &s[5..], + Ok(ref s) => s.as_str(), }; - let backend_str = unsafe { - let ptr = libc::getenv(c"XDG_SESSION_TYPE".as_ptr()); - if ptr.is_null() { - "Unknown" - } else { - let s = CStr::from_ptr(ptr).to_str().unwrap_or("Unknown"); - if s.is_empty() { "Unknown" } else { s } - } + let backend_str = match display_backend { + Err(_) => "Unknown", + Ok(ref s) if s.is_empty() => "Unknown", + Ok(ref s) => s.as_str(), }; // Pre-calculate capacity: desktop_len + " (" + backend_len + ")" diff --git a/src/main.rs b/src/main.rs index c3e7c69..ab93580 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ mod syscall; mod system; mod uptime; -use std::io::{self, Cursor, Write}; +use std::io::{Write, stdout}; pub use microfetch_lib::UtsName; @@ -81,13 +81,7 @@ fn print_system_info( let cyan = COLORS.cyan; let blue = COLORS.blue; let reset = COLORS.reset; - - let mut buf = [0u8; 2048]; - let mut cursor = Cursor::new(&mut buf[..]); - - write!( - cursor, - " + let system_info = format!(" {cyan} ▟█▖ {blue}▝█▙ ▗█▛ {user_info} ~{reset} {cyan} ▗▄▄▟██▄▄▄▄▄{blue}▝█▙█▛ {cyan}▖ {cyan} {blue}System{reset}  {os_name} {cyan} ▀▀▀▀▀▀▀▀▀▀▀▘{blue}▝██ {cyan}▟█▖ {cyan} {blue}Kernel{reset}  {kernel_version} @@ -96,17 +90,7 @@ fn print_system_info( {blue} ▟█▛{cyan}▗█▖ {cyan}▟█▛ {cyan} {blue}Desktop{reset}  {desktop} {blue} ▝█▛ {cyan}██▖{blue}▗▄▄▄▄▄▄▄▄▄▄▄ {cyan} {blue}Memory{reset}  {memory_usage} {blue} ▝ {cyan}▟█▜█▖{blue}▀▀▀▀▀██▛▀▀▘ {cyan}󱥎 {blue}Storage (/){reset}  {storage} - {cyan} ▟█▘ ▜█▖ {blue}▝█▛ {cyan} {blue}Colors{reset}  {colors}\n\n" - )?; + {cyan} ▟█▘ ▜█▖ {blue}▝█▛ {cyan} {blue}Colors{reset}  {colors}\n\n"); - let len = cursor.position() as usize; - // Direct syscall to avoid stdout buffering allocation - let written = unsafe { libc::write(libc::STDOUT_FILENO, buf.as_ptr().cast(), len) }; - if written < 0 { - return Err(io::Error::last_os_error().into()); - } - if written as usize != len { - return Err(io::Error::new(io::ErrorKind::WriteZero, "partial write to stdout").into()); - } - Ok(()) + Ok(stdout().write_all(system_info.as_bytes())?) } diff --git a/src/system.rs b/src/system.rs index ba8fe79..24406ec 100644 --- a/src/system.rs +++ b/src/system.rs @@ -1,18 +1,11 @@ -use std::{ffi::CStr, fmt::Write as _, io, mem::MaybeUninit}; +use std::{env, fmt::Write as _, io, mem::MaybeUninit}; use crate::{UtsName, colors::COLORS, syscall::read_file_fast}; #[must_use] #[cfg_attr(feature = "hotpath", hotpath::measure)] pub fn get_username_and_hostname(utsname: &UtsName) -> String { - let username = unsafe { - let ptr = libc::getenv(c"USER".as_ptr()); - if ptr.is_null() { - "unknown_user" - } else { - CStr::from_ptr(ptr).to_str().unwrap_or("unknown_user") - } - }; + let username = env::var("USER").unwrap_or_else(|_| "unknown_user".to_owned()); let hostname = utsname.nodename().to_str().unwrap_or("unknown_host"); let capacity = COLORS.yellow.len() @@ -25,7 +18,7 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String { let mut result = String::with_capacity(capacity); result.push_str(COLORS.yellow); - result.push_str(username); + result.push_str(&username); result.push_str(COLORS.red); result.push('@'); result.push_str(COLORS.green); @@ -38,17 +31,15 @@ pub fn get_username_and_hostname(utsname: &UtsName) -> String { #[must_use] #[cfg_attr(feature = "hotpath", hotpath::measure)] pub fn get_shell() -> String { - unsafe { - let ptr = libc::getenv(c"SHELL".as_ptr()); - if ptr.is_null() { - return "unknown_shell".into(); - } + let shell_path = + env::var("SHELL").unwrap_or_else(|_| "unknown_shell".to_owned()); - let bytes = CStr::from_ptr(ptr).to_bytes(); - let start = bytes.iter().rposition(|&b| b == b'/').map_or(0, |i| i + 1); - let name = std::str::from_utf8_unchecked(&bytes[start..]); - name.into() - } + // Find last '/' and get the part after it, avoiding allocation + shell_path + .rsplit('/') + .next() + .unwrap_or("unknown_shell") + .to_owned() } /// Gets the root disk usage information. @@ -115,7 +106,7 @@ pub fn get_memory_usage() -> Result { fn parse_memory_info() -> Result<(f64, f64), io::Error> { let mut total_memory_kb = 0u64; let mut available_memory_kb = 0u64; - let mut buffer = [0u8; 1024]; + let mut buffer = [0u8; 2048]; // Use fast syscall-based file reading let bytes_read = read_file_fast("/proc/meminfo", &mut buffer)?;