Skip to content

Commit 6dec93f

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 419825a commit 6dec93f

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
66
## [Unreleased]
77

88
### Added
9+
- Added `nix::unistd::{getdomainname, setdomainname}`.
10+
([#816](https://github.com/nix-rust/nix/pull/816))
911

1012
### Changed
1113
- Display and Debug for SysControlAddr now includes all fields.

src/unistd.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,56 @@ pub fn gethostname() -> Result<CString> {
760760
})
761761
}
762762

763+
cfg_if!{
764+
if #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
765+
target_os = "ios", target_os = "macos"))] {
766+
type namelen_t = c_int;
767+
} else {
768+
type namelen_t = size_t;
769+
}
770+
}
771+
772+
/// Set the NIS domain name (see
773+
/// [setdomainname(2)](http://man7.org/linux/man-pages/man2/setdomainname.2.html)).
774+
#[cfg(not(target_os = "android"))]
775+
pub fn setdomainname<S: AsRef<OsStr>>(name: S) -> Result<()> {
776+
let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char;
777+
let len = name.as_ref().len() as namelen_t;
778+
let res = unsafe { libc::setdomainname(ptr, len) };
779+
Errno::result(res).map(drop)
780+
}
781+
782+
/// Get the NIS domain name, returning a `CString` on success (see
783+
/// [getdomainname(2)](http://man7.org/linux/man-pages/man2/getdomainname.2.html)).
784+
///
785+
/// This function call attempts to get the NIS domain name for the running system
786+
/// and return it as a NUL-terminated string.
787+
///
788+
/// # Examples
789+
///
790+
/// ```no_run
791+
/// use nix::unistd;
792+
///
793+
/// let domainname_cstr = unistd::getdomainname().expect("Failed getting domain name");
794+
/// let domainname = domainname_cstr.into_string().expect("Domain name wasn't valid UTF-8");
795+
/// println!("Domain name: {}", domainname);
796+
/// ```
797+
#[cfg(not(target_os = "android"))]
798+
pub fn getdomainname() -> Result<CString> {
799+
const MAXDOMAINNAMELEN: usize = 256;
800+
let buf = vec![0; MAXDOMAINNAMELEN];
801+
let ptr = unsafe { CString::from_vec_unchecked(buf).into_raw() };
802+
803+
let res = unsafe { libc::getdomainname(ptr, MAXDOMAINNAMELEN as namelen_t) };
804+
Errno::result(res).map(|_| {
805+
unsafe {
806+
// Ensure returned string is always null-terminated
807+
*ptr.offset((MAXDOMAINNAMELEN - 1) as isize) = 0;
808+
CString::from_raw(ptr)
809+
}
810+
})
811+
}
812+
763813
/// Close a raw file descriptor
764814
///
765815
/// 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
@@ -408,3 +408,12 @@ fn test_gethostname() {
408408
let hn_string = hn.unwrap().into_string();
409409
assert!(hn_string.is_ok(), "Error: {:?}", hn_string.unwrap_err());
410410
}
411+
412+
#[test]
413+
#[cfg(not(target_os = "android"))]
414+
fn test_getdomainname() {
415+
let dn = getdomainname();
416+
assert!(dn.is_ok(), "Error: {:?}", dn.unwrap_err());
417+
let dn_string = dn.unwrap().into_string();
418+
assert!(dn_string.is_ok(), "Error: {:?}", dn_string.unwrap_err());
419+
}

0 commit comments

Comments
 (0)