From 9360c8e9b90b2e7bdc40a5d51d8205c9eaeaf1b7 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sat, 1 Aug 2026 11:02:35 +0200 Subject: [PATCH] conf: generate runtime .conf files in the block format Finit's own generated services -- watchdogd, keventd, runparts, and the dbus plugin -- still went through conf_save_service() as legacy one-liners, so `initctl show keventd` taught the old format on a system otherwise converted to the new one. conf_save_service() now takes the block title and a printf-style body and writes the file itself: # Generated by finit:conf_save_service() service keventd { description = "Finit kernel event daemon" runlevel = "S12345789" notify = "none" cgroup init {} command = "/libexec/finit/keventd" } vfprintf() into the file also removes the fixed-size staging buffers in the callers, where a long dbus pidfile path could truncate inside a quoted string and take the whole generated file with it. Semantics preserved: watch-only pid:! maps to pidfile without pidfile-create, the watchdog keeps its watchdog:finit identity, and log:console becomes log { file = "/dev/console" }. Signed-off-by: Joachim Wiberg --- plugins/dbus.c | 20 ++++++++++++-------- src/conf.c | 43 +++++++++++++++++++++++++++++++------------ src/conf.h | 3 ++- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/plugins/dbus.c b/plugins/dbus.c index a8a155a1..961f840c 100644 --- a/plugins/dbus.c +++ b/plugins/dbus.c @@ -100,7 +100,7 @@ static void setup(void *arg) { char *group = DBUS_DAEMONGROUP; char *user = DBUS_DAEMONUSER; - char line[256]; + char pid[300]; char *pidfn; mode_t prev; char *cmd; @@ -151,15 +151,19 @@ static void setup(void *arg) * Register service with Finit * Note: dbus drops privs after starting up. */ + pid[0] = 0; if (pidfn) { - snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus pid:!%s %s %s -- %s", - pidfn, cmd, DBUS_ARGS, DBUS_DESC); + snprintf(pid, sizeof(pid), "\tpidfile = \"%s\"\n", pidfn); free(pidfn); - } else - snprintf(line, sizeof(line), "[S123456789] cgroup.system notify:none name:dbus %s %s -- %s", - cmd, DBUS_ARGS, DBUS_DESC); - - conf_save_service(SVC_TYPE_SERVICE, line, "dbus.conf"); + } + conf_save_service(SVC_TYPE_SERVICE, "dbus", "dbus.conf", + "\tdescription = \"" DBUS_DESC "\"\n" + "\trunlevel = \"S123456789\"\n" + "\tnotify = \"none\"\n" + "\tcgroup system {}\n" + "%s" + "\tcommand = \"%s " DBUS_ARGS "\"\n", + pid, cmd); free(cmd); } diff --git a/src/conf.c b/src/conf.c index 8ee3d159..7e2a9386 100644 --- a/src/conf.c +++ b/src/conf.c @@ -43,6 +43,7 @@ #include "config.h" /* Generated by configure script */ +#include #include #include #include @@ -664,11 +665,14 @@ done: } /* - * Called by plugins and similar that dynamically generate system services + * Called by plugins and similar that dynamically generate system + * services. @body holds the block contents, one indented line per + * setting. */ -void conf_save_service(int type, char *cfg, char *file) +void conf_save_service(int type, const char *name, char *file, const char *fmt, ...) { char fn[256]; + va_list ap; svc_t foo; FILE *fp; @@ -684,7 +688,11 @@ void conf_save_service(int type, char *cfg, char *file) foo.type = type; fprintf(fp, "# Generated by finit:%s()\n", __func__); - fprintf(fp, "%s %s\n", svc_typestr(&foo), cfg); + fprintf(fp, "%s %s {\n", svc_typestr(&foo), name); + va_start(ap, fmt); + vfprintf(fp, fmt, ap); + va_end(ap); + fprintf(fp, "}\n"); fclose(fp); } @@ -2520,16 +2528,24 @@ int conf_init(uev_ctx_t *ctx) */ #ifdef WDT_DEVNODE if (whichp(FINIT_EXECPATH_ "/watchdogd") && fexist(WDT_DEVNODE)) { - conf_save_service(SVC_TYPE_SERVICE, "[S0123456789] cgroup.init notify:none name:watchdog :finit " - FINIT_EXECPATH_ "/watchdogd -- Finit watchdog daemon", "watchdogd.conf"); + conf_save_service(SVC_TYPE_SERVICE, "watchdog:finit", "watchdogd.conf", + "\tdescription = \"Finit watchdog daemon\"\n" + "\trunlevel = \"S0123456789\"\n" + "\tnotify = \"none\"\n" + "\tcgroup init {}\n" + "\tcommand = \"" FINIT_EXECPATH_ "/watchdogd\"\n"); } #endif /* * Start kernel event daemon as soon as possible, if enabled */ if (whichp(FINIT_EXECPATH_ "/keventd")) - conf_save_service(SVC_TYPE_SERVICE, "[S12345789] cgroup.init notify:none " - FINIT_EXECPATH_ "/keventd -- Finit kernel event daemon", "keventd.conf"); + conf_save_service(SVC_TYPE_SERVICE, "keventd", "keventd.conf", + "\tdescription = \"Finit kernel event daemon\"\n" + "\trunlevel = \"S12345789\"\n" + "\tnotify = \"none\"\n" + "\tcgroup init {}\n" + "\tcommand = \"" FINIT_EXECPATH_ "/keventd\"\n"); dbg("Allow plugins to register early runlevel 1 run/task/services ..."); plugin_run_hooks(HOOK_SVC_PLUGIN); @@ -2552,7 +2568,6 @@ int conf_init(uev_ctx_t *ctx) * Background startup scripts in the runparts directory, if any. */ if (runparts && fisdir(runparts) && !rescue) { - char conf[sizeof(_PATH_RUNPARTS) + strlen(runparts) + 100]; char args[10] = { 0 }; if (debug) @@ -2562,10 +2577,14 @@ int conf_init(uev_ctx_t *ctx) if (runparts_sysv) strlcat(args, "-s ", sizeof(args)); - snprintf(conf, sizeof(conf), "[S] notify:none log:console %s %s %s" - " -- Calling runparts %s in the background", - _PATH_RUNPARTS, args, runparts, runparts); - conf_save_service(SVC_TYPE_TASK, conf, "runparts.conf"); + conf_save_service(SVC_TYPE_TASK, "runparts", "runparts.conf", + "\tdescription = \"Calling runparts %s in the background\"\n" + "\trunlevel = \"S\"\n" + "\tconditions = { \"int/bootstrap\" }\n" + "\tnotify = \"none\"\n" + "\tlog { file = \"/dev/console\" }\n" + "\tcommand = \"%s %s%s\"\n", + runparts, _PATH_RUNPARTS, args, runparts); } return 0; diff --git a/src/conf.h b/src/conf.h index aa565fca..01479df5 100644 --- a/src/conf.h +++ b/src/conf.h @@ -71,7 +71,8 @@ int conf_monitor (void); void conf_saverc (void); void conf_save_exec_order (svc_t *svc, char *cmdline, int result); -void conf_save_service (int type, char *cfg, char *file); +void conf_save_service (int type, const char *name, char *file, const char *fmt, ...) + __attribute__ ((format (printf, 4, 5))); void conf_parse_cmdline (int argc, char *argv[]); void conf_reset_env (void);