diff --git a/doc/cmdline.md b/doc/cmdline.md index be0f6bf4..ebfff8a0 100644 --- a/doc/cmdline.md +++ b/doc/cmdline.md @@ -12,6 +12,17 @@ The `bool` setting is one of `on, off, true false, 1, 0`. * `debug`: Enable kernel debug. Debug messages are printed to the console until Finit starts up, unless `loglevel=7` (below) is used. +* `finit.cond=foo[,bar[,baz]]`: set `` condition, optionally + multiple conditions can be set using the same option, separated with a + comma. Alternatively, multiple `foo.cond=arg` can be given. Each will + result in a `` condition being set to control the rest of the + system bootstrap. + + Very useful for selecting different boot modes, e.g. manufacturing test, + firmware upgrade, or rescue mode. + + > Note: `` conditions cannot be cleared with `initctl`! + * `finit.debug[=bool]`: Enable finit debug. This is operated independently of the kernel `debug` setting. New as of Finit v4. diff --git a/doc/conditions.md b/doc/conditions.md index 416abe51..531177e2 100644 --- a/doc/conditions.md +++ b/doc/conditions.md @@ -46,11 +46,16 @@ Triggering ---------- Conditions are mainly triggered (asserted) by built-in plugins, e.g., -`netlink.so` and `pidfile.so`, see below for built-in conditions. Finit -also supports user-defined conditions, sometimes referred to as static -or one-shot conditions. They live in the `` + - `pidfile.so`: provides `` + - Cmdline `finit.cond=arg`: provides `name = strdup(arg); + TAILQ_INSERT_HEAD(&cond_boot_list, node, link); +} + +/* + * Convert all conditions read from the kernel command line (above) into + * proper finit conditions. + */ +static void cond_boot_strap(void) +{ + struct cond_boot *node, *tmp; + + TAILQ_FOREACH_SAFE(node, &cond_boot_list, link, tmp) { + TAILQ_REMOVE(&cond_boot_list, node, link); + if (node->name) { + char *ptr; + + ptr = strtok(node->name, ","); + while (ptr) { + char cond[strlen(ptr) + 6]; + + snprintf(cond, sizeof(cond), "boot/%s", ptr); + cond_set_oneshot_noupdate(cond); + + ptr = strtok(NULL, ","); + } + + free(node->name); + } + free(node); + } +} + /* * The service condition name is constructed from the 'pid/' prefix and * the unique NAME:ID tuple that identify each process in Finit. Here @@ -366,6 +427,7 @@ void cond_init(void) } cond_bump_reconf(); + cond_boot_strap(); } /** diff --git a/src/cond.h b/src/cond.h index 0a3bb54c..8dd7c168 100644 --- a/src/cond.h +++ b/src/cond.h @@ -31,6 +31,7 @@ enum cond_state cond_get (const char *name); enum cond_state cond_get_agg (const char *names); int cond_affects (const char *name, const char *names); +void cond_boot_parse (char *arg); int cond_update (const char *name); int cond_set_path (const char *path, enum cond_state new); void cond_set (const char *name); @@ -38,9 +39,9 @@ void cond_set_oneshot (const char *name); void cond_clear (const char *name); void cond_reload (void); -int cond_set_noupdate (const char *name); -int cond_set_oneshot_noupdate(const char *name); -int cond_clear_noupdate(const char *name); +int cond_set_noupdate(const char *name); +int cond_set_oneshot_noupdate(const char *name); +int cond_clear_noupdate(const char *name); void cond_reassert (const char *pat); void cond_deassert (const char *pat); diff --git a/src/conf.c b/src/conf.c index d871b54a..9ef50ab7 100644 --- a/src/conf.c +++ b/src/conf.c @@ -113,6 +113,11 @@ static void parse_finit_opts(char *opt) return; } + if (string_compare(opt, "cond")) { + cond_boot_parse(arg); + return; + } + if (string_compare(opt, "status_style")) { if (!arg) { _e("status_style option requires an argument, skipping.");