feat: init - dynamic service discovery via init.toml

This commit is contained in:
2026-08-10 17:00:52 +02:00
parent e25ef470e0
commit 69725658cf
4 changed files with 174 additions and 27 deletions
+109 -16
View File
@@ -1,11 +1,12 @@
/*
* main.cpp
* Init system for MontaukOS (PID 0)
* Chains system services then launches the shell.
* Discovers and starts system services from 0:/config/init.toml.
* Copyright (c) 2026 Daniel Hammer
*/
#include <montauk/syscall.h>
#include <montauk/config.h>
#include <libc/stdio.h>
// ---- ANSI color codes ----
@@ -88,31 +89,123 @@ static bool run_service(const char* path, const char* name, bool wait = true) {
return true;
}
// ---- Service configuration ----
static constexpr const char* SERVICE_PREFIX = "services.";
static bool is_service_table(const montauk::toml::Value* value) {
if (!value || value->type != montauk::toml::Type::Table || !value->key)
return false;
if (!montauk::starts_with(value->key, SERVICE_PREFIX))
return false;
// Only [services.<id>] declares a service. Nested tables belong to that
// service and must not be treated as additional services.
const char* id = value->key + montauk::slen(SERVICE_PREFIX);
if (!*id) return false;
while (*id) {
if (*id == '.') return false;
id++;
}
return true;
}
static void service_key(char* out, int out_size, const char* id, const char* field) {
snprintf(out, out_size, "%s%s.%s", SERVICE_PREFIX, id, field);
}
static montauk::toml::Value* find_service(const montauk::toml::Doc& doc, const char* id) {
char table_key[256];
snprintf(table_key, sizeof(table_key), "%s%s", SERVICE_PREFIX, id);
return doc.get_table(table_key);
}
static bool run_configured_service(const montauk::toml::Doc& doc,
montauk::toml::Value* service,
int fallback_depth = 0) {
const char* id = service->key + montauk::slen(SERVICE_PREFIX);
char key[256];
char msg[192];
service_key(key, sizeof(key), id, "name");
const char* name = doc.get_string(key, id);
service_key(key, sizeof(key), id, "enabled");
if (!doc.get_bool(key, true)) {
snprintf(msg, sizeof(msg), "%s disabled, skipping", name);
log_info(msg);
return true;
}
service_key(key, sizeof(key), id, "path");
const char* path = doc.get_string(key, "");
if (!path[0]) {
snprintf(msg, sizeof(msg), "Service %s has no path, skipping", id);
log_err(msg);
return false;
}
service_key(key, sizeof(key), id, "optional");
bool optional = doc.get_bool(key, false);
if (optional && !service_installed(path)) {
snprintf(msg, sizeof(msg), "%s not installed, skipping", name);
log_info(msg);
return true;
}
service_key(key, sizeof(key), id, "wait");
bool wait = doc.get_bool(key, true);
if (run_service(path, name, wait)) return true;
service_key(key, sizeof(key), id, "fallback");
const char* fallback = doc.get_string(key, "");
if (!fallback[0]) return false;
if (fallback_depth >= 8) {
log_err("Service fallback chain is too deep");
return false;
}
auto* fallback_service = find_service(doc, fallback);
if (!fallback_service) {
snprintf(msg, sizeof(msg), "Fallback service %s is not configured", fallback);
log_err(msg);
return false;
}
snprintf(msg, sizeof(msg), "%s failed, falling back to %s", name, fallback);
log_warn(msg);
return run_configured_service(doc, fallback_service, fallback_depth + 1);
}
// ---- Main ----
extern "C" void _start() {
log_info("The Montauk Operating System");
// ---- Stage 1: Network configuration (non-blocking) ----
run_service("0:/os/dhcp.elf", "dhcp", false);
run_service("0:/os/ntp.elf", "network time", false);
auto config = montauk::config::load("init");
int discovered = 0;
// Printing is an optional install component; skip quietly when absent.
if (service_installed("0:/os/printd.elf"))
run_service("0:/os/printd.elf", "print spooler", false);
else
log_info("Print spooler not installed, skipping");
// Table order is file order, making the config itself the startup order.
for (int i = 0; i < config.entries.count; i++) {
auto* service = config.entries.items[i];
if (!is_service_table(service)) continue;
discovered++;
// ---- Stage 2: Login screen -> desktop (falls back to desktop, then shell) ----
if (!run_service("0:/os/login.elf", "login")) {
log_warn("Login failed, falling back to desktop");
if (!run_service("0:/os/desktop.elf", "desktop")) {
log_warn("Desktop failed, falling back to shell");
run_service("0:/os/shell.elf", "shell");
}
const char* id = service->key + montauk::slen(SERVICE_PREFIX);
char key[256];
service_key(key, sizeof(key), id, "fallback_only");
if (config.get_bool(key, false)) continue;
run_configured_service(config, service);
}
if (discovered == 0)
log_err("No services found in 0:/config/init.toml");
config.destroy();
log_warn("All services exited");
for (;;) {