Hostinfo day 1: Mainly documentation.
[virt-hostinfo.git] / hostinfod / configuration.c
1 /* virt-hostinfo
2  * Copyright (C) 2009 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #include <apr_general.h>
28
29 #include "hostinfod.h"
30
31 typedef int (*process_line_fn) (const char *key, const char *value);
32 static void process_conf_file (const char *path, int exit_if_not_exist, process_line_fn process_line);
33
34 /* Read the main configuration file.  This file is NOT reread if it
35  * changes, but the auxiliary guests.conf file IS reread (and so is
36  * the socket directory of course).
37  */
38 void
39 read_main_conf_file (void)
40 {
41   process_conf_file (conf_file, 0, NULL);
42 }
43
44 static void
45 process_conf_file (const char *path, int exit_if_not_exist,
46                    process_line_fn process_line)
47 {
48   static const char *whitespace = " \t\n\v";
49   FILE *fp;
50   char *line = NULL;
51   size_t len = 0;
52   size_t real_len, key_len;
53   ssize_t r;
54   const char *key, *value;
55
56   fp = fopen (path, "r");
57   if (!fp) {
58     if (exit_if_not_exist) {
59       perror (path);
60       exit (1);
61     }
62     return;
63   }
64
65   while ((r = getline (&line, &len, fp)) != -1) {
66     /* Remove trailing \n */
67     real_len = len;
68     if (real_len > 0 && line[real_len-1] == '\n')
69       line[--real_len] = '\0';
70
71     /* Ignore blank lines and comments. */
72     if (real_len == 0)
73       continue;
74     if (line[0] == '#' || strspn (line, whitespace) == real_len)
75       continue;
76
77     /* Split into key value. */
78     key_len = strcspn (line, whitespace);
79     line[key_len] = '\0';
80     key = line;
81     value = key_len < real_len ? &line[key_len+1] : NULL;
82     if (value) {
83       value += strspn (line, whitespace);
84       if (value[0] == '\0')
85         value = NULL;
86     }
87
88     if (process_line && process_line (key, value) == -1)
89       exit (1);
90   }
91
92   free (line);
93
94   if (ferror (fp)) {
95     fprintf (stderr, "error reading configuration file: %s\n", path);
96     exit (1);
97   }
98   if (fclose (fp) == EOF) {
99     perror (path);
100     exit (1);
101   }
102 }