mirror of
https://github.com/troglobit/finit.git
synced 2026-10-13 10:14:47 +00:00
conf: support list of candidate commands for services
A daemon known under more than one name had to be declared once per
name, each stanza carrying nowarn so the ones that were not installed
were skipped quietly. That leaned on the line-based format having no
titles. With a title as the service identity the repetition is no
longer available, so the candidates move inside the block:
command = { "/lib/systemd/systemd-udevd", "-udevd" }
Finit starts the first one whose binary resolves. A candidate that is
not installed is expected here, so nothing is logged for the ones that
lose, and only the winner is looked up again by service_register().
The leading '-' keeps its meaning and is read from the candidate that
wins, or from the last one when none resolve.
libconfuse accepts a bare string for a list option, so the common
`command = "prog args"` is unchanged, and whichp() already skips any
arguments to the command, so the candidate goes to it as written.
tty blocks take the same list. Their command is the getty to run, and
it has the same reason to name alternatives. Both block types now
share svc_command(), which also puts the leading '-' rule back in one
place: tty_translate() had its own copy. A tty needs no command at
all, it may name a device or notty instead, so svc_command() returns
NULL for an empty section and each caller decides whether that is an
error.
system/10-hotplug.conf.in returns to one udevd block, which is what it
meant all along.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
1 parent
516ee41494
commit
cfae4a0e10
4 files changed
+166
-31
No files matched your search
+51
-12
@@ -232,7 +232,12 @@ static cfg_opt_t log_opts[] = {
|
||||
static cfg_opt_t svc_opts[] = {
|
||||
CFG_STR ("description", NULL, CFGF_NODEFAULT),
|
||||
CFG_STR ("desc", NULL, CFGF_NODEFAULT), /* alias */
|
||||
CFG_STR ("command", NULL, CFGF_NODEFAULT),
|
||||
/*
|
||||
* A list, but libconfuse takes a bare string for one as well, so
|
||||
* the common `command = "prog args"` is unaffected. See
|
||||
* svc_command().
|
||||
*/
|
||||
CFG_STR_LIST("command", NULL, CFGF_NODEFAULT),
|
||||
CFG_STR ("runlevel", NULL, CFGF_NODEFAULT),
|
||||
CFG_STR_LIST("conditions", NULL, CFGF_NODEFAULT),
|
||||
CFG_STR_LIST("cond", NULL, CFGF_NODEFAULT), /* alias */
|
||||
@@ -307,7 +312,7 @@ static cfg_opt_t tty_opts[] = {
|
||||
CFG_BOOL ("noclear", cfg_false, CFGF_NODEFAULT),
|
||||
CFG_BOOL ("nowait", cfg_false, CFGF_NODEFAULT),
|
||||
CFG_BOOL ("nologin", cfg_false, CFGF_NODEFAULT),
|
||||
CFG_STR ("command", NULL, CFGF_NODEFAULT),
|
||||
CFG_STR_LIST("command", NULL, CFGF_NODEFAULT), /* candidates, see svc_command() */
|
||||
CFG_BOOL ("notty", cfg_false, CFGF_NODEFAULT),
|
||||
CFG_BOOL ("rescue", cfg_false, CFGF_NODEFAULT),
|
||||
CFG_END()
|
||||
@@ -1105,6 +1110,46 @@ static int sec_getbool(cfg_t *sec, const char *key, const char *alias)
|
||||
return cfg_getbool(sec, key) == cfg_true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick the command for a service. Several may be listed, in which
|
||||
* case they are candidates for the same service and the first one
|
||||
* whose binary resolves wins:
|
||||
*
|
||||
* command = { "/lib/systemd/systemd-udevd", "udevd" }
|
||||
*
|
||||
* The line-based format could only spell this as one stanza per
|
||||
* candidate, relying on nowarn to skip the ones that were not
|
||||
* installed. A candidate not being there is not an error here, so
|
||||
* only the winner is looked up again by service_register().
|
||||
*
|
||||
* A leading '-' still says a missing binary is expected, cf. systemd
|
||||
* ExecStart=-.
|
||||
*
|
||||
* Returns NULL when the section has no command at all, which is an
|
||||
* error for a service but not for a tty, so the caller decides.
|
||||
*/
|
||||
static const char *svc_command(cfg_t *sec, int *nowarn)
|
||||
{
|
||||
const char *cand = NULL;
|
||||
unsigned int i, num;
|
||||
|
||||
num = cfg_size(sec, "command");
|
||||
if (!num)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
cand = cfg_getnstr(sec, "command", i);
|
||||
*nowarn = cand[0] == '-';
|
||||
|
||||
/* which() skips any arguments to the command */
|
||||
if (whichp(&cand[*nowarn]))
|
||||
break;
|
||||
}
|
||||
|
||||
/* the winner, or the last candidate when none of them resolve */
|
||||
return &cand[*nowarn];
|
||||
}
|
||||
|
||||
/*
|
||||
* Append token to the one-liner being built, space separated.
|
||||
*/
|
||||
@@ -1399,18 +1444,13 @@ static void svc_translate(cfg_t *sec, int type, struct rlimit rlimit[], char *fi
|
||||
svc_t *svc;
|
||||
char *id;
|
||||
|
||||
cmd = sec_getstr(sec, "command", NULL);
|
||||
cmd = svc_command(sec, &nowarn);
|
||||
if (!cmd) {
|
||||
logit(LOG_ERR, "%s: section '%s' missing command, skipping",
|
||||
file, cfg_title(sec));
|
||||
return;
|
||||
}
|
||||
|
||||
/* a leading - tolerates a missing binary, cf. systemd ExecStart=- */
|
||||
nowarn = cmd[0] == '-';
|
||||
if (nowarn)
|
||||
cmd++;
|
||||
|
||||
if ((str = sec_getstr(sec, "runlevel", NULL)))
|
||||
addtok(line, sizeof(line), "[%s]", str);
|
||||
|
||||
@@ -1614,6 +1654,7 @@ static void tty_translate(cfg_t *sec, struct rlimit rlimit[], char *file)
|
||||
{
|
||||
char line[LINE_SIZE] = "";
|
||||
const char *str, *dev, *cmd;
|
||||
int nowarn = 0;
|
||||
char buf[512];
|
||||
|
||||
if ((str = sec_getstr(sec, "runlevel", NULL)))
|
||||
@@ -1623,11 +1664,9 @@ static void tty_translate(cfg_t *sec, struct rlimit rlimit[], char *file)
|
||||
addtok(line, sizeof(line), "<%s>", buf);
|
||||
|
||||
dev = sec_getstr(sec, "device", NULL);
|
||||
cmd = sec_getstr(sec, "command", NULL);
|
||||
if (cmd && cmd[0] == '-') {
|
||||
cmd = svc_command(sec, &nowarn);
|
||||
if (nowarn)
|
||||
addtok(line, sizeof(line), "nowarn");
|
||||
cmd++;
|
||||
}
|
||||
|
||||
if (dev) {
|
||||
addtok(line, sizeof(line), "%s", dev);
|
||||
|
||||
Reference in new issue
Block a user