4 * Copyright (c) 2003 DecisionSoft Ltd.
12 #include "stringmap.h"
17 #define CONFIG_TYPE_STRING 0
18 #define CONFIG_TYPE_BOOL 1
19 #define CONFIG_TYPE_INT 2
21 #define MAX_CONFIG_LINE 2048
23 char * config_directives[] = {
47 extern options_t options ;
49 int is_cfgdirective_valid(const char *s) {
51 for (t = 0; config_directives[t] != NULL; t++)
52 if (strcmp(s, config_directives[t]) == 0) return 1;
57 config = stringmap_new();
58 return config != NULL;
62 * Read a configuration file consisting of key: value tuples, returning a
63 * stringmap of the results. Prints errors to stderr, rather than using
64 * syslog, since this file is called at program startup. Returns 1 on success
66 int read_config_file(const char *f, int whinge) {
72 line = xmalloc(MAX_CONFIG_LINE);
76 if(whinge) fprintf(stderr, "%s: %s\n", f, strerror(errno));
80 while (fgets(line, MAX_CONFIG_LINE, fp)) {
81 char *key, *value, *r;
83 for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
85 /* Get continuation lines. Ugly. */
86 while (*(line + strlen(line) - 1) == '\\') {
87 if (!fgets(line + strlen(line) - 1, MAX_CONFIG_LINE - strlen(line), fp))
89 for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
93 key = strpbrk(line, "#\n");
98 key = line + strspn(line, " \t");
99 value = strchr(line, ':');
102 /* foo : bar baz quux
106 r = key + strcspn(key, " \t:");
111 /* foo\0: bar baz quux
113 value += strspn(value, " \t");
114 r = value + strlen(value) - 1;
115 while (strchr(" \t", *r) && r > value) --r;
118 /* (Removed check for zero length value.) */
120 /* Check that this is a valid key. */
121 if (!is_cfgdirective_valid(key))
122 fprintf(stderr, "%s:%d: warning: unknown directive \"%s\"\n", f, i, key);
123 else if ((I = stringmap_insert(config, key, item_ptr(xstrdup(value)))))
124 /* Don't warn of repeated directives, because they
125 * may have been specified via the command line
126 * Previous option takes precedence.
128 fprintf(stderr, "%s:%d: warning: repeated directive \"%s\"\n", f, i, key);
132 memset(line, 0, MAX_CONFIG_LINE); /* security paranoia */
141 if (line) xfree(line);
146 int config_get_int(const char *directive, int *value) {
150 if (!value) return -1;
152 S = stringmap_find(config, directive);
158 *value = strtol(s, &t, 10);
161 return errno == ERANGE ? -1 : 1;
165 * Get an integer value from a config string. Returns 1 on success, -1 on
166 * failure, or 0 if no value was found. */
167 int config_get_float(const char *directive, float *value) {
172 if (!value) return -1;
174 if (!(S = stringmap_find(config, directive)))
180 *value = strtod(s, &t);
183 return errno == ERANGE ? -1 : 1;
186 /* config_get_string;
187 * Get a string value from the config file. Returns NULL if it is not
189 char *config_get_string(const char *directive) {
192 S = stringmap_find(config, directive);
193 if (S) return (char*)S->d.v;
198 * Get a boolean value from the config file. Returns false if not present. */
199 int config_get_bool(const char *directive) {
202 s = config_get_string(directive);
203 if (s && (strcmp(s, "yes") == 0 || strcmp(s, "true") == 0))
210 * Get an enumeration value from the config file. Returns false if not
211 * present or an invalid value is found. */
212 int config_get_enum(const char *directive, config_enumeration_type *enumeration, int *value) {
214 config_enumeration_type *t;
215 s = config_get_string(directive);
217 for(t = enumeration; t->name; t++) {
218 if(strcmp(s,t->name) == 0) {
223 fprintf(stderr,"Invalid enumeration value \"%s\" for directive \"%s\"\n", s, directive);
228 /* config_set_string; Sets a value in the config, possibly overriding
231 void config_set_string(const char *directive, const char* s) {
234 S = stringmap_find(config, directive);
237 S->d = item_ptr(xstrdup(s));
240 stringmap_insert(config, directive, item_ptr(xstrdup(s)));
244 int read_config(char *file, int whinge_on_error) {
247 return read_config_file(file, whinge_on_error);