1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

Merge pull request #2684 from blyxxyz/hostname-cleanup

hostname: Cleanup
This commit is contained in:
Sylvestre Ledru 2021-09-16 22:22:34 +02:00 committed by GitHub
commit 3d867fcf7c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 65 deletions

View file

@ -68,6 +68,7 @@ structs
substr substr
splitn splitn
trunc trunc
uninit
# * uutils # * uutils
basenc basenc
@ -277,6 +278,7 @@ ULONG
ULONGLONG ULONGLONG
UNLEN UNLEN
WCHAR WCHAR
WSADATA
errhandlingapi errhandlingapi
fileapi fileapi
handleapi handleapi

View file

@ -10,18 +10,13 @@
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use clap::{crate_version, App, Arg, ArgMatches};
use std::collections::hash_set::HashSet; use std::collections::hash_set::HashSet;
use std::net::ToSocketAddrs; use std::net::ToSocketAddrs;
use std::str; use std::str;
#[cfg(windows)]
use uucore::error::UUsageError;
use uucore::error::{UResult, USimpleError};
#[cfg(windows)] use clap::{crate_version, App, Arg, ArgMatches};
use winapi::shared::minwindef::MAKEWORD;
#[cfg(windows)] use uucore::error::{FromIo, UResult};
use winapi::um::winsock2::{WSACleanup, WSAStartup};
static ABOUT: &str = "Display or set the system's host name."; static ABOUT: &str = "Display or set the system's host name.";
@ -31,45 +26,52 @@ static OPT_FQDN: &str = "fqdn";
static OPT_SHORT: &str = "short"; static OPT_SHORT: &str = "short";
static OPT_HOST: &str = "host"; static OPT_HOST: &str = "host";
#[uucore_procs::gen_uumain] #[cfg(windows)]
pub fn uumain(args: impl uucore::Args) -> UResult<()> { mod wsa {
#![allow(clippy::let_and_return)] use std::io;
#[cfg(windows)]
unsafe { use winapi::shared::minwindef::MAKEWORD;
#[allow(deprecated)] use winapi::um::winsock2::{WSACleanup, WSAStartup, WSADATA};
let mut data = std::mem::uninitialized();
if WSAStartup(MAKEWORD(2, 2), &mut data as *mut _) != 0 { pub(super) struct WsaHandle(());
return Err(UUsageError::new(
1, pub(super) fn start() -> io::Result<WsaHandle> {
"Failed to start Winsock 2.2".to_string(), let err = unsafe {
)); let mut data = std::mem::MaybeUninit::<WSADATA>::uninit();
WSAStartup(MAKEWORD(2, 2), data.as_mut_ptr())
};
if err != 0 {
Err(io::Error::from_raw_os_error(err))
} else {
Ok(WsaHandle(()))
} }
} }
let result = execute(args);
#[cfg(windows)] impl Drop for WsaHandle {
unsafe { fn drop(&mut self) {
WSACleanup(); unsafe {
// This possibly returns an error but we can't handle it
let _err = WSACleanup();
}
}
} }
result
} }
fn usage() -> String { fn usage() -> String {
format!("{0} [OPTION]... [HOSTNAME]", uucore::execution_phrase()) format!("{0} [OPTION]... [HOSTNAME]", uucore::execution_phrase())
} }
fn execute(args: impl uucore::Args) -> UResult<()> { #[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let usage = usage(); let usage = usage();
let matches = uu_app().usage(&usage[..]).get_matches_from(args); let matches = uu_app().usage(&usage[..]).get_matches_from(args);
match matches.value_of(OPT_HOST) { #[cfg(windows)]
let _handle = wsa::start().map_err_context(|| "failed to start Winsock".to_owned())?;
match matches.value_of_os(OPT_HOST) {
None => display_hostname(&matches), None => display_hostname(&matches),
Some(host) => { Some(host) => hostname::set(host).map_err_context(|| "failed to set hostname".to_owned()),
if let Err(err) = hostname::set(host) {
return Err(USimpleError::new(1, format!("{}", err)));
} else {
Ok(())
}
}
} }
} }
@ -81,64 +83,68 @@ pub fn uu_app() -> App<'static, 'static> {
Arg::with_name(OPT_DOMAIN) Arg::with_name(OPT_DOMAIN)
.short("d") .short("d")
.long("domain") .long("domain")
.overrides_with_all(&[OPT_DOMAIN, OPT_IP_ADDRESS, OPT_FQDN, OPT_SHORT])
.help("Display the name of the DNS domain if possible"), .help("Display the name of the DNS domain if possible"),
) )
.arg( .arg(
Arg::with_name(OPT_IP_ADDRESS) Arg::with_name(OPT_IP_ADDRESS)
.short("i") .short("i")
.long("ip-address") .long("ip-address")
.overrides_with_all(&[OPT_DOMAIN, OPT_IP_ADDRESS, OPT_FQDN, OPT_SHORT])
.help("Display the network address(es) of the host"), .help("Display the network address(es) of the host"),
) )
// TODO: support --long
.arg( .arg(
Arg::with_name(OPT_FQDN) Arg::with_name(OPT_FQDN)
.short("f") .short("f")
.long("fqdn") .long("fqdn")
.overrides_with_all(&[OPT_DOMAIN, OPT_IP_ADDRESS, OPT_FQDN, OPT_SHORT])
.help("Display the FQDN (Fully Qualified Domain Name) (default)"), .help("Display the FQDN (Fully Qualified Domain Name) (default)"),
) )
.arg(Arg::with_name(OPT_SHORT).short("s").long("short").help( .arg(
"Display the short hostname (the portion before the first dot) if \ Arg::with_name(OPT_SHORT)
possible", .short("s")
)) .long("short")
.overrides_with_all(&[OPT_DOMAIN, OPT_IP_ADDRESS, OPT_FQDN, OPT_SHORT])
.help("Display the short hostname (the portion before the first dot) if possible"),
)
.arg(Arg::with_name(OPT_HOST)) .arg(Arg::with_name(OPT_HOST))
} }
fn display_hostname(matches: &ArgMatches) -> UResult<()> { fn display_hostname(matches: &ArgMatches) -> UResult<()> {
let hostname = hostname::get().unwrap().into_string().unwrap(); let hostname = hostname::get()
.map_err_context(|| "failed to get hostname".to_owned())?
.to_string_lossy()
.into_owned();
if matches.is_present(OPT_IP_ADDRESS) { if matches.is_present(OPT_IP_ADDRESS) {
// XXX: to_socket_addrs needs hostname:port so append a dummy port and remove it later. // XXX: to_socket_addrs needs hostname:port so append a dummy port and remove it later.
// This was originally supposed to use std::net::lookup_host, but that seems to be // This was originally supposed to use std::net::lookup_host, but that seems to be
// deprecated. Perhaps we should use the dns-lookup crate? // deprecated. Perhaps we should use the dns-lookup crate?
let hostname = hostname + ":1"; let hostname = hostname + ":1";
match hostname.to_socket_addrs() { let addresses = hostname
Ok(addresses) => { .to_socket_addrs()
let mut hashset = HashSet::new(); .map_err_context(|| "failed to resolve socket addresses".to_owned())?;
let mut output = String::new(); let mut hashset = HashSet::new();
for addr in addresses { let mut output = String::new();
// XXX: not sure why this is necessary... for addr in addresses {
if !hashset.contains(&addr) { // XXX: not sure why this is necessary...
let mut ip = format!("{}", addr); if !hashset.contains(&addr) {
if ip.ends_with(":1") { let mut ip = addr.to_string();
let len = ip.len(); if ip.ends_with(":1") {
ip.truncate(len - 2); let len = ip.len();
} ip.truncate(len - 2);
output.push_str(&ip);
output.push(' ');
hashset.insert(addr);
}
} }
let len = output.len(); output.push_str(&ip);
if len > 0 { output.push(' ');
println!("{}", &output[0..len - 1]); hashset.insert(addr);
}
Ok(())
}
Err(f) => {
return Err(USimpleError::new(1, format!("{}", f)));
} }
} }
let len = output.len();
if len > 0 {
println!("{}", &output[0..len - 1]);
}
Ok(())
} else { } else {
if matches.is_present(OPT_SHORT) || matches.is_present(OPT_DOMAIN) { if matches.is_present(OPT_SHORT) || matches.is_present(OPT_DOMAIN) {
let mut it = hostname.char_indices().filter(|&ci| ci.1 == '.'); let mut it = hostname.char_indices().filter(|&ci| ci.1 == '.');