relibc/header/netdb/
host.rs1use alloc::{boxed::Box, str::SplitWhitespace, vec::Vec};
2use core::{mem, ptr};
3
4use crate::{
5 error::ResultExt,
6 header::{
7 arpa_inet::inet_aton, fcntl::O_RDONLY, netinet_in::in_addr, sys_socket::constants::AF_INET,
8 unistd::SEEK_SET,
9 },
10 platform::{
11 Pal, Sys,
12 rlb::{Line, RawLineBuffer},
13 types::{c_char, c_int},
14 },
15 raw_cell::RawCell,
16};
17
18use super::{bytes_to_box_str, hostent};
19
20static mut HOSTDB: c_int = -1;
21pub static mut HOST_ENTRY: hostent = hostent {
22 h_name: ptr::null_mut(),
23 h_aliases: ptr::null_mut(),
24 h_addrtype: 0,
25 h_length: 0,
26 h_addr_list: ptr::null_mut(),
27};
28pub static HOST_NAME: RawCell<Option<Vec<u8>>> = RawCell::new(None);
29pub static HOST_ALIASES: RawCell<Option<Vec<Vec<u8>>>> = RawCell::new(None);
30static _HOST_ALIASES: RawCell<Option<Vec<*mut c_char>>> = RawCell::new(None);
31pub static mut HOST_ADDR: Option<in_addr> = None;
32pub static mut HOST_ADDR_LIST: [*mut c_char; 2] = [ptr::null_mut(); 2];
33pub static mut _HOST_ADDR_LIST: [u8; 4] = [0u8; 4];
34static mut H_POS: usize = 0;
35pub static mut HOST_STAYOPEN: c_int = 0;
36
37#[unsafe(no_mangle)]
38pub unsafe extern "C" fn endhostent() {
39 if unsafe { HOSTDB } >= 0
40 && let Ok(()) = Sys::close(unsafe { HOSTDB })
41 {} unsafe { HOSTDB = -1 };
43}
44
45#[unsafe(no_mangle)]
46pub unsafe extern "C" fn sethostent(stayopen: c_int) {
47 unsafe { HOST_STAYOPEN = stayopen };
48 if unsafe { HOSTDB } < 0 {
49 unsafe { HOSTDB = Sys::open(c"/etc/hosts".into(), O_RDONLY, 0).or_minus_one_errno() }
50 } else if Sys::lseek(unsafe { HOSTDB }, 0, SEEK_SET).is_ok() {
51 } unsafe { H_POS = 0 };
53}
54
55#[unsafe(no_mangle)]
56pub unsafe extern "C" fn gethostent() -> *mut hostent {
57 if unsafe { HOSTDB } < 0 {
58 unsafe { HOSTDB = Sys::open(c"/etc/hosts".into(), O_RDONLY, 0).or_minus_one_errno() };
59 }
60 let mut rlb = RawLineBuffer::new(unsafe { HOSTDB });
61 rlb.seek(unsafe { H_POS });
62
63 let mut r: Box<str> = Box::default();
64 while r.is_empty() || r.split_whitespace().next().is_none() || r.starts_with('#') {
65 r = match rlb.next() {
66 Line::Some(s) => bytes_to_box_str(s),
67 _ => {
68 if unsafe { HOST_STAYOPEN } == 0 {
69 unsafe { endhostent() };
70 }
71 return ptr::null_mut();
72 }
73 };
74 }
75 rlb.next();
76 unsafe { H_POS = rlb.line_pos() };
77
78 let mut iter: SplitWhitespace = r.split_whitespace();
79
80 let addr_vec: Vec<u8> = iter.next().unwrap().bytes().chain(Some(b'\0')).collect();
81 let addr_cstr = addr_vec.as_slice().as_ptr().cast::<c_char>();
82 let mut addr = mem::MaybeUninit::uninit();
83 unsafe { inet_aton(addr_cstr, addr.as_mut_ptr()) };
84 let addr = unsafe { addr.assume_init() };
85
86 unsafe {
87 _HOST_ADDR_LIST = addr.s_addr.to_ne_bytes();
88 HOST_ADDR_LIST = [(&raw mut _HOST_ADDR_LIST).cast::<c_char>(), ptr::null_mut()];
89
90 HOST_ADDR = Some(addr);
91 }
92
93 let host_name = iter.next().unwrap().bytes().chain(Some(b'\0')).collect();
94
95 let mut _host_aliases: Vec<Vec<u8>> = iter
96 .map(|alias| alias.bytes().chain(Some(b'\0')).collect())
97 .collect();
98 unsafe { HOST_ALIASES.unsafe_set(Some(_host_aliases)) };
99
100 let mut host_aliases: Vec<*mut c_char> = unsafe {
101 HOST_ALIASES
102 .unsafe_mut()
103 .as_mut()
104 .unwrap()
105 .iter_mut()
106 .map(|x| x.as_mut_ptr().cast::<c_char>())
107 .chain([ptr::null_mut(), ptr::null_mut()])
108 .collect()
109 };
110
111 unsafe { HOST_NAME.unsafe_set(Some(host_name)) };
112
113 unsafe {
114 HOST_ENTRY = hostent {
115 h_name: HOST_NAME
116 .unsafe_mut()
117 .as_mut()
118 .unwrap()
119 .as_mut_ptr()
120 .cast::<c_char>(),
121 h_aliases: host_aliases.as_mut_slice().as_mut_ptr(),
122 h_addrtype: AF_INET,
123 h_length: 4,
124 h_addr_list: (&raw mut HOST_ADDR_LIST).cast(),
125 };
126 _HOST_ALIASES.unsafe_set(Some(host_aliases));
127 }
128 if unsafe { HOST_STAYOPEN } == 0 {
129 unsafe { endhostent() };
130 }
131 (&raw mut HOST_ENTRY).cast::<hostent>()
132}