4 * Copyright (c) 2003 DecisionSoft Ltd.
13 #include "stringmap.h"
18 #define CONFIG_TYPE_STRING 0
19 #define CONFIG_TYPE_BOOL 1
20 #define CONFIG_TYPE_INT 2
22 #define MAX_CONFIG_LINE 2048
24 char * config_directives[] = {
52 extern options_t options ;
54 int is_cfgdirective_valid(const char *s) {
56 for (t = 0; config_directives[t] != NULL; t++)
57 if (strcmp(s, config_directives[t]) == 0) return 1;
62 config = stringmap_new();
63 return config != NULL;
67 * Read a configuration file consisting of key: value tuples, returning a
68 * stringmap of the results. Prints errors to stderr, rather than using
69 * syslog, since this file is called at program startup. Returns 1 on success
71 int read_config_file(const char *f, int whinge) {
77 line = xmalloc(MAX_CONFIG_LINE);
81 if(whinge) fprintf(stderr, "%s: %s\n", f, strerror(errno));
85 while (fgets(line, MAX_CONFIG_LINE, fp)) {
86 char *key, *value, *r;
88 for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
90 /* Get continuation lines. Ugly. */
91 while (*(line + strlen(line) - 1) == '\\') {
92 if (!fgets(line + strlen(line) - 1, MAX_CONFIG_LINE - strlen(line), fp))
94 for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
98 key = strpbrk(line, "#\n");
101 /* foo : bar baz quux
103 key = line + strspn(line, " \t");
104 value = strchr(line, ':');
107 /* foo : bar baz quux
111 r = key + strcspn(key, " \t:");
116 /* foo\0: bar baz quux
118 value += strspn(value, " \t");
119 r = value + strlen(value) - 1;
120 while (strchr(" \t", *r) && r > value) --r;
123 /* (Removed check for zero length value.) */
125 /* Check that this is a valid key. */
126 if (!is_cfgdirective_valid(key))
127 fprintf(stderr, "%s:%d: warning: unknown directive \"%s\"\n", f, i, key);
128 else if ((I = stringmap_insert(config, key, item_ptr(xstrdup(value)))))
129 /* Don't warn of repeated directives, because they
130 * may have been specified via the command line
131 * Previous option takes precedence.
133 fprintf(stderr, "%s:%d: warning: repeated directive \"%s\"\n", f, i, key);
137 memset(line, 0, MAX_CONFIG_LINE); /* security paranoia */
146 if (line) xfree(line);
151 int config_get_int(const char *directive, int *value) {
155 if (!value) return -1;
157 S = stringmap_find(config, directive);
163 *value = strtol(s, &t, 10);
166 return errno == ERANGE ? -1 : 1;
170 * Get an integer value from a config string. Returns 1 on success, -1 on
171 * failure, or 0 if no value was found. */
172 int config_get_float(const char *directive, float *value) {
176 if (!value) return -1;
178 if (!(S = stringmap_find(config, directive)))
184 *value = strtod(s, &t);
187 return errno == ERANGE ? -1 : 1;
190 /* config_get_string;
191 * Get a string value from the config file. Returns NULL if it is not
193 char *config_get_string(const char *directive) {
196 S = stringmap_find(config, directive);
197 if (S) return (char*)S->d.v;
202 * Get a boolean value from the config file. Returns false if not present. */
203 int config_get_bool(const char *directive) {
206 s = config_get_string(directive);
207 if (s && (strcmp(s, "yes") == 0 || strcmp(s, "true") == 0))
214 * Get an enumeration value from the config file. Returns false if not
215 * present or an invalid value is found. */
216 int config_get_enum(const char *directive, config_enumeration_type *enumeration, int *value) {
218 config_enumeration_type *t;
219 s = config_get_string(directive);
221 for(t = enumeration; t->name; t++) {
222 if(strcmp(s,t->name) == 0) {
227 fprintf(stderr,"Invalid enumeration value \"%s\" for directive \"%s\"\n", s, directive);
232 /* config_set_string; Sets a value in the config, possibly overriding
235 void config_set_string(const char *directive, const char* s) {
238 S = stringmap_find(config, directive);
241 S->d = item_ptr(xstrdup(s));
244 stringmap_insert(config, directive, item_ptr(xstrdup(s)));
248 int read_config(char *file, int whinge_on_error) {
249 return read_config_file(file, whinge_on_error);