use std::path::PathBuf;
pub fn get_mock_bin() -> PathBuf {
if let Ok(path) = std::env::var("CARGO_BIN_EXE_term-session-mock") {
return PathBuf::from(path);
}
let resolved = resolve_mock_bin();
if let Some(path) = resolved {
return path;
}
build_mock_bin();
match resolve_mock_bin() {
Some(path) => path,
None => panic!(
"term-session-mock binary still missing after `cargo build`; \
searched {:?} and {:?}",
mock_bin_candidates().0,
mock_bin_candidates().1,
),
}
}
fn mock_bin_candidates() -> (PathBuf, PathBuf) {
let mut path = std::env::current_exe().expect("test exe path");
path.pop();
if path.ends_with("deps") {
path.pop();
}
let plain = path.join(format!("term-session-mock{}", std::env::consts::EXE_SUFFIX));
let deps_dir = path.join("deps");
(plain, deps_dir)
}
fn resolve_mock_bin() -> Option<PathBuf> {
let (plain, deps_dir) = mock_bin_candidates();
if plain.exists() {
return Some(plain);
}
let suffix = std::env::consts::EXE_SUFFIX;
if let Ok(entries) = std::fs::read_dir(&deps_dir) {
for entry in entries.flatten() {
let name = entry.file_name();
let name = name.to_string_lossy();
if name.starts_with("term-session-mock-") && name.ends_with(suffix) {
return Some(entry.path());
}
}
}
None
}
fn build_mock_bin() {
let manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml");
let status = std::process::Command::new(env!("CARGO"))
.arg("build")
.arg("--manifest-path")
.arg(&manifest)
.status()
.expect("failed to spawn `cargo build` for term-session-mock");
if !status.success() {
panic!(
"`cargo build --manifest-path {}` failed with {status}",
manifest.display()
);
}
}
pub const CHECK_PID_ALIVE: i32 = 0;
pub const CHECK_PID_DEAD: i32 = 1;
#[cfg(windows)]
pub fn process_is_alive(pid: u32) -> bool {
use windows_sys::Win32::Foundation::{CloseHandle, STILL_ACTIVE};
use windows_sys::Win32::System::Threading::{
GetExitCodeProcess, OpenProcess, PROCESS_QUERY_LIMITED_INFORMATION,
};
unsafe {
let handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid);
if handle.is_null() {
return false;
}
let mut code: u32 = 0;
let ok = GetExitCodeProcess(handle, &mut code);
let _ = CloseHandle(handle);
ok != 0 && code == STILL_ACTIVE as u32
}
}
#[cfg(not(windows))]
pub fn process_is_alive(pid: u32) -> bool {
unsafe { libc::kill(pid as i32, 0) == 0 }
}