diff --git a/doc/configuration.txt b/doc/configuration.txt index 12d44c547..a6af2f267 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -746,6 +746,29 @@ file, or could be inherited by a program (See 3.7. Programs): * HAPROXY_MASTER_CLI: In master-worker mode, listeners addresses of the master CLI, separated by semicolons. +In addition, some pseudo-variables are internally resolved and may be used as +regular variables. Pseudo-variables always start with a dot ('.'), and are the +only ones where the dot is permitted. The current list of pseudo-variables is: + +* .FILE: the name of the configuration file currently being parsed. + +* .LINE: the line number of the configuration file currently being parsed, + starting at one. + +* .SECTION: the name of the section currently being parsed, or its type if the + section doesn't have a name (e.g. "global"), or an empty string before the + first section. + +These variables are resolved at the location where they are parsed. For example +if a ".LINE" variable is used in a "log-format" directive located in a defaults +section, its line number will be resolved before parsing and compiling the +"log-format" directive, so this same line number will be reused by subsequent +proxies. + +This way it is possible to emit information to help locate a rule in variables, +logs, error statuses, health checks, header values, or even to use line numbers +to name some config objects like servers for example. + See also "external-check command" for other variables. diff --git a/src/tools.c b/src/tools.c index 056c9ca77..c45358570 100644 --- a/src/tools.c +++ b/src/tools.c @@ -5300,14 +5300,14 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg */ char *var_name; char save_char; - char *value; + const char *value; in++; if (*in == '{') brace = in++; - if (!isalpha((unsigned char)*in) && *in != '_') { + if (!isalpha((unsigned char)*in) && *in != '_' && *in != '.') { /* unacceptable character in variable name */ err |= PARSE_ERR_VARNAME; if (errptr) @@ -5316,12 +5316,31 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg } var_name = in; + if (*in == '.') + in++; while (isalnum((unsigned char)*in) || *in == '_') in++; save_char = *in; *in = '\0'; - value = getenv(var_name); + if (unlikely(*var_name == '.')) { + /* internal pseudo-variables */ + if (strcmp(var_name, ".LINE") == 0) + value = ultoa(global.cfg_curr_line); + else if (strcmp(var_name, ".FILE") == 0) + value = global.cfg_curr_file; + else if (strcmp(var_name, ".SECTION") == 0) + value = global.cfg_curr_section; + else { + /* unsupported internal variable name */ + err |= PARSE_ERR_VARNAME; + if (errptr) + *errptr = var_name; + goto leave; + } + } else { + value = getenv(var_name); + } *in = save_char; /* support for '[*]' sequence to force word expansion,