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[] = {
51 extern options_t options ;
53 int is_cfgdirective_valid(const char *s) {
55 for (t = 0; config_directives[t] != NULL; t++)
56 if (strcmp(s, config_directives[t]) == 0) return 1;
61 config = stringmap_new();
62 return config != NULL;
66 * Read a configuration file consisting of key: value tuples, returning a
67 * stringmap of the results. Prints errors to stderr, rather than using
68 * syslog, since this file is called at program startup. Returns 1 on success
70 int read_config_file(const char *f, int whinge) {
76 line = xmalloc(MAX_CONFIG_LINE);
80 if(whinge) fprintf(stderr, "%s: %s\n", f, strerror(errno));
84 while (fgets(line, MAX_CONFIG_LINE, fp)) {
85 char *key, *value, *r;
87 for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
89 /* Get continuation lines. Ugly. */
90 while (*(line + strlen(line) - 1) == '\\') {
91 if (!fgets(line + strlen(line) - 1, MAX_CONFIG_LINE - strlen(line), fp))
93 for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
97 key = strpbrk(line, "#\n");
100 /* foo : bar baz quux
102 key = line + strspn(line, " \t");
103 value = strchr(line, ':');
106 /* foo : bar baz quux
110 r = key + strcspn(key, " \t:");
115 /* foo\0: bar baz quux
117 value += strspn(value, " \t");
118 r = value + strlen(value) - 1;
119 while (strchr(" \t", *r) && r > value) --r;
122 /* (Removed check for zero length value.) */
124 /* Check that this is a valid key. */
125 if (!is_cfgdirective_valid(key))
126 fprintf(stderr, "%s:%d: warning: unknown directive \"%s\"\n", f, i, key);
127 else if ((I = stringmap_insert(config, key, item_ptr(xstrdup(value)))))
128 /* Don't warn of repeated directives, because they
129 * may have been specified via the command line
130 * Previous option takes precedence.
132 fprintf(stderr, "%s:%d: warning: repeated directive \"%s\"\n", f, i, key);
136 memset(line, 0, MAX_CONFIG_LINE); /* security paranoia */
145 if (line) xfree(line);
150 int config_get_int(const char *directive, int *value) {
154 if (!value) return -1;
156 S = stringmap_find(config, directive);
162 *value = strtol(s, &t, 10);
165 return errno == ERANGE ? -1 : 1;
169 * Get an integer value from a config string. Returns 1 on success, -1 on
170 * failure, or 0 if no value was found. */
171 int config_get_float(const char *directive, float *value) {
175 if (!value) return -1;
177 if (!(S = stringmap_find(config, directive)))
183 *value = strtod(s, &t);
186 return errno == ERANGE ? -1 : 1;
189 /* config_get_string;
190 * Get a string value from the config file. Returns NULL if it is not
192 char *config_get_string(const char *directive) {
195 S = stringmap_find(config, directive);
196 if (S) return (char*)S->d.v;
201 * Get a boolean value from the config file. Returns false if not present. */
202 int config_get_bool(const char *directive) {
205 s = config_get_string(directive);
206 if (s && (strcmp(s, "yes") == 0 || strcmp(s, "true") == 0))
213 * Get an enumeration value from the config file. Returns false if not
214 * present or an invalid value is found. */
215 int config_get_enum(const char *directive, config_enumeration_type *enumeration, int *value) {
217 config_enumeration_type *t;
218 s = config_get_string(directive);
220 for(t = enumeration; t->name; t++) {
221 if(strcmp(s,t->name) == 0) {
226 fprintf(stderr,"Invalid enumeration value \"%s\" for directive \"%s\"\n", s, directive);
231 /* config_set_string; Sets a value in the config, possibly overriding
234 void config_set_string(const char *directive, const char* s) {
237 S = stringmap_find(config, directive);
240 S->d = item_ptr(xstrdup(s));
243 stringmap_insert(config, directive, item_ptr(xstrdup(s)));
247 int read_config(char *file, int whinge_on_error) {
248 return read_config_file(file, whinge_on_error);