#![allow(dead_code, non_snake_case, non_camel_case_types)]
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int};
use nix::libc::{dlclose, dlerror, dlopen, dlsym};
const RTLD_NOW: c_int = 0x2;
type str_str_fn = extern "C" fn(*const c_char) -> *const c_char;
type str_int_fn = extern "C" fn(*const c_char) -> c_int;
type int_str_fn = extern "C" fn(c_int) -> *const c_char;
type int_int_fn = extern "C" fn(c_int) -> c_int;
pub fn os_libcall(
libname: Option<&str>,
funcname: Option<&str>,
argv: Option<&str>,
argi: i32,
str_out: Option<&mut Option<String>>,
int_out: &mut i32,
) -> bool {
let (libname, funcname) = match (libname, funcname) {
(Some(l), Some(f)) => (l, f),
_ => return false,
};
let dlerr = || -> String {
unsafe {
let p = dlerror();
if p.is_null() {
String::new()
} else {
CStr::from_ptr(p).to_string_lossy().into_owned()
}
}
};
let c_libname = match CString::new(libname) {
Ok(s) => s,
Err(_) => return false,
};
let c_funcname = match CString::new(funcname) {
Ok(s) => s,
Err(_) => return false,
};
let lib = unsafe { dlopen(c_libname.as_ptr(), RTLD_NOW) };
if lib.is_null() {
crate::ported::message::semsg(&format!("dlerror = \"{}\"", dlerr()));
return false;
}
let fnptr = unsafe { dlsym(lib, c_funcname.as_ptr()) };
if fnptr.is_null() {
crate::ported::message::semsg(&format!("dlerror = \"{}\"", dlerr()));
unsafe { dlclose(lib) };
return false;
}
let c_argv = argv.and_then(|s| CString::new(s).ok());
let mut success = true;
if let Some(out) = str_out {
let res: *const c_char = match &c_argv {
Some(a) => {
let sfn: str_str_fn = unsafe { std::mem::transmute(fnptr) };
sfn(a.as_ptr())
}
None => {
let ifn: int_str_fn = unsafe { std::mem::transmute(fnptr) };
ifn(argi as c_int)
}
};
let addr = res as isize;
*out = if !res.is_null() && addr != 1 && addr != -1 {
Some(
unsafe { CStr::from_ptr(res) }
.to_string_lossy()
.into_owned(),
)
} else {
None
};
} else {
*int_out = match &c_argv {
Some(a) => {
let sfn: str_int_fn = unsafe { std::mem::transmute(fnptr) };
sfn(a.as_ptr()) as i32
}
None => {
let ifn: int_int_fn = unsafe { std::mem::transmute(fnptr) };
ifn(argi as c_int) as i32
}
};
let _ = &mut success; }
unsafe { dlclose(lib) };
let _ = success;
true
}