use aurora_core::{AuroraResult, Pipeline, Value};
use std::process::Command;
use std::fs;
use walkdir::WalkDir;
pub fn unix_ps() -> AuroraResult<Pipeline> {
let output = Command::new("ps")
.args(["aux"])
.output()
.map_err(|e| aurora_core::AuroraError::ModuleError(
format!("ps failed: {}", e)
))?;
let stdout = String::from_utf8_lossy(&output.stdout);
let mut rows: Vec<Vec<Value>> = Vec::new();
for (i, line) in stdout.lines().enumerate() {
if i == 0 || line.trim().is_empty() { continue; }
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 11 {
rows.push(vec![
Value::String(parts[0].into()),
Value::String(parts[1].into()),
Value::String(parts[2].into()),
Value::String(parts[3].into()),
Value::String(parts[10].into()),
]);
}
}
Ok(Pipeline::table(
vec!["user".into(), "pid".into(), "cpu%".into(), "mem%".into(), "command".into()],
rows,
))
}
pub fn unix_df(human: bool) -> AuroraResult<Pipeline> {
let mut cmd = Command::new("df");
if human {
cmd.arg("-h");
}
let output = cmd.output()
.map_err(|e| aurora_core::AuroraError::ModuleError(
format!("df failed: {}", e)
))?;
let stdout = String::from_utf8_lossy(&output.stdout);
let mut rows: Vec<Vec<Value>> = Vec::new();
for (i, line) in stdout.lines().enumerate() {
if i == 0 || line.trim().is_empty() { continue; }
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 6 {
rows.push(vec![
Value::String(parts[0].into()),
Value::String(parts[1].into()),
Value::String(parts[2].into()),
Value::String(parts[3].into()),
Value::String(parts[4].into()),
Value::String(parts[5].into()),
]);
}
}
Ok(Pipeline::table(
vec!["filesystem".into(), "size".into(), "used".into(), "avail".into(), "use%".into(), "mounted".into()],
rows,
))
}
pub fn unix_du(path: &str) -> AuroraResult<Pipeline> {
let mut rows: Vec<Vec<Value>> = Vec::new();
for entry in WalkDir::new(path).into_iter().filter_map(|e| e.ok()) {
if entry.file_type().is_dir() {
let p = entry.path().to_string_lossy().to_string();
let mut size: i64 = 0;
if let Ok(dir) = fs::read_dir(entry.path()) {
for sub in dir.flatten() {
if let Ok(meta) = sub.metadata() {
size += meta.len() as i64;
}
}
}
rows.push(vec![
Value::String(p),
Value::Int(size),
]);
}
}
Ok(Pipeline::table(
vec!["path".into(), "size_bytes".into()],
rows,
))
}
pub fn unix_uptime() -> AuroraResult<Pipeline> {
let content = fs::read_to_string("/proc/uptime")
.ok();
if let Some(uptime_str) = content {
if let Some(secs) = uptime_str.split(' ').next() {
let secs = secs.trim();
let secs_f: f64 = secs.parse().unwrap_or(0.0);
let days = (secs_f / 86400.0) as i64;
let hours = ((secs_f % 86400.0) / 3600.0) as i64;
let minutes = ((secs_f % 3600.0) / 60.0) as i64;
return Ok(Pipeline::table(
vec!["uptime_seconds".into(), "days".into(), "hours".into(), "minutes".into()],
vec![vec![
Value::Float(secs_f),
Value::Int(days),
Value::Int(hours),
Value::Int(minutes),
]],
));
}
}
let output = Command::new("uptime")
.output()
.ok();
if let Some(out) = output {
let stdout = String::from_utf8_lossy(&out.stdout);
return Ok(Pipeline::table(
vec!["uptime".into()],
vec![vec![Value::String(stdout.trim().into())]],
));
}
Ok(Pipeline::table(
vec!["uptime".into()],
vec![vec![Value::String("unknown".into())]],
))
}
pub fn unix_env() -> AuroraResult<Pipeline> {
let mut rows: Vec<Vec<Value>> = Vec::new();
for (key, value) in std::env::vars() {
rows.push(vec![
Value::String(key),
Value::String(value),
]);
}
Ok(Pipeline::table(
vec!["key".into(), "value".into()],
rows,
))
}
pub fn unix_uname() -> AuroraResult<Pipeline> {
let output = Command::new("uname")
.arg("-a")
.output()
.map_err(|e| aurora_core::AuroraError::ModuleError(
format!("uname failed: {}", e)
))?;
let stdout = String::from_utf8_lossy(&output.stdout);
let parts: Vec<&str> = stdout.trim().split_whitespace().collect();
let kernel = parts.get(0).copied().unwrap_or("");
let hostname = parts.get(1).copied().unwrap_or("");
let kernel_release = parts.get(2).copied().unwrap_or("");
let kernel_version = parts.get(3).copied().unwrap_or("");
let arch = if parts.len() > 11 { parts[11] } else { parts.last().copied().unwrap_or("") };
Ok(Pipeline::table(
vec!["kernel".into(), "hostname".into(), "release".into(), "version".into(), "arch".into()],
vec![vec![
Value::String(kernel.into()),
Value::String(hostname.into()),
Value::String(kernel_release.into()),
Value::String(kernel_version.into()),
Value::String(arch.into()),
]],
))
}