From afe0488bf284478ec54ee608798f216f39cc3d36 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 3 Oct 2023 15:14:31 +0200 Subject: [PATCH] Add support for runtime evaluation of if: 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] confd -b --load startup-config -- Loading startup-config run name:failure log:prio:user.critical if: \ [S] 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 condition and if:. 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 --- src/service.c | 2 +- src/svc.c | 12 +++++++++++- src/svc.h | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/service.c b/src/service.c index cb7c7c0d..6f4afbdc 100644 --- a/src/service.c +++ b/src/service.c @@ -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); } } diff --git a/src/svc.c b/src/svc.c index 02d786b8..50b7f17a 100644 --- a/src/svc.c +++ b/src/svc.c @@ -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++; diff --git a/src/svc.h b/src/svc.h index 40611cfb..5aaaadaa 100644 --- a/src/svc.h +++ b/src/svc.h @@ -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 *));