From: Willy Tarreau Date: Thu, 6 May 2021 14:34:23 +0000 (+0200) Subject: MINOR: config: add predicate "feature" to detect certain built-in features X-Git-Tag: v2.4-dev19~108 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=58ca706e164f1bc4973c7a96240ccae2647177fa;p=thirdparty%2Fhaproxy.git MINOR: config: add predicate "feature" to detect certain built-in features The "feature(name)" predicate will return true if corresponds to a name listed after a '+' in the features list, that is it was enabled at build time with USE_=1. Typical use cases will include OPENSSL, LUA and LINUX_SPLICE. But maybe it will also be convenient to use with optional addons such as PROMEX and the device detection modules to help keeping the same configs across various deployments. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 4242e014e9..5f60507fd7 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -814,6 +814,10 @@ The list of currently supported predicates is the following: - defined() : returns true if an environment variable exists, regardless of its contents + - feature() : returns true if feature is listed as present + in the features list reported by "haproxy -vv" + (which means a appears after a '+') + - streq(,) : returns true only if the two strings are equal - strneq(,) : returns true only if the two strings differ @@ -830,7 +834,9 @@ Example: .endif .if streq("$WITH_SSL",yes) + .if feature(OPENSSL) bind :443 ssl crt ... + .endif .endif Three other directives are provided to report some status: diff --git a/src/cfgparse.c b/src/cfgparse.c index 9daac06c2f..15e4ad8644 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -137,6 +137,7 @@ enum nested_cond_state { enum cond_predicate { CFG_PRED_NONE, // none CFG_PRED_DEFINED, // "defined" + CFG_PRED_FEATURE, // "feature" CFG_PRED_STREQ, // "streq" CFG_PRED_STRNEQ, // "strneq" }; @@ -150,6 +151,7 @@ struct cond_pred_kw { /* supported condition predicates */ const struct cond_pred_kw cond_predicates[] = { { "defined", CFG_PRED_DEFINED, ARG1(1, STR) }, + { "feature", CFG_PRED_FEATURE, ARG1(1, STR) }, { "streq", CFG_PRED_STREQ, ARG2(2, STR, STR) }, { "strneq", CFG_PRED_STRNEQ, ARG2(2, STR, STR) }, { NULL, CFG_PRED_NONE, 0 } @@ -1722,6 +1724,27 @@ static int cfg_eval_condition(char **args, char **err, const char **errptr) ret = getenv(argp[0].data.str.area) != NULL; goto done; + case CFG_PRED_FEATURE: { // checks if the arg matches an enabled feature + const char *p; + + for (p = build_features; (p = strstr(p, argp[0].data.str.area)); p++) { + if ((p[argp[0].data.str.data] == ' ' || p[argp[0].data.str.data] == 0) && + p > build_features) { + if (*(p-1) == '+') { // "+OPENSSL" + ret = 1; + goto done; + } + else if (*(p-1) == '-') { // "-OPENSSL" + ret = 0; + goto done; + } + /* it was a sub-word, let's restart from next place */ + } + } + /* not found */ + ret = 0; + goto done; + } case CFG_PRED_STREQ: // checks if the two arg are equal ret = strcmp(argp[0].data.str.area, argp[1].data.str.area) == 0; goto done;