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