Add support for runtime evaluation of if:<condition> statements

The if: statement, introduced in v4.4, allows for discarding run/task/services
that depend on other services, based on that service's name, or condition.
Discarding in this context means unloading from the configuration.

At runtime, however, it has proven quite useful to be able to conditionally
qualify a run/task/service based on a condition.  Consider this example from
the Infix operating system:

run name:startup log:prio:user.notice \
	[S] <pid/sysrepo> confd -b --load startup-config -- Loading startup-config

run name:failure log:prio:user.critical if:<usr/fail-startup> \
	[S] <pid/sysrepo> confd --load failure-config -- Loading failure-config

The two run statements reside in the same .conf file so Finit runs them in true
sequence.  If loading the file `startup-config` fails confd sets the condition
usr/fail-startup, thus allowing the next run statement to load `failure-config`.

Notice the difference between <pid/sysrepo> condition and if:<usr/fail-startup>.
The former is a condition for starting and the latter is a condition to check if
a run/task/service is qualified to even be considerered.  The best comparison is
with the [runlevel] option, it too is used to qualify.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2023-10-03 16:39:46 +02:00
parent ec5e42694d
commit afe0488bf2
3 changed files with 13 additions and 3 deletions
+1 -1
View File
@@ -1955,7 +1955,7 @@ void service_mark_unavail(void)
if (!svc->ifstmt[0])
continue;
if (!svc_ifthen(svc_ident(svc, buf, sizeof(buf)), svc->ifstmt))
if (!svc_ifthen(1, svc_ident(svc, buf, sizeof(buf)), svc->ifstmt))
svc_mark(svc);
}
}
+11 -1
View File
@@ -643,6 +643,9 @@ int svc_enabled(svc_t *svc)
if (svc_is_missing(svc))
return 0;
if (!svc_ifthen(0, NULL, svc->ifstmt))
return 0;
if (svc_is_tty(svc) && bootstrap)
return 0;
@@ -688,13 +691,14 @@ int svc_conflicts(svc_t *svc)
/**
* svc_ifthen - Check if: statement in declaration
* @is_conf: Set when called by service_mark_unavail()
* @ident: svc_t identififcation (name:id)
* @stmt: if: statement from .conf file
*
* Returns:
* %TRUE(1) yes, use this svc_t, %FALSE(0) prune
*/
int svc_ifthen(const char *ident, char *stmt)
int svc_ifthen(int is_conf, const char *ident, char *stmt)
{
int not = 0;
svc_t *svc;
@@ -707,6 +711,9 @@ int svc_ifthen(const char *ident, char *stmt)
char *ptr = ++stmt;
int i = 0;
if (is_conf)
return 1;
if (stmt[0] == '!') {
stmt++;
not++;
@@ -724,6 +731,9 @@ int svc_ifthen(const char *ident, char *stmt)
return 1;
}
if (!is_conf)
return 1;
if (stmt[0] == '!') {
stmt++;
not++;
+1 -1
View File
@@ -241,7 +241,7 @@ void svc_prune_bootstrap (void);
void svc_enable (svc_t *svc);
int svc_enabled (svc_t *svc);
int svc_conflicts (svc_t *svc);
int svc_ifthen (const char *ident, char *ifstm);
int svc_ifthen (int is_conf, const char *ident, char *stmt);
int svc_parse_jobstr (char *str, size_t len, void *user_data, int (*found)(svc_t *, void *), int (not_found)(char *, char *, void *));