use clap::Parser;
use qssh::agent::QsshAgent;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[clap(name = "qssh-agent")]
#[clap(about = "QSSH Agent - Manages post-quantum SSH keys")]
struct Args {
#[clap(short = 's', long)]
socket: Option<String>,
#[clap(short = 'k', long)]
kill: bool,
#[clap(short = 'D', long)]
debug: bool,
#[clap(short = 'c', long)]
csh_style: bool,
}
#[tokio::main]
async fn main() {
let args = Args::parse();
if args.debug {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("debug"))
.init();
} else {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
.init();
}
let socket_path = args.socket.unwrap_or_else(|| {
format!("/tmp/qssh-agent-{}/agent.sock", std::process::id())
});
let socket_path = PathBuf::from(&socket_path);
if args.kill {
if socket_path.exists() {
std::fs::remove_file(&socket_path).ok();
println!("Agent killed");
} else {
eprintln!("No agent running");
}
return;
}
let agent = QsshAgent::new(socket_path.clone());
if !args.debug {
if args.csh_style {
println!("setenv QSSH_AUTH_SOCK {};", socket_path.display());
println!("echo Agent pid {};", std::process::id());
} else {
println!("QSSH_AUTH_SOCK={}; export QSSH_AUTH_SOCK;", socket_path.display());
println!("echo Agent pid {};", std::process::id());
}
}
if !args.debug {
use std::process::{Command, Stdio};
let exe = std::env::current_exe().expect("Failed to get current exe");
let mut cmd = Command::new(exe);
cmd.arg("-D")
.arg("-s")
.arg(socket_path.to_str().unwrap())
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null());
match cmd.spawn() {
Ok(child) => {
if !args.csh_style {
println!("echo Agent pid {};", child.id());
}
return;
}
Err(e) => {
eprintln!("Failed to fork: {}", e);
std::process::exit(1);
}
}
}
log::info!("Starting QSSH Agent on {:?}", socket_path);
let agent_clone = agent.clone();
tokio::spawn(async move {
loop {
tokio::time::sleep(std::time::Duration::from_secs(60)).await;
agent_clone.cleanup_expired_keys().await;
}
});
if let Err(e) = agent.start().await {
eprintln!("Agent error: {}", e);
std::process::exit(1);
}
}