origin_studio/
env.rs

1//! Inspection and manipulation of the process’s environment.
2
3use 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}