#[cfg(unix)]
use std::{
fs,
io::{self, Write as _},
os::unix::fs::PermissionsExt as _,
path::Path,
process::{Command, Stdio},
};
#[cfg(unix)]
use crate::child::{CleanupPolicy, OwnedChild};
#[cfg(unix)]
pub mod crash_barrier;
pub mod http;
pub mod net;
#[cfg(unix)]
pub fn process_state(pid: u32) -> io::Result<Option<char>> {
use crate::tool::{OutputLimit, OutputLimits, capture_command};
let output = capture_command(
Command::new("/bin/ps").args(["-p", &pid.to_string(), "-o", "stat="]),
OutputLimits {
stdout: OutputLimit::Terminate(4096),
stderr: OutputLimit::Terminate(4096),
timeout: None,
},
)
.map_err(io::Error::other)?;
if output.status.code() == Some(1) && output.stdout.is_empty() && output.stderr.is_empty() {
return Ok(None);
}
if !output.status.success() {
return Err(io::Error::other(format!(
"process-state inspection failed: {}",
output.status
)));
}
let state = std::str::from_utf8(&output.stdout)
.map_err(|error| io::Error::new(io::ErrorKind::InvalidData, error))?;
Ok(state.trim().chars().next())
}
#[cfg(unix)]
pub fn write_executable_script(path: &Path, contents: impl AsRef<[u8]>) -> io::Result<()> {
let mut writer = OwnedChild::spawn(
Command::new("/bin/sh")
.args(["-c", "cat > \"$1\"", "write-test-script"])
.arg(path)
.stdin(Stdio::piped()),
CleanupPolicy::KillAndWait,
)?;
let written = writer
.take_stdin()
.ok_or_else(|| io::Error::other("script writer stdin missing"))?
.write_all(contents.as_ref());
let status = writer.wait();
written?;
let status = status?;
if !status.success() {
return Err(io::Error::other(format!("script writer failed: {status}")));
}
let mut permissions = fs::metadata(path)?.permissions();
permissions.set_mode(0o755);
fs::set_permissions(path, permissions)
}
#[cfg(all(test, unix))]
mod tests;