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