]> gitweb.fperrin.net Git - iftop.git/blob - cfgfile.c
Import iftop-1.0pre4
[iftop.git] / cfgfile.c
1 /*
2  * cfgfile.c:
3  *
4  * Copyright (c) 2003 DecisionSoft Ltd.
5  *
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <stdlib.h>
12
13 #include "stringmap.h"
14 #include "iftop.h"
15 #include "options.h"
16 #include "cfgfile.h"
17
18 #define CONFIG_TYPE_STRING 0
19 #define CONFIG_TYPE_BOOL   1
20 #define CONFIG_TYPE_INT    2
21
22 #define MAX_CONFIG_LINE     2048
23
24 char * config_directives[] = {
25         "interface", 
26         "dns-resolution",
27         "port-resolution",
28         "filter-code",
29         "show-bars", 
30         "promiscuous",
31         "hide-source",
32         "hide-destination",
33         "use-bytes", 
34         "sort", 
35         "line-display", 
36         "show-totals", 
37         "log-scale", 
38         "max-bandwidth",
39         "net-filter", 
40         "net-filter6", 
41         "link-local",
42         "port-display", 
43         "timed-output",
44         "no-curses",
45         "num-lines",
46         NULL
47 };
48
49 stringmap config;
50
51 extern options_t options ;
52
53 int is_cfgdirective_valid(const char *s) {
54     int t;
55     for (t = 0; config_directives[t] != NULL; t++)
56        if (strcmp(s, config_directives[t]) == 0) return 1;
57     return 0;
58 }
59
60 int config_init() {
61     config = stringmap_new();
62     return config != NULL;
63 }
64
65 /* read_config_file:
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
69  * or 0 on failure. */
70 int read_config_file(const char *f, int whinge) {
71     int ret = 0;
72     FILE *fp;
73     char *line;
74     int i = 1;
75
76     line = xmalloc(MAX_CONFIG_LINE);
77
78     fp = fopen(f, "rt");
79     if (!fp) {
80         if(whinge) fprintf(stderr, "%s: %s\n", f, strerror(errno)); 
81         goto fail;
82     }
83
84     while (fgets(line, MAX_CONFIG_LINE, fp)) {
85         char *key, *value, *r;
86
87         for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
88
89         /* Get continuation lines. Ugly. */
90         while (*(line + strlen(line) - 1) == '\\') {
91             if (!fgets(line + strlen(line) - 1, MAX_CONFIG_LINE - strlen(line), fp))
92                 break;
93             for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
94         }
95
96         /* Strip comment. */
97         key = strpbrk(line, "#\n");
98         if (key) *key = 0;
99
100         /*    foo  : bar baz quux
101          * key^    ^value          */
102         key = line + strspn(line, " \t");
103         value = strchr(line, ':');
104
105         if (value) {
106             /*    foo  : bar baz quux
107              * key^  ^r ^value         */
108             ++value;
109
110             r = key + strcspn(key, " \t:");
111             if (r != key) {
112                 item *I;
113                 *r = 0;
114
115                 /*    foo\0: bar baz quux
116                  * key^      ^value      ^r */
117                 value += strspn(value, " \t");
118                 r = value + strlen(value) - 1;
119                 while (strchr(" \t", *r) && r > value) --r;
120                 *(r + 1) = 0;
121
122                 /* (Removed check for zero length value.) */
123
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.
131                      */
132                     fprintf(stderr, "%s:%d: warning: repeated directive \"%s\"\n", f, i, key);
133             }
134         }
135
136         memset(line, 0, MAX_CONFIG_LINE); /* security paranoia */
137
138         ++i;
139     }
140
141     ret = 1;
142
143 fail:
144     if (fp) fclose(fp);
145     if (line) xfree(line);
146
147     return ret;
148 }
149
150 int config_get_int(const char *directive, int *value) {
151     stringmap S;
152     char *s, *t;
153
154     if (!value) return -1;
155
156     S = stringmap_find(config, directive);
157     if (!S) return 0;
158
159     s = (char*)S->d.v;
160     if (!*s) return -1;
161     errno = 0;
162     *value = strtol(s, &t, 10);
163     if (*t) return -1;
164
165     return errno == ERANGE ? -1 : 1;
166 }
167
168 /* config_get_float:
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) {
172     stringmap S;
173     char *s, *t;
174
175     if (!value) return -1;
176
177     if (!(S = stringmap_find(config, directive)))
178         return 0;
179
180     s = (char*)S->d.v;
181     if (!*s) return -1;
182     errno = 0;
183     *value = strtod(s, &t);
184     if (*t) return -1;
185
186     return errno == ERANGE ? -1 : 1;
187 }
188
189 /* config_get_string;
190  * Get a string value from the config file. Returns NULL if it is not
191  * present. */
192 char *config_get_string(const char *directive) {
193     stringmap S;
194
195     S = stringmap_find(config, directive);
196     if (S) return (char*)S->d.v;
197     else return NULL;
198 }
199
200 /* config_get_bool:
201  * Get a boolean value from the config file. Returns false if not present. */
202 int config_get_bool(const char *directive) {
203     char *s;
204
205     s = config_get_string(directive);
206     if (s && (strcmp(s, "yes") == 0 || strcmp(s, "true") == 0))
207         return 1;
208     else
209         return 0;
210 }
211
212 /* config_get_enum:
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) {
216     char *s;
217     config_enumeration_type *t;
218     s = config_get_string(directive);
219     if(s) {
220         for(t = enumeration; t->name; t++) {
221             if(strcmp(s,t->name) == 0) {
222                 *value = t->value;
223                 return 1;
224             }
225         }
226         fprintf(stderr,"Invalid enumeration value \"%s\" for directive \"%s\"\n", s, directive);
227     }
228     return 0;
229 }
230
231 /* config_set_string; Sets a value in the config, possibly overriding
232  * an existing value
233  */
234 void config_set_string(const char *directive, const char* s) {
235     stringmap S;
236
237     S = stringmap_find(config, directive);
238     if (S) {
239       xfree(S->d.v);
240       S->d = item_ptr(xstrdup(s));
241     }
242     else {
243       stringmap_insert(config, directive, item_ptr(xstrdup(s)));
244     }
245 }
246
247 int read_config(char *file, int whinge_on_error) {
248     return read_config_file(file, whinge_on_error);
249 }