use std::collections::HashMap;
use std::path::PathBuf;
use std::time::Duration;
use tatara_eval::Interpreter;
use tatara_init::{InitConfig, LinuxSupervisor, Pid};
use tatara_lisp::{domain::TataraDomain, read};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();
if let Some(idx) = args.iter().position(|a| a == "--eval") {
let form = args.get(idx + 1).ok_or("--eval needs a Lisp form")?;
let interp = Interpreter::new_with_system();
let value = interp.eval_source(form)?;
eprintln!("[tatara-init:eval] {value}");
return Ok(());
}
let path = resolve_config_path();
let source = std::fs::read_to_string(&path)
.map_err(|e| format!("failed to read {}: {e}", path.display()))?;
let forms = read(&source)?;
let form = forms
.into_iter()
.next()
.ok_or("config file contains no forms")?;
let cfg = InitConfig::compile_from_sexp(&form)?;
eprintln!(
"[tatara-init] booting '{}' with {} service(s)",
cfg.name,
cfg.services.len()
);
for result in tatara_init::mount_early_filesystems() {
match result {
Ok(m) => eprintln!("[tatara-init] mounted {} ({})", m.target, m.fstype),
Err(e) => eprintln!("[tatara-init] mount warn: {e}"),
}
}
for m in &cfg.mounts {
match tatara_init::mount_extra(&m.source, &m.target, &m.fstype, m.options.as_deref()) {
Ok(()) => eprintln!(
"[tatara-init] mounted {} ({} from {})",
m.target, m.fstype, m.source
),
Err(e) => eprintln!("[tatara-init] mount warn: {e}"),
}
}
let mut sup = LinuxSupervisor::new();
let by_name = tatara_init::supervisor::boot(&mut sup, &cfg)?;
let mut tracking: HashMap<Pid, String> = by_name.into_iter().map(|(n, p)| (p, n)).collect();
loop {
let events = tatara_init::supervisor::run_once(&mut sup, &cfg, &mut tracking)?;
for ev in events {
eprintln!(
"[tatara-init] reaped {} (pid={}) status={}{}",
ev.name,
ev.pid,
ev.exit_status,
match ev.restarted_as {
Some(p) => format!(" → restarted as {p}"),
None => "".into(),
}
);
}
std::thread::sleep(Duration::from_millis(250));
}
}
fn resolve_config_path() -> PathBuf {
if let Some(arg) = std::env::args().nth(1) {
return PathBuf::from(arg);
}
if let Ok(env) = std::env::var("TATARA_INIT_CONFIG") {
return PathBuf::from(env);
}
PathBuf::from("/etc/tatara/init.lisp")
}