use std::{
ffi::OsStr,
fmt::Debug,
process::{Command, Stdio},
};
pub fn exec<I, S>(cmd: S, args: I) -> Option<String>
where
I: IntoIterator<Item = S> + Debug,
S: AsRef<OsStr> + Debug,
{
let output = Command::new(cmd)
.args(args)
.stdin(Stdio::null())
.output()
.ok()?;
Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
}
pub async fn exec_async<S, I>(cmd: S, args: I) -> Option<String>
where
I: IntoIterator<Item = S> + Debug,
S: AsRef<OsStr> + Debug,
{
let output = tokio::process::Command::new(cmd)
.args(args)
.stdin(Stdio::null())
.output()
.await
.ok()?;
Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
}
pub fn get_file_name(path: &str) -> Option<String> {
let path = path.replace('\\', "/");
let name = path.split('/').next_back()?.split('.').next()?.trim();
Some(name.into())
}
pub fn get_pid_name(id: u32) -> Option<String> {
std::fs::read_to_string(format!("/proc/{id}/comm").as_str())
.ok()
.map(|i| i.trim().to_string())
}
pub fn get_ppid(id: u32) -> Option<u32> {
if let Some(ppid) = exec(
"grep",
["-i", "-F", "PPid:", format!("/proc/{id}/status").as_str()],
) {
let ppid = ppid.split(':').next_back()?.trim();
let ppid: u32 = ppid.parse().ok()?;
return Some(ppid);
}
None
}
#[cfg(target_os = "android")]
unsafe extern "C" {
fn __system_property_get(name: *const libc::c_char, value: *mut libc::c_char) -> i32;
}
#[cfg(target_os = "android")]
pub fn get_property(property: &str) -> Option<String> {
use std::ffi::{CStr, CString};
use std::io;
let prop_cstr = CString::new(property)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))
.ok()?;
let mut buffer = [0i8; 92];
let result = unsafe {
__system_property_get(
prop_cstr.as_ptr() as *mut u8,
buffer.as_mut_ptr() as *mut u8,
)
};
if result < 0 {
return None;
}
let value = unsafe {
CStr::from_ptr(buffer.as_ptr() as *const u8)
.to_string_lossy()
.into_owned()
};
if value.is_empty() {
return None;
}
Some(value)
}
pub fn detect_cpu(name: &str) -> Option<String> {
crate::mappings::CPU_MAPPINGS.iter().find_map(|i| {
if i.0 == name {
Some(i.1.to_string())
} else {
None
}
})
}
pub fn detect_locale(name: &str) -> Option<String> {
crate::mappings::LOCALE_MAPPINGS.iter().find_map(|i| {
if i.0 == name {
Some(i.2.to_string())
} else {
None
}
})
}