Toggling session parameters currently requires editing the configuration file and reloading BIRD. Doing so programatically requires keeping up with the syntax and layout of a particular configuration. This commit introduces an alternative method for gating configuration of boolean protocol properties. In addition to the keywords on/off and yes/no, a user can instead provide a filename on which to predicate whether the flag is set. In particular, this makes toggling protocols programatically much simpler, since we can decouple state from configuration more cleanly, i.e: protocol kernel { disabled filename "/etc/disable-kernel"; } --- conf/cf-lex.l | 23 +++++++++++++++++++++++ conf/conf.h | 1 + conf/confbase.Y | 3 ++- doc/bird.sgml | 5 +++-- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 5a2a4d6..af85291 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -693,6 +693,29 @@ cf_symbol_class_name(struct symbol *sym) } } +/** + * cf_file_exists - check if expanded filename exists + * @arg: filename + * + * This function expands relative filenames and returns + * whether file is present. + */ +int +cf_file_exists(char *arg) +{ + char *patt = arg; + + if (*arg != '/') + { + int dlen = strlen(ifs->file_name); + char *dir = alloca(dlen + 1); + patt = alloca(dlen + strlen(arg) + 2); + memcpy(dir, ifs->file_name, dlen + 1); + sprintf(patt, "%s/%s", dirname(dir), arg); + } + + return access(patt, F_OK) != -1; +} /** * DOC: Parser diff --git a/conf/conf.h b/conf/conf.h index 89a2c5b..6f6a33d 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -160,6 +160,7 @@ char *cf_symbol_class_name(struct symbol *sym); static inline int cf_symbol_is_constant(struct symbol *sym) { return (sym->class & 0xff00) == SYM_CONSTANT; } +int cf_file_exists(char *arg); /* Parser */ diff --git a/conf/confbase.Y b/conf/confbase.Y index 5f487c1..7ee26f3 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -88,7 +88,7 @@ CF_DECLS %left '!' %nonassoc '.' -CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT) +CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, FILENAME) CF_GRAMMAR @@ -143,6 +143,7 @@ bool: | YES { $$ = 1; } | OFF { $$ = 0; } | NO { $$ = 0; } + | FILENAME text { $$ = cf_file_exists($2); } | /* Silence means agreement */ { $$ = 1; } ; diff --git a/doc/bird.sgml b/doc/bird.sgml index a0b45f4..03682cb 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -493,8 +493,9 @@ protocol (see sections talking about the protocols). <p>Several options use a <m/switch/ argument. It can be either <cf/on/, <cf/yes/ or a numeric expression with a non-zero value for the option to be enabled or <cf/off/, <cf/no/ or a numeric expression evaluating to zero to -disable it. An empty <m/switch/ is equivalent to <cf/on/ ("silence means -agreement"). +disable it. Alternatively you can gate the value of <m/switch/ on the presence +of a file through the <cf/filename/ "<m/name/" directive. An empty <m/switch/ +is equivalent to <cf/on/ ("silence means agreement"). <descrip> <tag>preference <m/expr/</tag> -- 2.8.1