diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2020-02-28 10:07:54 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2020-02-28 10:07:54 +0200 |
commit | 73bfc3bdfac590266ad67c48de5e866bb5d5fa4d (patch) | |
tree | 2488c3b3b009c0c49f56a63f10df7340432588c4 /src/config.c | |
parent | 7e8ff0ed908913de7467daa28feb25164abc7ad9 (diff) | |
download | ping903-73bfc3bdfac590266ad67c48de5e866bb5d5fa4d.tar.gz ping903-73bfc3bdfac590266ad67c48de5e866bb5d5fa4d.tar.bz2 |
Implement here-document syntax in configuration file.
Here-document is supported for ip-list and trusted-ip statements.
* doc/ping903.conf.5: Document the here-document syntax.
* NEWS: Likewise.
* examples/inspect: Mention that the created output is a valid
configuration file.
* src/config.c: Support for here-document.
* src/defs.h: Mark printf-like functions as such.
* src/ping903.h (CF_HEREDOC_OPCODE): New data type.
(cf_callback_arg): Add heredoc member.
(STMT_T_HEREDOC): New statement type.
* src/remoteip.c (cf_trusted_ip_heredoc): New function.
* src/ping903.c: Fix format strings and unused variables.
* src/ping903q.c: Likewise.
* src/pinger.c: Likewise.
Diffstat (limited to 'src/config.c')
-rw-r--r-- | src/config.c | 109 |
1 files changed, 105 insertions, 4 deletions
diff --git a/src/config.c b/src/config.c index a04423f..58841c9 100644 --- a/src/config.c +++ b/src/config.c @@ -118,7 +118,7 @@ file_read_ip_list(FILE *fp, char const *fname) rc = pinger_host_add(p, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); if (rc) { - error("%s:%d: out of memory"); + error("%s:%d: out of memory", fname, ln); ret = CF_RET_FAIL; break; } @@ -143,7 +143,45 @@ cf_ip_list(int mode, union cf_callback_arg *arg, void *data) case CF_SERIALIZE: return cf_ip_list_serialize(arg, data); } + abort(); } + +static int +cf_ip_list_heredoc(int mode, union cf_callback_arg *arg, void *data) +{ + struct addrinfo hints, *res; + int rc; + + if (mode == CF_SERIALIZE) + return CF_RET_IGNORE; + + switch (arg->heredoc.op) { + case CF_HEREDOC_START: + case CF_HEREDOC_STOP: + break; + + case CF_HEREDOC_NEXT: + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_protocol = IPPROTO_TCP; + rc = getaddrinfo(arg->heredoc.val, NULL, &hints, &res); + if (rc) { + error("%s:%d: invalid IP address", + arg->heredoc.file, arg->heredoc.line); + return CF_RET_FAIL; + } + rc = pinger_host_add(arg->heredoc.val, res->ai_addr, + res->ai_addrlen); + freeaddrinfo(res); + if (rc) { + error("%s:%d: out of memory", arg->heredoc.file, + arg->heredoc.line); + return CF_RET_FAIL; + } + } + return CF_RET_OK; +} + struct cf_stmt { char const *kw; @@ -156,11 +194,13 @@ struct cf_stmt statements[] = { { "listen", STMT_T_STRING, &httpd_addr }, { "pidfile", STMT_T_STRING, &pidfile }, { "trusted-ip", STMT_T_CALLBACK, NULL, cf_trusted_ip }, + { "trusted-ip", STMT_T_HEREDOC, NULL, cf_trusted_ip_heredoc }, { "probe-interval", STMT_T_ULONG, &probe_interval }, { "ping-interval", STMT_T_ULONG, &ping_interval }, { "ping-count", STMT_T_ULONG, &ping_count }, { "tolerance", STMT_T_ULONG, &ping_tolerance }, { "ip-list", STMT_T_CALLBACK, NULL, cf_ip_list }, + { "ip-list", STMT_T_HEREDOC, NULL, cf_ip_list_heredoc }, { "data-length", STMT_T_ULONG, &data_length }, { "syslog-facility", STMT_T_CALLBACK, NULL, cf_syslog_facility }, { "access-log", STMT_T_BOOL, &httpd_access_log }, @@ -171,11 +211,13 @@ struct cf_stmt statements[] = { }; static struct cf_stmt * -find_stmt(char const *kw) +find_stmt(char const *kw, int heredoc) { struct cf_stmt *cf; for (cf = statements; cf->kw; cf++) { - if (strcmp(cf->kw, kw) == 0) + if (((heredoc && cf->type == STMT_T_HEREDOC) + || (!heredoc && cf->type != STMT_T_HEREDOC)) + && strcmp(cf->kw, kw) == 0) return cf; } return NULL; @@ -184,7 +226,7 @@ find_stmt(char const *kw) static int stmt_parse(char const *kw, char const *val, char const *file, unsigned line) { - struct cf_stmt *cf = find_stmt(kw); + struct cf_stmt *cf = find_stmt(kw, 0); union cf_callback_arg arg; if (!cf) { @@ -240,6 +282,12 @@ readconfig(char const *file) unsigned ln = 0; int skip_to_eol = 0; int ec = 0; + struct { + char *eot; + CF_CALLBACK callback; + void *data; + unsigned line; + } heredoc = { .eot = NULL }; fp = fopen(file, "r"); if (!fp) { @@ -281,6 +329,29 @@ readconfig(char const *file) ; if (*p == 0 || *p == '#') continue; + + if (heredoc.eot) { + union cf_callback_arg arg; + arg.heredoc.file = file; + arg.heredoc.line = ln; + + if (strcmp(heredoc.eot, p) == 0) { + arg.heredoc.op = CF_HEREDOC_STOP; + if (heredoc.callback(CF_PARSE, &arg, + heredoc.data)) + ec = 1; + free(heredoc.eot); + heredoc.eot = NULL; + } else { + arg.heredoc.op = CF_HEREDOC_NEXT; + arg.heredoc.val = p; + if (heredoc.callback(CF_PARSE, &arg, + heredoc.data)) + ec = 1; + } + continue; + } + kw = p; while (*p && isascii(*p) && (isalnum(*p) || *p == '_' || *p == '-')) @@ -296,12 +367,41 @@ readconfig(char const *file) continue; } + if (p[0] == '<' && p[1] == '<') { + p += 2; + struct cf_stmt *cf = find_stmt(kw, 1); + if (cf) { + union cf_callback_arg arg; + + arg.heredoc.op = CF_HEREDOC_START; + arg.heredoc.file = file; + arg.heredoc.line = ln; + + heredoc.callback = cf->callback; + heredoc.data = cf->data; + heredoc.line = ln; + heredoc.eot = estrdup(p); + if (heredoc.callback(CF_PARSE, &arg, + heredoc.data)) + ec = 1; + } else { + error("%s:%d: unknown heredoc statement", + file, ln); + ec = 1; + } + continue; + } + if (stmt_parse(kw, p, file, ln)) { ec = 1; } } fclose(fp); + if (heredoc.eot) { + error("%s:%d: heredoc not closed", file, heredoc.line); + ec = 1; + } if ((double) ping_count * ping_interval >= probe_interval) { error("configuration error: ping_count * ping_interval >= probe_interval"); ec = 1; @@ -339,6 +439,7 @@ config_to_json(void) break; case STMT_T_CALLBACK: + case STMT_T_HEREDOC: arg.output = NULL; switch (cf->callback(CF_SERIALIZE, &arg, cf->data)) { case CF_RET_OK: |