use std::env;
use std::fs::File;
use std::net::TcpListener;
use std::net::UdpSocket;
use std::path::Path;
use std::process::Command;
use std::process::Stdio;
use std::thread;
use std::time::Duration;
fn find_exec(name: &str) -> std::path::PathBuf {
let this_exec = std::env::current_exe().expect("current exe");
let exec_dir = this_exec
.parent()
.expect("exe dir")
.parent()
.expect("target dir");
exec_dir.join(name)
}
fn child_main() {
let ready_path =
env::var("PTOOLS_TEST_READY_FILE").expect("PTOOLS_TEST_READY_FILE must be set");
let _tcp_listener = TcpListener::bind("127.0.0.1:0").expect("bind tcp listener");
let _udp_socket = UdpSocket::bind("127.0.0.1:0").expect("bind udp socket");
File::create(ready_path).expect("create ready file");
loop {
thread::sleep(Duration::from_millis(100));
}
}
fn parent_main() {
let ready_path =
env::var("PTOOLS_TEST_READY_FILE").expect("PTOOLS_TEST_READY_FILE must be set");
let mut child = Command::new(find_exec("examples/pfiles_sockopts_parent"))
.arg("--child")
.env("PTOOLS_TEST_READY_FILE", &ready_path)
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.spawn()
.expect("spawn child mode");
let ready_file = Path::new(&ready_path);
while !ready_file.exists() {
if let Some(status) = child.try_wait().expect("wait child") {
panic!("child exited early: {status}");
}
thread::sleep(Duration::from_millis(100));
}
let output = Command::new(find_exec("pfiles"))
.arg(child.id().to_string())
.stdin(Stdio::null())
.output()
.expect("run pfiles");
child.kill().expect("kill child");
let _ = child.wait();
let _ = std::fs::remove_file(ready_file);
if !output.status.success() {
eprintln!("pfiles failed: {:?}", output.status);
std::process::exit(1);
}
print!("{}", String::from_utf8_lossy(&output.stdout));
}
fn main() {
if env::args().any(|arg| arg == "--child") {
child_main();
} else {
parent_main();
}
}