X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=hostinfod%2Fconfiguration.c;h=90200f8927a09cb487aa13c8530ab45fb3ce7403;hb=dcbfcc566fa812fd3085c89a8cfed7fe34bb05e8;hp=14a2b8059873ef6d80fef6ae92a3ff81496e5351;hpb=b6184e540f0a61a014ccabc888530eb45458cfa2;p=virt-hostinfo.git diff --git a/hostinfod/configuration.c b/hostinfod/configuration.c index 14a2b80..90200f8 100644 --- a/hostinfod/configuration.c +++ b/hostinfod/configuration.c @@ -22,49 +22,108 @@ #include #include +#include #include #include +#include #include "hostinfod.h" -typedef int (*process_line_fn) (const char *key, const char *value); -static void process_conf_file (const char *path, int exit_if_not_exist, process_line_fn process_line); +typedef int (*process_line_fn) (const char *path, int lineno, + const char *key, const char *value); +typedef int (*process_section_fn) (const char *path, int lineno, + const char *section); +static void process_conf_file (const char *path, int exit_if_not_exist, + process_line_fn process_line, + process_section_fn process_section); +static int get_bool (const char *str); + +/* Read the main configuration file. */ +static int main_process_line (const char *path, int lineno, const char *key, const char *value); -/* Read the main configuration file. This file is NOT reread if it - * changes, but the auxiliary guests.conf file IS reread (and so is - * the socket directory of course). - */ void read_main_conf_file (void) { - process_conf_file (conf_file, 0, NULL); + process_conf_file (conf_file, 0, main_process_line, NULL); } +static int +main_process_line (const char *path, int lineno, + const char *key, const char *value) +{ + int bool; + + if (strcasecmp (key, "guests") == 0) { + if (!value) { + error ("%s:%d: directive is empty: %s", path, lineno, key); + return -1; + } + guests_file = apr_pstrdup (pool, value); + } else if (strcasecmp (key, "sockets") == 0) { + if (!value) { + error ("%s:%d: directive is empty: %s", path, lineno, key); + return -1; + } + socket_dir = apr_pstrdup (pool, value); + } else if (strcasecmp (key, "verbose") == 0) { + bool = get_bool (value); + if (bool == -1) { + error ("%s:%d: %s: not a valid boolean - use 1 or 0", path, lineno, key); + return -1; + } + if (!verbose_set_on_cmdline) + verbose = bool; + } else if (strcasecmp (key, "foreground") == 0) { + bool = get_bool (value); + if (bool == -1) { + error ("%s:%d: %s: not a valid boolean - use 1 or 0", path, lineno, key); + return -1; + } + if (!foreground_set_on_cmdline) + foreground = bool; + } else { + error ("%s:%d: unknown directive in configuration file: %s", + path, lineno, key); + return -1; + } + return 0; +} + +/* Configuration file parser. */ static void process_conf_file (const char *path, int exit_if_not_exist, - process_line_fn process_line) + process_line_fn process_line, + process_section_fn process_section) { static const char *whitespace = " \t\n\v"; FILE *fp; char *line = NULL; + int lineno = 0; size_t len = 0; size_t real_len, key_len; ssize_t r; const char *key, *value; + debug ("begin processing configuration file %s", path); + fp = fopen (path, "r"); if (!fp) { if (exit_if_not_exist) { - perror (path); + perrorf ("%s", path); exit (1); - } + } else + pwarningf ("%s", path); return; } while ((r = getline (&line, &len, fp)) != -1) { + lineno++; + + /*debug ("%s:%d: '%s' (len = %d)", path, lineno, line, len);*/ + /* Remove trailing \n */ - real_len = len; + real_len = strlen (line); if (real_len > 0 && line[real_len-1] == '\n') line[--real_len] = '\0'; @@ -74,29 +133,75 @@ process_conf_file (const char *path, int exit_if_not_exist, if (line[0] == '#' || strspn (line, whitespace) == real_len) continue; - /* Split into key value. */ - key_len = strcspn (line, whitespace); - line[key_len] = '\0'; - key = line; - value = key_len < real_len ? &line[key_len+1] : NULL; - if (value) { - value += strspn (line, whitespace); - if (value[0] == '\0') - value = NULL; + if (line[0] == '[') { /* Section. */ + if (line[real_len-1] == ']') + line[--real_len] = '\0'; + else { + error ("%s:%d: in section header, ']' not found (is there trailing whitespace or a comment?), near: %s", + path, lineno, line); + exit (1); + } + + debug ("configuration file: section [%s]", line); + + if (!process_section) { + error ("%s:%d: unexpected section header ([%s]) in file", + path, lineno, line); + exit (1); + } + + if (process_section (path, lineno, line) == -1) + exit (1); } + else { /* Key value */ + key_len = strcspn (line, whitespace); + line[key_len] = '\0'; + key = line; + value = key_len < real_len ? &line[key_len+1] : NULL; + if (value) { + value += strspn (line, whitespace); + if (value[0] == '\0') + value = NULL; + } - if (process_line && process_line (key, value) == -1) - exit (1); + debug ("configuration file: key '%s', value '%s'", key, value); + + if (process_line && process_line (path, lineno, key, value) == -1) + exit (1); + } } free (line); if (ferror (fp)) { - fprintf (stderr, "error reading configuration file: %s\n", path); + error ("%s: error reading configuration file", path); exit (1); } if (fclose (fp) == EOF) { - perror (path); + perrorf ("%s", path); exit (1); } + + debug ("finished processing configuration file successfully"); +} + +static int +get_bool (const char *str) +{ + if (!str) + return -1; + + if (strcasecmp (str, "on") == 0) + return 1; + if (strcasecmp (str, "off") == 0) + return 0; + + switch (str[0]) { + case '1': case 'y': case 'Y': case 't': case 'T': case 'e': case 'E': + return 1; + case '0': case 'n': case 'N': case 'f': case 'F': case 'd': case 'D': + return 0; + } + + return -1; }