1use core::ffi::CStr;
4use core::ptr::null_mut;
5use core::{slice, str};
6
7pub(crate) struct MainArgs {
8 pub(crate) argc: i32,
9 pub(crate) argv: *mut *mut u8,
10 pub(crate) envp: *mut *mut u8,
11}
12
13pub(crate) static mut MAIN_ARGS: MainArgs = MainArgs {
14 argc: 0,
15 argv: null_mut(),
16 envp: null_mut(),
17};
18
19unsafe impl Send for MainArgs {}
20unsafe impl Sync for MainArgs {}
21
22#[derive(Copy, Clone, Debug, Eq, PartialEq)]
23pub enum VarError {
24 NotPresent,
25 NotUnicode,
26}
27
28pub fn var<K: AsRef<str>>(key: K) -> Result<&'static str, VarError> {
29 unsafe {
30 let mut ptr = MAIN_ARGS.envp;
31 let key_bytes = key.as_ref().as_bytes();
32 loop {
33 let env = *ptr;
34 if env.is_null() {
35 break;
36 }
37 let mut c = env;
38 while *c != b'=' {
39 c = c.add(1);
40 }
41 if key_bytes
42 == slice::from_raw_parts(env.cast::<u8>(), c.offset_from(env).try_into().unwrap())
43 {
44 return str::from_utf8(CStr::from_ptr(c.add(1).cast()).to_bytes())
45 .map_err(|_| VarError::NotUnicode);
46 }
47 ptr = ptr.add(1);
48 }
49 }
50 Err(VarError::NotPresent)
51}
52
53pub fn args() -> Args {
54 Args { pos: 0 }
55}
56
57pub struct Args {
58 pos: usize,
59}
60
61impl Iterator for Args {
62 type Item = &'static str;
63
64 fn next(&mut self) -> Option<Self::Item> {
65 unsafe {
66 if self.pos < MAIN_ARGS.argc as usize {
67 let arg = MAIN_ARGS.argv.add(self.pos);
68 self.pos += 1;
69 let cstr = CStr::from_ptr(arg.read().cast());
70 return Some(core::str::from_utf8(cstr.to_bytes()).unwrap());
71 }
72 }
73 None
74 }
75}
76
77impl ExactSizeIterator for Args {
78 fn len(&self) -> usize {
79 unsafe { MAIN_ARGS.argc as usize - self.pos }
80 }
81}