Skip to main content

relibc/header/netdb/
host.rs

1use 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    {} // TODO handle error
42    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    } // TODO handle error
52    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}