use crate::error::{NeofetchError, Result};
use std::ffi::OsStr;
use std::process::Stdio;
pub async fn execute_command(cmd: impl AsRef<OsStr>, args: &[impl AsRef<OsStr>]) -> Result<String> {
let cmd_ref = cmd.as_ref();
let cmd_str = cmd_ref.to_string_lossy().to_string();
let output = tokio::process::Command::new(cmd_ref)
.args(args)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.output()
.await
.map_err(|e| NeofetchError::command_execution(cmd_str.clone(), e))?;
if !output.status.success()
&& let Some(code) = output.status.code()
{
return Err(NeofetchError::command_failed(cmd_str, code));
}
Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
}
pub fn execute_command_sync(cmd: impl AsRef<OsStr>, args: &[impl AsRef<OsStr>]) -> Result<String> {
let cmd_ref = cmd.as_ref();
let cmd_str = cmd_ref.to_string_lossy().to_string();
let output = std::process::Command::new(cmd_ref)
.args(args)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.output()
.map_err(|e| NeofetchError::command_execution(cmd_str.clone(), e))?;
if !output.status.success()
&& let Some(code) = output.status.code()
{
return Err(NeofetchError::command_failed(cmd_str, code));
}
Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
}
pub async fn execute_command_optional(
cmd: impl AsRef<OsStr>,
args: &[impl AsRef<OsStr>],
) -> Option<String> {
execute_command(cmd, args).await.ok()
}
pub fn execute_command_sync_optional(
cmd: impl AsRef<OsStr>,
args: &[impl AsRef<OsStr>],
) -> Option<String> {
execute_command_sync(cmd, args).ok()
}
#[cfg(unix)]
pub fn get_process_name(pid: u32) -> Result<String> {
use crate::utils::read_file_to_string_sync;
let path = format!("/proc/{}/comm", pid);
read_file_to_string_sync(&path).map(|s| s.trim().to_string())
}
#[cfg(unix)]
pub fn get_parent_pid(pid: u32) -> Result<u32> {
let output = execute_command_sync(
"grep",
&["-i", "-F", "PPid:", &format!("/proc/{}/status", pid)],
)?;
let ppid_str = output
.split(':')
.nth(1)
.ok_or_else(|| NeofetchError::parse_error("PPid", "missing colon separator"))?
.trim();
ppid_str
.parse()
.map_err(|e| NeofetchError::parse_error("PPid", format!("invalid number: {}", e)))
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_execute_command() {
#[cfg(unix)]
let result = execute_command("echo", &["test"]).await;
#[cfg(windows)]
let result = execute_command("cmd", &["/C", "echo test"]).await;
assert!(result.is_ok());
}
#[test]
fn test_execute_command_sync() {
#[cfg(unix)]
let result = execute_command_sync("echo", &["test"]);
#[cfg(windows)]
let result = execute_command_sync("cmd", &["/C", "echo test"]);
assert!(result.is_ok());
}
}