pub fn name() -> Option<String> {
let raw = host_name()?;
let short = raw.split('.').next().unwrap_or_default().trim();
(!short.is_empty()).then(|| short.to_owned())
}
#[cfg(windows)]
fn host_name() -> Option<String> {
std::env::var("COMPUTERNAME").ok()
}
#[cfg(unix)]
fn host_name() -> Option<String> {
use std::ffi::{c_char, c_int};
unsafe extern "C" {
fn gethostname(name: *mut c_char, len: usize) -> c_int;
}
let mut buffer = [0u8; 256];
let status = unsafe { gethostname(buffer.as_mut_ptr().cast(), buffer.len()) };
if status != 0 {
return None;
}
let end = buffer.iter().position(|&byte| byte == 0)?;
String::from_utf8(buffer[..end].to_vec()).ok()
}
#[cfg(not(any(windows, unix)))]
fn host_name() -> Option<String> {
None
}
#[cfg(test)]
mod tests {
#[test]
fn a_name_found_is_short_and_never_blank() {
if let Some(name) = super::name() {
assert!(!name.is_empty());
assert!(!name.contains('.'), "{name}");
assert_eq!(name.trim(), name);
}
}
}