Annotation of embedaddon/iftop/cfgfile.c, revision 1.1.1.1
1.1 misho 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: "port-display",
40: NULL
41: };
42:
43: stringmap config;
44:
45: extern options_t options ;
46:
47: int is_cfgdirective_valid(const char *s) {
48: char **t;
49: for (t = config_directives; *t != NULL; ++t)
50: if (strcmp(s, *t) == 0) return 1;
51: return 0;
52: }
53:
54: int config_init() {
55: config = stringmap_new();
56: return config != NULL;
57: }
58:
59: /* read_config_file:
60: * Read a configuration file consisting of key: value tuples, returning a
61: * stringmap of the results. Prints errors to stderr, rather than using
62: * syslog, since this file is called at program startup. Returns 1 on success
63: * or 0 on failure. */
64: int read_config_file(const char *f, int whinge) {
65: int ret = 0;
66: FILE *fp;
67: char *line;
68: int i = 1;
69:
70: line = xmalloc(MAX_CONFIG_LINE);
71:
72: fp = fopen(f, "rt");
73: if (!fp) {
74: if(whinge) fprintf(stderr, "%s: %s\n", f, strerror(errno));
75: goto fail;
76: }
77:
78: while (fgets(line, MAX_CONFIG_LINE, fp)) {
79: char *key, *value, *r;
80:
81: for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
82:
83: /* Get continuation lines. Ugly. */
84: while (*(line + strlen(line) - 1) == '\\') {
85: if (!fgets(line + strlen(line) - 1, MAX_CONFIG_LINE - strlen(line), fp))
86: break;
87: for (r = line + strlen(line) - 1; r > line && *r == '\n'; *(r--) = 0);
88: }
89:
90: /* Strip comment. */
91: key = strpbrk(line, "#\n");
92: if (key) *key = 0;
93:
94: /* foo : bar baz quux
95: * key^ ^value */
96: key = line + strspn(line, " \t");
97: value = strchr(line, ':');
98:
99: if (value) {
100: /* foo : bar baz quux
101: * key^ ^r ^value */
102: ++value;
103:
104: r = key + strcspn(key, " \t:");
105: if (r != key) {
106: item *I;
107: *r = 0;
108:
109: /* foo\0: bar baz quux
110: * key^ ^value ^r */
111: value += strspn(value, " \t");
112: r = value + strlen(value) - 1;
113: while (strchr(" \t", *r) && r > value) --r;
114: *(r + 1) = 0;
115:
116: /* (Removed check for zero length value.) */
117:
118: /* Check that this is a valid key. */
119: if (!is_cfgdirective_valid(key))
120: fprintf(stderr, "%s:%d: warning: unknown directive \"%s\"\n", f, i, key);
121: else if ((I = stringmap_insert(config, key, item_ptr(xstrdup(value)))))
122: /* Don't warn of repeated directives, because they
123: * may have been specified via the command line
124: * Previous option takes precedence.
125: */
126: fprintf(stderr, "%s:%d: warning: repeated directive \"%s\"\n", f, i, key);
127: }
128: }
129:
130: memset(line, 0, MAX_CONFIG_LINE); /* security paranoia */
131:
132: ++i;
133: }
134:
135: ret = 1;
136:
137: fail:
138: if (fp) fclose(fp);
139: if (line) xfree(line);
140:
141: return ret;
142: }
143:
144: int config_get_int(const char *directive, int *value) {
145: stringmap S;
146: char *s, *t;
147:
148: if (!value) return -1;
149:
150: S = stringmap_find(config, directive);
151: if (!S) return 0;
152:
153: s = (char*)S->d.v;
154: if (!*s) return -1;
155: errno = 0;
156: *value = strtol(s, &t, 10);
157: if (*t) return -1;
158:
159: return errno == ERANGE ? -1 : 1;
160: }
161:
162: /* config_get_float:
163: * Get an integer value from a config string. Returns 1 on success, -1 on
164: * failure, or 0 if no value was found. */
165: int config_get_float(const char *directive, float *value) {
166: stringmap S;
167: item *I;
168: char *s, *t;
169:
170: if (!value) return -1;
171:
172: if (!(S = stringmap_find(config, directive)))
173: return 0;
174:
175: s = (char*)S->d.v;
176: if (!*s) return -1;
177: errno = 0;
178: *value = strtod(s, &t);
179: if (*t) return -1;
180:
181: return errno == ERANGE ? -1 : 1;
182: }
183:
184: /* config_get_string;
185: * Get a string value from the config file. Returns NULL if it is not
186: * present. */
187: char *config_get_string(const char *directive) {
188: stringmap S;
189:
190: S = stringmap_find(config, directive);
191: if (S) return (char*)S->d.v;
192: else return NULL;
193: }
194:
195: /* config_get_bool:
196: * Get a boolean value from the config file. Returns false if not present. */
197: int config_get_bool(const char *directive) {
198: char *s;
199:
200: s = config_get_string(directive);
201: if (s && (strcmp(s, "yes") == 0 || strcmp(s, "true") == 0))
202: return 1;
203: else
204: return 0;
205: }
206:
207: /* config_get_enum:
208: * Get an enumeration value from the config file. Returns false if not
209: * present or an invalid value is found. */
210: int config_get_enum(const char *directive, config_enumeration_type *enumeration, int *value) {
211: char *s;
212: config_enumeration_type *t;
213: s = config_get_string(directive);
214: if(s) {
215: for(t = enumeration; t->name; t++) {
216: if(strcmp(s,t->name) == 0) {
217: *value = t->value;
218: return 1;
219: }
220: }
221: fprintf(stderr,"Invalid enumeration value \"%s\" for directive \"%s\"\n", s, directive);
222: }
223: return 0;
224: }
225:
226: /* config_set_string; Sets a value in the config, possibly overriding
227: * an existing value
228: */
229: void config_set_string(const char *directive, const char* s) {
230: stringmap S;
231:
232: S = stringmap_find(config, directive);
233: if (S) stringmap_delete_free(S);
234: stringmap_insert(config, directive, item_ptr(xstrdup(s)));
235: }
236:
237: int read_config(char *file, int whinge_on_error) {
238: void* o;
239:
240: return read_config_file(file, whinge_on_error);
241: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>