Skip to content

Commit 09ff9d5

Browse files
committed
unistd: add {get,set}domainname
This implements `getdomainname(2)` and `setdomainname(2)`, which are common UNIX extensions not covered by POSIX. References: * http://man7.org/linux/man-pages/man2/getdomainname.2.html * http://man7.org/linux/man-pages/man2/setdomainname.2.html
1 parent 4b0159d commit 09ff9d5

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
3535
([#857](https://github.com/nix-rust/nix/pull/857))
3636
- Added `request_code_write_int!` on FreeBSD/DragonFlyBSD
3737
([#833](https://github.com/nix-rust/nix/pull/833))
38+
- Added `nix::unistd::{getdomainname, setdomainname}` for all platforms except Android.
39+
([#816](https://github.com/nix-rust/nix/pull/816))
3840

3941
### Changed
4042
- Display and Debug for SysControlAddr now includes all fields.

src/unistd.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,65 @@ pub fn gethostname() -> Result<OsString> {
774774
})
775775
}
776776

777+
cfg_if!{
778+
if #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
779+
target_os = "ios", target_os = "macos"))] {
780+
type namelen_t = c_int;
781+
} else if #[cfg(not(target_os = "android"))] {
782+
type namelen_t = size_t;
783+
}
784+
}
785+
786+
/// Set the NIS domain name (see
787+
/// [setdomainname(2)](http://man7.org/linux/man-pages/man2/setdomainname.2.html)).
788+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios",
789+
target_os = "linux", target_os = "macos", target_os = "netbsd",
790+
target_os = "openbsd"))]
791+
pub fn setdomainname<S: AsRef<OsStr>>(name: S) -> Result<()> {
792+
let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char;
793+
let len = name.as_ref().as_bytes().len() as namelen_t;
794+
let res = unsafe { libc::setdomainname(ptr, len) };
795+
Errno::result(res).map(drop)
796+
}
797+
798+
/// Get the NIS domain name, returning a `OsString` on success (see
799+
/// [getdomainname(2)](http://man7.org/linux/man-pages/man2/getdomainname.2.html)).
800+
///
801+
/// This function call attempts to get the NIS domain name for the
802+
/// running system.
803+
///
804+
/// # Examples
805+
///
806+
/// ```
807+
/// use nix::unistd;
808+
///
809+
/// let domainname_os = unistd::getdomainname().expect("Failed getting domain name");
810+
/// let domainname = domainname_os.into_string().expect("Domain name wasn't valid UTF-8");
811+
/// println!("Domain name: {}", domainname);
812+
/// ```
813+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios",
814+
target_os = "linux", target_os = "macos", target_os = "netbsd",
815+
target_os = "openbsd"))]
816+
pub fn getdomainname() -> Result<OsString> {
817+
// Minimum hostname maximum length as defined by POSIX,
818+
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
819+
const _POSIX_HOST_NAME_MAX: c_long = 255;
820+
let buf_len = sysconf(SysconfVar::HOST_NAME_MAX)
821+
.unwrap_or(None).unwrap_or(_POSIX_HOST_NAME_MAX + 1);
822+
let buf = vec![0; buf_len as usize];
823+
let ptr = unsafe { CString::from_vec_unchecked(buf).into_raw() };
824+
825+
let res = unsafe { libc::getdomainname(ptr, buf_len as namelen_t) };
826+
Errno::result(res).map(|_| {
827+
let cstr = unsafe {
828+
// Ensure CString is null-terminated
829+
*ptr.offset((buf_len - 1) as isize) = 0;
830+
CString::from_raw(ptr)
831+
};
832+
OsString::from_vec(cstr.into_bytes())
833+
})
834+
}
835+
777836
/// Close a raw file descriptor
778837
///
779838
/// Be aware that many Rust types implicitly close-on-drop, including

test/test_unistd.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,12 @@ fn test_gethostname() {
463463
let hn = gethostname().expect("gethostname failed");
464464
hn.into_string().expect("hostname contains invalid data");
465465
}
466+
467+
#[test]
468+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios",
469+
target_os = "linux", target_os = "macos", target_os = "netbsd",
470+
target_os = "openbsd"))]
471+
fn test_getdomainname() {
472+
let dn = getdomainname().expect("getdomainname failed");
473+
dn.into_string().expect("domainname contains invalid data");
474+
}

0 commit comments

Comments
 (0)