mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
hostname: add support for Windows (and maybe other systems too)
This commit is contained in:
parent
15aaa8215e
commit
6330474b4f
5 changed files with 76 additions and 39 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,6 +4,7 @@ target/
|
||||||
/tmp/
|
/tmp/
|
||||||
/busybox/
|
/busybox/
|
||||||
/.vscode/
|
/.vscode/
|
||||||
|
/.vs/
|
||||||
*~
|
*~
|
||||||
.*.swp
|
.*.swp
|
||||||
.*.swo
|
.*.swo
|
||||||
|
|
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -543,6 +543,7 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"uucore 0.0.1",
|
"uucore 0.0.1",
|
||||||
|
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -13,7 +13,6 @@ unix = [
|
||||||
"du",
|
"du",
|
||||||
"groups",
|
"groups",
|
||||||
"hostid",
|
"hostid",
|
||||||
"hostname",
|
|
||||||
"id",
|
"id",
|
||||||
"install",
|
"install",
|
||||||
"kill",
|
"kill",
|
||||||
|
@ -68,6 +67,7 @@ generic = [
|
||||||
"arch",
|
"arch",
|
||||||
"cat",
|
"cat",
|
||||||
"hashsum",
|
"hashsum",
|
||||||
|
"hostname",
|
||||||
"join",
|
"join",
|
||||||
"more",
|
"more",
|
||||||
"ln",
|
"ln",
|
||||||
|
|
|
@ -10,6 +10,7 @@ path = "hostname.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2.26"
|
libc = "0.2.26"
|
||||||
|
winapi = { version = "0.3", features = ["sysinfoapi", "winsock2"] }
|
||||||
uucore = { path="../uucore" }
|
uucore = { path="../uucore" }
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|
|
@ -7,41 +7,57 @@
|
||||||
*
|
*
|
||||||
* For the full copyright and license information, please view the LICENSE
|
* For the full copyright and license information, please view the LICENSE
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*
|
|
||||||
* Synced with:
|
|
||||||
*
|
|
||||||
* https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
#[cfg(windows)]
|
||||||
|
extern crate winapi;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate uucore;
|
extern crate uucore;
|
||||||
|
|
||||||
use std::collections::hash_set::HashSet;
|
use std::collections::hash_set::HashSet;
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
|
use std::io;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use winapi::um::winsock2::{GetHostNameW, WSAStartup, WSACleanup};
|
||||||
|
#[cfg(windows)]
|
||||||
|
use winapi::um::sysinfoapi::{ComputerNamePhysicalDnsHostname, SetComputerNameExW};
|
||||||
|
#[cfg(windows)]
|
||||||
|
use winapi::shared::minwindef::MAKEWORD;
|
||||||
|
#[cfg(windows)]
|
||||||
|
use uucore::wide::*;
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use libc::gethostname;
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
use libc::sethostname;
|
||||||
|
|
||||||
static SYNTAX: &'static str = "[OPTION]... [HOSTNAME]";
|
static SYNTAX: &'static str = "[OPTION]... [HOSTNAME]";
|
||||||
static SUMMARY: &'static str = "Print or set the system's host name.";
|
static SUMMARY: &'static str = "Print or set the system's host name.";
|
||||||
static LONG_HELP: &'static str = "";
|
static LONG_HELP: &'static str = "";
|
||||||
|
|
||||||
extern {
|
|
||||||
fn gethostname(name: *mut libc::c_char, namelen: libc::size_t) -> libc::c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
|
||||||
extern {
|
|
||||||
fn sethostname(name: *const libc::c_char, namelen: libc::c_int) -> libc::c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
extern {
|
|
||||||
fn sethostname(name: *const libc::c_char, namelen: libc::size_t) -> libc::c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn uumain(args: Vec<String>) -> i32 {
|
pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
|
#[cfg(windows)]
|
||||||
|
unsafe {
|
||||||
|
let mut data = std::mem::uninitialized();
|
||||||
|
if WSAStartup(MAKEWORD(2, 2), &mut data as *mut _) != 0 {
|
||||||
|
eprintln!("Failed to start Winsock 2.2");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let result = execute(args);
|
||||||
|
#[cfg(windows)]
|
||||||
|
unsafe {
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(args: Vec<String>) -> i32 {
|
||||||
let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP)
|
let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP)
|
||||||
.optflag("d", "domain", "Display the name of the DNS domain if possible")
|
.optflag("d", "domain", "Display the name of the DNS domain if possible")
|
||||||
.optflag("i", "ip-address", "Display the network address(es) of the host")
|
.optflag("i", "ip-address", "Display the network address(es) of the host")
|
||||||
|
@ -51,7 +67,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
|
|
||||||
match matches.free.len() {
|
match matches.free.len() {
|
||||||
0 => {
|
0 => {
|
||||||
let hostname = xgethostname();
|
let hostname = return_if_err!(1, xgethostname());
|
||||||
|
|
||||||
if matches.opt_present("i") {
|
if matches.opt_present("i") {
|
||||||
// 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.
|
||||||
|
@ -110,45 +126,63 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn xgethostname() -> String {
|
#[cfg(not(windows))]
|
||||||
let namelen = 256usize;
|
fn xgethostname() -> io::Result<String> {
|
||||||
let mut name : Vec<u8> = repeat(0).take(namelen).collect();
|
let namelen = 256;
|
||||||
|
let mut name: Vec<u8> = repeat(0).take(namelen).collect();
|
||||||
let err = unsafe {
|
let err = unsafe {
|
||||||
gethostname (name.as_mut_ptr() as *mut libc::c_char,
|
gethostname(name.as_mut_ptr() as *mut libc::c_char, namelen as libc::size_t)
|
||||||
namelen as libc::size_t)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if err != 0 {
|
if err == 0 {
|
||||||
panic!("Cannot determine hostname");
|
let last_char = name.iter().position(|byte| *byte == 0).unwrap_or(namelen);
|
||||||
|
|
||||||
|
Ok(str::from_utf8(&name[..last_char]).unwrap().to_owned())
|
||||||
|
} else {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
}
|
}
|
||||||
|
|
||||||
let last_char = name.iter().position(|byte| *byte == 0).unwrap_or(namelen);
|
|
||||||
|
|
||||||
str::from_utf8(&name[..last_char]).unwrap().to_owned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
#[cfg(windows)]
|
||||||
|
fn xgethostname() -> io::Result<String> {
|
||||||
|
let namelen = 256;
|
||||||
|
let mut name: Vec<u16> = repeat(0).take(namelen).collect();
|
||||||
|
let err = unsafe {
|
||||||
|
GetHostNameW(name.as_mut_ptr(), namelen as libc::c_int)
|
||||||
|
};
|
||||||
|
|
||||||
|
if err == 0 {
|
||||||
|
Ok(String::from_wide_null(&name))
|
||||||
|
} else {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(windows))]
|
||||||
fn xsethostname(name: &str) {
|
fn xsethostname(name: &str) {
|
||||||
let vec_name: Vec<libc::c_char> = name.bytes().map(|c| c as libc::c_char).collect();
|
let vec_name: Vec<libc::c_char> = name.bytes().map(|c| c as libc::c_char).collect();
|
||||||
|
|
||||||
let err = unsafe {
|
let err = unsafe {
|
||||||
sethostname (vec_name.as_ptr(), vec_name.len() as libc::c_int)
|
sethostname(vec_name.as_ptr(), vec_name.len() as _)
|
||||||
};
|
};
|
||||||
|
|
||||||
if err != 0 {
|
if err != 0 {
|
||||||
println!("Cannot set hostname to {}", name);
|
eprintln!("Cannot set hostname to {}", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(windows)]
|
||||||
fn xsethostname(name: &str) {
|
fn xsethostname(name: &str) {
|
||||||
let vec_name: Vec<libc::c_char> = name.bytes().map(|c| c as libc::c_char).collect();
|
use std::ffi::OsStr;
|
||||||
|
|
||||||
|
let wide_name = OsStr::new(name).to_wide_null();
|
||||||
|
|
||||||
let err = unsafe {
|
let err = unsafe {
|
||||||
sethostname (vec_name.as_ptr(), vec_name.len() as libc::size_t)
|
SetComputerNameExW(ComputerNamePhysicalDnsHostname, wide_name.as_ptr())
|
||||||
};
|
};
|
||||||
|
|
||||||
if err != 0 {
|
if err == 0 {
|
||||||
println!("Cannot set hostname to {}", name);
|
// NOTE: the above is correct, failure is when the function returns 0 apparently
|
||||||
|
eprintln!("Cannot set hostname to {}", name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue