1use std::path::PathBuf;
11
12pub fn get_mock_bin() -> PathBuf {
27 get_bin("term-session-mock", "CARGO_BIN_EXE_term-session-mock")
28}
29
30fn bin_candidates(bin_name: &str) -> (PathBuf, PathBuf) {
32 let mut path = std::env::current_exe().expect("test exe path");
33 path.pop();
34 if path.ends_with("deps") {
35 path.pop();
36 }
37 let plain = path.join(format!("{bin_name}{}", std::env::consts::EXE_SUFFIX));
38 let deps_dir = path.join("deps");
39 (plain, deps_dir)
40}
41
42fn resolve_bin(bin_name: &str) -> Option<PathBuf> {
43 let (plain, deps_dir) = bin_candidates(bin_name);
44 if plain.exists() {
45 return Some(plain);
46 }
47
48 let suffix = std::env::consts::EXE_SUFFIX;
49 let prefix = format!("{bin_name}-");
50 if let Ok(entries) = std::fs::read_dir(&deps_dir) {
51 for entry in entries.flatten() {
52 let name = entry.file_name();
53 let name = name.to_string_lossy();
54 if name.starts_with(&prefix) && name.ends_with(suffix) {
55 return Some(entry.path());
56 }
57 }
58 }
59
60 None
61}
62
63fn build_bin() {
67 let manifest = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("Cargo.toml");
68 let status = std::process::Command::new(env!("CARGO"))
69 .arg("build")
70 .arg("--manifest-path")
71 .arg(&manifest)
72 .status()
73 .expect("failed to spawn `cargo build` for term-session-mock");
74 if !status.success() {
75 panic!(
76 "`cargo build --manifest-path {}` failed with {status}",
77 manifest.display()
78 );
79 }
80}
81
82fn get_bin(bin_name: &str, env_var: &str) -> PathBuf {
83 if let Ok(path) = std::env::var(env_var) {
84 return PathBuf::from(path);
85 }
86
87 let resolved = resolve_bin(bin_name);
88 if let Some(path) = resolved {
89 return path;
90 }
91
92 build_bin();
93
94 match resolve_bin(bin_name) {
95 Some(path) => path,
96 None => panic!(
97 "{bin_name} binary still missing after `cargo build`; \
98 searched {:?} and {:?}",
99 bin_candidates(bin_name).0,
100 bin_candidates(bin_name).1,
101 ),
102 }
103}
104
105pub const CHECK_PID_ALIVE: i32 = 0;
110pub const CHECK_PID_DEAD: i32 = 1;
112
113#[cfg(windows)]
115pub fn process_is_alive(pid: u32) -> bool {
116 use windows_sys::Win32::Foundation::{CloseHandle, STILL_ACTIVE};
117 use windows_sys::Win32::System::Threading::{
118 GetExitCodeProcess, OpenProcess, PROCESS_QUERY_LIMITED_INFORMATION,
119 };
120
121 unsafe {
122 let handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid);
123 if handle.is_null() {
124 return false;
125 }
126 let mut code: u32 = 0;
127 let ok = GetExitCodeProcess(handle, &mut code);
128 let _ = CloseHandle(handle);
129 ok != 0 && code == STILL_ACTIVE as u32
130 }
131}
132
133#[cfg(not(windows))]
135pub fn process_is_alive(pid: u32) -> bool {
136 unsafe { libc::kill(pid as i32, 0) == 0 }
138}