From 13d58ace9f523ff8293c5296fd5d468c771b5db3 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 27 Jul 2026 12:53:33 +0200 Subject: [PATCH] conf: rename remain and manual for what they actually do Both keys prompt the question they should be answering. 'remain' decides whether a finished run or task keeps existing: without it the entry is pruned, so the work re-runs on every runlevel entry, initctl cannot see it, and its post script never fires. With it the entry stays, is not re-run, and gets a teardown when stopped or when it leaves its runlevels. That is systemd's RemainAfterExit, and 'remain' is that name with the informative half cut off. 'manual' says how a service is started but not that it is about starting at all. remain -> remain-after-exit manual -> manual-start Both keep their old spelling as an alias, which they qualify for twice over, as abbreviations of the canonical name and as the legacy spellings. While here, give sec_getbool() the alias argument its string and list counterparts already take. Signed-off-by: Joachim Wiberg --- src/conf.c | 37 ++++++++++++++++++++----------------- test/conf-format.sh | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/conf.c b/src/conf.c index 4154b0fa..947f1854 100644 --- a/src/conf.c +++ b/src/conf.c @@ -235,8 +235,10 @@ static cfg_opt_t svc_opts[] = { CFG_BOOL ("pidfile-create", cfg_false, CFGF_NODEFAULT), CFG_STR ("notify", NULL, CFGF_NODEFAULT), CFG_STR ("type", NULL, CFGF_NODEFAULT), - CFG_BOOL ("manual", cfg_false, CFGF_NODEFAULT), - CFG_BOOL ("remain", cfg_false, CFGF_NODEFAULT), + CFG_BOOL ("manual-start", cfg_false, CFGF_NODEFAULT), + CFG_BOOL ("manual", cfg_false, CFGF_NODEFAULT), /* alias */ + CFG_BOOL ("remain-after-exit", cfg_false, CFGF_NODEFAULT), + CFG_BOOL ("remain", cfg_false, CFGF_NODEFAULT), /* alias */ CFG_BOOL ("respawn", cfg_false, CFGF_NODEFAULT), CFG_STR ("restart", NULL, CFGF_NODEFAULT), CFG_INT ("restart-max", 0, CFGF_NODEFAULT), @@ -1038,9 +1040,10 @@ static char *sec_getlist(cfg_t *sec, const char *key, const char *alias, char *b return buf; } -static int sec_getbool(cfg_t *sec, const char *key) +static int sec_getbool(cfg_t *sec, const char *key, const char *alias) { - if (!cfg_size(sec, key)) + key = sec_key(sec, key, alias); + if (!key) return 0; return cfg_getbool(sec, key) == cfg_true; @@ -1236,7 +1239,7 @@ static void svc_translate(cfg_t *sec, int type, struct rlimit rlimit[], char *fi */ bang = 0; if (type == SVC_TYPE_RUN || type == SVC_TYPE_TASK) { - if (cfg_size(sec, "required") && !sec_getbool(sec, "required")) + if (cfg_size(sec, "required") && !sec_getbool(sec, "required", NULL)) bang = 1; /* do not hold up bootstrap */ if (cfg_size(sec, "reload-signal")) logit(LOG_WARNING, "%s: %s: reload-signal does not apply" @@ -1305,7 +1308,7 @@ static void svc_translate(cfg_t *sec, int type, struct rlimit rlimit[], char *fi * pidfile plugin discovers on its own. */ str = sec_getstr(sec, "pidfile", NULL); - own = sec_getbool(sec, "pidfile-create"); + own = sec_getbool(sec, "pidfile-create", NULL); if (str && strcmp(str, "true") && strcmp(str, "false")) addopt(line, sizeof(line), own ? "pid:" : "pid:!", str); @@ -1323,11 +1326,11 @@ static void svc_translate(cfg_t *sec, int type, struct rlimit rlimit[], char *fi file, str); } - if (sec_getbool(sec, "manual")) + if (sec_getbool(sec, "manual-start", "manual")) addtok(line, sizeof(line), "manual:yes"); - if (sec_getbool(sec, "remain")) + if (sec_getbool(sec, "remain-after-exit", "remain")) addtok(line, sizeof(line), "remain:yes"); - if (sec_getbool(sec, "respawn")) + if (sec_getbool(sec, "respawn", NULL)) addtok(line, sizeof(line), "respawn"); if (nowarn) addtok(line, sizeof(line), "nowarn"); @@ -1445,9 +1448,9 @@ static void tty_translate(cfg_t *sec, struct rlimit rlimit[], char *file) } else if (cmd) { addtok(line, sizeof(line), "%s", cmd); } else { - if (sec_getbool(sec, "notty")) + if (sec_getbool(sec, "notty", NULL)) addtok(line, sizeof(line), "notty"); - if (sec_getbool(sec, "rescue")) + if (sec_getbool(sec, "rescue", NULL)) addtok(line, sizeof(line), "rescue"); if (!line[0]) { @@ -1457,11 +1460,11 @@ static void tty_translate(cfg_t *sec, struct rlimit rlimit[], char *file) } } - if (sec_getbool(sec, "noclear")) + if (sec_getbool(sec, "noclear", NULL)) addtok(line, sizeof(line), "noclear"); - if (sec_getbool(sec, "nowait")) + if (sec_getbool(sec, "nowait", NULL)) addtok(line, sizeof(line), "nowait"); - if (sec_getbool(sec, "nologin")) + if (sec_getbool(sec, "nologin", NULL)) addtok(line, sizeof(line), "nologin"); if (dev && (str = sec_getstr(sec, "term", NULL))) @@ -1539,8 +1542,8 @@ static void conf_parse_statics(cfg_t *cfg) if (runparts) free(runparts); runparts = strdup(str); - runparts_progress = sec_getbool(cfg, "runparts-progress"); - runparts_sysv = sec_getbool(cfg, "runparts-sysv"); + runparts_progress = sec_getbool(cfg, "runparts-progress", NULL); + runparts_sysv = sec_getbool(cfg, "runparts-sysv", NULL); } if (cfg_size(cfg, "runlevel")) { @@ -1597,7 +1600,7 @@ static void conf_parse_statics(cfg_t *cfg) } if (cfg_size(cfg, "reboot-watchdog")) - wdtreboot = sec_getbool(cfg, "reboot-watchdog"); + wdtreboot = sec_getbool(cfg, "reboot-watchdog", NULL); if (cfg_size(cfg, "service-interval")) { long val = cfg_getint(cfg, "service-interval"); diff --git a/test/conf-format.sh b/test/conf-format.sh index 6d72e6fc..76bbd1b1 100755 --- a/test/conf-format.sh +++ b/test/conf-format.sh @@ -218,3 +218,42 @@ run "echo '}' >> $FINIT_CONF" run "initctl reload" retry 'assert_desc "Power failure" pwrfail' + +# remain-after-exit keeps a completed task in the service list, so it +# is still visible and can be stopped. The alias must reach the same +# legacy token. +for key in remain-after-exit remain; do + say "$key keeps a completed task visible" + run "echo 'task setup {' > $FINIT_CONF" + run "echo ' description = \"Setup task\"' >> $FINIT_CONF" + run "echo ' runlevel = \"2345\"' >> $FINIT_CONF" + run "echo \" $key = true\" >> $FINIT_CONF" + run "echo ' command = \"/bin/true\"' >> $FINIT_CONF" + run "echo '}' >> $FINIT_CONF" + run "initctl reload" + + retry 'assert_desc "Setup task" setup' +done + +# manual-start registers the service but does not start it, so both +# spellings must reach the legacy manual:yes token. +for key in manual-start manual; do + say "$key leaves the service stopped until asked" + run "echo 'service service.sh {' > $FINIT_CONF" + run "echo ' description = \"Manual service\"' >> $FINIT_CONF" + run "echo \" $key = true\" >> $FINIT_CONF" + run "echo ' command = \"service.sh\"' >> $FINIT_CONF" + run "echo '}' >> $FINIT_CONF" + run "initctl reload" + + retry 'assert_desc "Manual service" service.sh' + assert_num_children 0 service.sh + + run "initctl start service.sh" + retry 'assert_num_children 1 service.sh' + + # a started service survives the next reload, so clear it before + # the alias pass repeats the "stopped until asked" check + run "initctl stop service.sh" + retry 'assert_num_children 0 service.sh' +done