use clap::Parser;
use kranz_cli::cli::{Cli, Command};
use kranz_cli::commands;
use std::process::ExitCode;
#[cfg(windows)]
const WINDOWS_MAIN_STACK_BYTES: usize = 8 * 1024 * 1024;
#[cfg(windows)]
fn main() -> ExitCode {
let thread = match std::thread::Builder::new()
.name("kranz-main".to_string())
.stack_size(WINDOWS_MAIN_STACK_BYTES)
.spawn(main_inner)
{
Ok(thread) => thread,
Err(error) => {
eprintln!("kranz: failed to start the Windows main thread: {error}");
return ExitCode::from(1);
}
};
match thread.join() {
Ok(code) => code,
Err(_) => {
eprintln!("kranz: Windows main thread panicked");
ExitCode::from(1)
}
}
}
#[cfg(not(windows))]
fn main() -> ExitCode {
main_inner()
}
fn main_inner() -> ExitCode {
#[cfg(windows)]
if kranz_engine::sandbox_windows::internal_hostile_child_requested() {
return match kranz_engine::sandbox_windows::run_internal_hostile_child() {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
eprintln!("kranz AppContainer hostile child: {error}");
ExitCode::from(1)
}
};
}
#[cfg(windows)]
if kranz_engine::sandbox_windows::internal_launcher_requested() {
return match kranz_engine::sandbox_windows::run_internal_launcher() {
Ok(code) => ExitCode::from(code.clamp(0, 255) as u8),
Err(error) => {
eprintln!("kranz AppContainer launcher: {error}");
ExitCode::from(1)
}
};
}
#[cfg(windows)]
if kranz_engine::sandbox_windows::internal_self_test_requested()
|| kranz_engine::sandbox_windows::internal_gate_self_test_requested()
{
let _ = tracing_subscriber::fmt()
.with_max_level(tracing::Level::ERROR)
.with_writer(std::io::stderr)
.with_ansi(false)
.try_init();
}
#[cfg(windows)]
if kranz_engine::sandbox_windows::internal_self_test_requested() {
return match kranz_engine::sandbox_windows::run_production_hostile_self_test() {
Ok(receipt) => {
println!("{receipt}");
ExitCode::SUCCESS
}
Err(error) => {
eprintln!("kranz AppContainer production self-test: {error}");
ExitCode::from(1)
}
};
}
#[cfg(windows)]
if kranz_engine::sandbox_windows::internal_gate_self_test_requested() {
return match kranz_engine::sandbox_windows::run_production_gate_self_test() {
Ok(receipt) => {
println!("{receipt}");
ExitCode::SUCCESS
}
Err(error) => {
eprintln!("kranz AppContainer production gate self-test: {error}");
ExitCode::from(1)
}
};
}
let runtime = match tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
{
Ok(runtime) => runtime,
Err(error) => {
eprintln!("kranz: failed to initialize async runtime: {error}");
return ExitCode::from(1);
}
};
runtime.block_on(run_cli())
}
async fn run_cli() -> ExitCode {
rustls::crypto::ring::default_provider()
.install_default()
.expect("install rustls ring CryptoProvider before any TLS use");
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("warn")),
)
.with_writer(std::io::stderr)
.init();
let cli = Cli::parse();
let interruptible = matches!(
cli.command,
Command::Exec { .. } | Command::Run | Command::Work { .. }
);
let result = if interruptible {
tokio::select! {
biased;
signal = tokio::signal::ctrl_c() => {
match signal {
Ok(()) => {
eprintln!("kranz: interrupted; mission state is retained for resume");
Ok(130)
}
Err(error) => Err(error.into()),
}
}
result = commands::run_cli(cli) => result,
}
} else {
commands::run_cli(cli).await
};
match result {
Ok(code) => ExitCode::from(code.clamp(0, 255) as u8),
Err(e) => {
eprintln!("kranz: {e:#}");
ExitCode::from(1)
}
}
}