1use crate::ffi;
2use crate::utils::Boolean;
3use navigator::cli::LibinjectArgs;
4use spin::Mutex;
5use std::ffi::CStr;
6use std::os::raw::c_char;
7use std::sync::LazyLock;
8
9static ARGS: LazyLock<Mutex<Option<LibinjectArgs>>> = LazyLock::new(|| Mutex::new(None));
10
11pub unsafe fn parse(client_id: ffi::client_id_t) -> LibinjectArgs {
12 unsafe {
13 let args_str = get_option_array(client_id)
14 .expect("Failed reading cli argument array")
15 .expect("Expecting at least one cli arg");
16 let parsed_args = LibinjectArgs::from_vec(args_str);
17 let mut args = ARGS.lock();
18 *args = Some(parsed_args.clone());
19 parsed_args
20 }
21}
22
23pub fn get_args() -> Result<LibinjectArgs, String> {
24 let args = ARGS.lock();
25 args.clone()
26 .ok_or("Args must be parsed first with cli::parse(client_id)".to_string())
27}
28
29pub unsafe fn get_option_array(client_id: ffi::client_id_t) -> Result<Option<Vec<String>>, String> {
30 unsafe {
31 let mut argc: i32 = 0;
32 let mut argv: *mut *const c_char = std::ptr::null_mut();
33
34 match ffi::dr_get_option_array(client_id, &mut argc, &mut argv).as_bool() {
35 true => {
36 if argc == 0 {
37 return Ok(None);
38 }
39 if argv.is_null() {
40 return Err(format!(
41 "There were {argc} arguments, but the C pointer to the array was null!"
42 ));
43 }
44
45 let slice = std::slice::from_raw_parts(argv, argc as usize);
46 let vec = slice
47 .iter()
48 .map(|&ptr| {
49 CStr::from_ptr(ptr).to_string_lossy().into_owned()
51 })
52 .collect();
53
54 Ok(Some(vec))
55 }
56 false => Err("Call to dr_get_option_array failed".to_string()),
57 }
58 }
59}