1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-12 17:14:46 +02:00

Conditional Config: add support for <, >, <= and >= in @if $SOMETHING ...

And also don't require double quotes on the right hand side.

So you now use something like: @if $MAXCONNECTIONS >= 1024
This commit is contained in:
Bram Matthys
2026-03-22 19:15:35 +01:00
parent 2346aa3977
commit 100abaa82d
3 changed files with 77 additions and 21 deletions
+3
View File
@@ -17,6 +17,9 @@ This is work in progress and may not always be a stable version.
* New `@if file-exists("filename")` to check if a file exists.
Paths are relative to the conf directory, or absolute if starting
with `/`.
* Variable comparisons now support `>`, `>=`, `<`, `<=` in addition
to `==` and `!=`. Uses natural ordering, so version strings and
numbers compare correctly. Example: `@if $MAXCONNECTIONS >= 1024`.
### Changes:
* [GeoIP](https://www.unrealircd.org/docs/GeoIP):
+2
View File
@@ -1650,6 +1650,7 @@ struct AuthConfig {
*/
typedef enum ConfigIfCondition { IF_DEFINED=1, IF_VALUE=2, IF_MODULE_LOADED=3, IF_MODULE_EXISTS=4, IF_MINIMUM_VERSION=5, IF_FILE_EXISTS=6} ConfigIfCondition;
typedef enum CompareOp { COMPARE_EQ=0, COMPARE_NE=1, COMPARE_GT=2, COMPARE_GE=3, COMPARE_LT=4, COMPARE_LE=5 } CompareOp;
struct ConditionalConfig
{
@@ -1657,6 +1658,7 @@ struct ConditionalConfig
int priority; /**< Preprocessor level. Starts with 1, then 2, 3, .. */
ConfigIfCondition condition; /**< See ConfigIfCondition, one of: IF_* */
int negative; /**< For ! conditions */
CompareOp compare_op; /**< Only for IF_VALUE */
char *name; /**< Name of the variable or module */
char *opt; /**< Only for IF_VALUE */
};
+72 -21
View File
@@ -94,6 +94,10 @@ PreprocessorItem evaluate_preprocessor_if(char *statement, const char *filename,
/* Currently we support:
* $XYZ == "something"
* $XYZ != "something"
* $XYZ > "something"
* $XYZ >= "something"
* $XYZ < "something"
* $XYZ <= "something"
* module-loaded("something")
* !module-loaded("something")
* module-exists("something")
@@ -127,9 +131,15 @@ PreprocessorItem evaluate_preprocessor_if(char *statement, const char *filename,
/* Otherwise it should be a $VARIABLE comparison */
{
char *name, *name_terminate, *name2;
CompareOp compare_op;
int op_len;
// Should be one of:
// $XYZ == "something"
// $XYZ != "something"
// $XYZ >= "something"
// $XYZ <= "something"
// $XYZ > "something"
// $XYZ < "something"
// Anything else is an error.
if (*p != '$')
{
@@ -137,10 +147,16 @@ PreprocessorItem evaluate_preprocessor_if(char *statement, const char *filename,
filename, linenumber, statement);
return PREPROCESSOR_ERROR;
}
if (negative)
{
config_error("%s:%i: @if: the '!' prefix cannot be used with variable comparisons, use != instead: %s",
filename, linenumber, statement);
return PREPROCESSOR_ERROR;
}
p++;
/* variable name starts now */
name = p;
read_until(&p, " \t=!");
read_until(&p, " \t=!<>");
if (!*p)
{
config_error("%s:%i: invalid if statement (termination error): %s",
@@ -151,40 +167,65 @@ PreprocessorItem evaluate_preprocessor_if(char *statement, const char *filename,
skip_whitespace(&p);
if (!strncmp(p, "==", 2))
{
negative = 0;
compare_op = COMPARE_EQ;
op_len = 2;
} else
if (!strncmp(p, "!=", 2))
{
negative = 1;
compare_op = COMPARE_NE;
op_len = 2;
} else
if (!strncmp(p, ">=", 2))
{
compare_op = COMPARE_GE;
op_len = 2;
} else
if (!strncmp(p, "<=", 2))
{
compare_op = COMPARE_LE;
op_len = 2;
} else
if (*p == '>')
{
compare_op = COMPARE_GT;
op_len = 1;
} else
if (*p == '<')
{
compare_op = COMPARE_LT;
op_len = 1;
} else
{
*name_terminate = '\0';
config_error("%s:%i: @if: expected == or != after '%s'",
config_error("%s:%i: @if: expected comparison operator (==, !=, >, >=, <, <=) after '%s'",
filename, linenumber, name);
return PREPROCESSOR_ERROR;
}
p += 2;
p += op_len;
*name_terminate = '\0';
skip_whitespace(&p);
if (*p != '"')
if (*p == '"')
{
config_error("%s:%i: @if: expected double quotes, missing \" perhaps?",
filename, linenumber);
return PREPROCESSOR_ERROR;
}
p++;
name2 = p;
read_until(&p, "\"");
if (!*p)
p++;
name2 = p;
read_until(&p, "\"");
if (!*p)
{
config_error("%s:%i: invalid @if statement, missing \" at end perhaps?",
filename, linenumber);
return PREPROCESSOR_ERROR;
}
*p = '\0';
} else
{
config_error("%s:%i: invalid @if statement, missing \" at end perhaps?",
filename, linenumber);
return PREPROCESSOR_ERROR;
name2 = p;
read_until(&p, " \t");
if (*p)
*p = '\0';
}
*p = '\0';
cc = safe_alloc(sizeof(ConditionalConfig));
cc->condition = IF_VALUE;
cc->negative = negative;
cc->compare_op = compare_op;
safe_strdup(cc->name, name);
safe_strdup(cc->opt, name2);
*cc_out = cc;
@@ -327,6 +368,7 @@ void preprocessor_cc_duplicate_list(ConditionalConfig *r, ConditionalConfig **ou
cc->priority = r->priority;
cc->condition = r->condition;
cc->negative = r->negative;
cc->compare_op = r->compare_op;
AddListItem(cc, *out);
}
}
@@ -400,9 +442,18 @@ int preprocessor_resolve_if(ConditionalConfig *cc, PreprocessorPhase phase)
if (cc->condition == IF_VALUE)
{
NameValuePrioList *d = find_config_define(cc->name);
if (d && !strcasecmp(d->value, cc->opt))
if (d)
{
result = 1;
int cmp = strnatcasecmp(d->value, cc->opt);
switch (cc->compare_op)
{
case COMPARE_EQ: result = (cmp == 0); break;
case COMPARE_NE: result = (cmp != 0); break;
case COMPARE_GT: result = (cmp > 0); break;
case COMPARE_GE: result = (cmp >= 0); break;
case COMPARE_LT: result = (cmp < 0); break;
case COMPARE_LE: result = (cmp <= 0); break;
}
}
} else
{