b781d83e7a148c8fbdbab5d457e7e2888fe7b8f0
[collectd.git] / src / libesl / esl_config.c
1 /*
2  * Copyright (c) 2007, Anthony Minessale II
3  * All rights reserved.
4  * 
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 
16  * * Neither the name of the original author; nor the names of any contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  * 
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
25  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include "esl.h"
35 #include "esl_config.h"
36
37 ESL_DECLARE(int) esl_config_open_file(esl_config_t *cfg, const char *file_path)
38 {
39         FILE *f;
40         const char *path = NULL;
41         char path_buf[1024];
42
43         if (file_path[0] == '/') {
44                 path = file_path;
45         } else {
46                 esl_snprintf(path_buf, sizeof(path_buf), "%s%s%s", ESL_CONFIG_DIR, ESL_PATH_SEPARATOR, file_path);
47                 path = path_buf;
48         }
49
50         if (!path) {
51                 return 0;
52         }
53
54         memset(cfg, 0, sizeof(*cfg));
55         cfg->lockto = -1;
56         esl_log(ESL_LOG_DEBUG, "Configuration file is %s.\n", path);
57         f = fopen(path, "r");
58
59         if (!f) {
60                 if (file_path[0] != '/') {
61                         int last = -1;
62                         char *var, *val;
63
64                         esl_snprintf(path_buf, sizeof(path_buf), "%s%sopenesl.conf", ESL_CONFIG_DIR, ESL_PATH_SEPARATOR);
65                         path = path_buf;
66
67                         if ((f = fopen(path, "r")) == 0) {
68                                 return 0;
69                         }
70
71                         cfg->file = f;
72                         esl_set_string(cfg->path, path);
73
74                         while (esl_config_next_pair(cfg, &var, &val)) {
75                                 if ((cfg->sectno != last) && !strcmp(cfg->section, file_path)) {
76                                         cfg->lockto = cfg->sectno;
77                                         return 1;
78                                 }
79                         }
80
81                         esl_config_close_file(cfg);
82                         memset(cfg, 0, sizeof(*cfg));
83                         return 0;
84                 }
85
86                 return 0;
87         } else {
88                 cfg->file = f;
89                 esl_set_string(cfg->path, path);
90                 return 1;
91         }
92 }
93
94 ESL_DECLARE(void) esl_config_close_file(esl_config_t *cfg)
95 {
96
97         if (cfg->file) {
98                 fclose(cfg->file);
99         }
100
101         memset(cfg, 0, sizeof(*cfg));
102 }
103
104
105
106 ESL_DECLARE(int) esl_config_next_pair(esl_config_t *cfg, char **var, char **val)
107 {
108         int ret = 0;
109         char *p, *end;
110
111         *var = *val = NULL;
112
113         if (!cfg->path) {
114                 return 0;
115         }
116
117         for (;;) {
118                 cfg->lineno++;
119
120                 if (!fgets(cfg->buf, sizeof(cfg->buf), cfg->file)) {
121                         ret = 0;
122                         break;
123                 }
124                 *var = cfg->buf;
125
126                 if (**var == '[' && (end = strchr(*var, ']')) != 0) {
127                         *end = '\0';
128                         (*var)++;
129                         if (**var == '+') {
130                                 (*var)++;
131                                 esl_copy_string(cfg->section, *var, sizeof(cfg->section));
132                                 cfg->sectno++;
133
134                                 if (cfg->lockto > -1 && cfg->sectno != cfg->lockto) {
135                                         break;
136                                 }
137                                 cfg->catno = 0;
138                                 cfg->lineno = 0;
139                                 *var = (char *) "";
140                                 *val = (char *) "";
141                                 return 1;
142                         } else {
143                                 esl_copy_string(cfg->category, *var, sizeof(cfg->category));
144                                 cfg->catno++;
145                         }
146                         continue;
147                 }
148
149
150
151                 if (**var == '#' || **var == ';' || **var == '\n' || **var == '\r') {
152                         continue;
153                 }
154
155                 if (!strncmp(*var, "__END__", 7)) {
156                         break;
157                 }
158
159
160                 if ((end = strchr(*var, ';')) && *(end+1) == *end) {
161                         *end = '\0';
162                         end--;
163                 } else if ((end = strchr(*var, '\n')) != 0) {
164                         if (*(end - 1) == '\r') {
165                                 end--;
166                         }
167                         *end = '\0';
168                 }
169
170                 p = *var;
171                 while ((*p == ' ' || *p == '\t') && p != end) {
172                         *p = '\0';
173                         p++;
174                 }
175                 *var = p;
176
177
178                 if ((*val = strchr(*var, '=')) == 0) {
179                         ret = -1;
180                         /* log_printf(0, server.log, "Invalid syntax on %s: line %d\n", cfg->path, cfg->lineno); */
181                         continue;
182                 } else {
183                         p = *val - 1;
184                         *(*val) = '\0';
185                         (*val)++;
186                         if (*(*val) == '>') {
187                                 *(*val) = '\0';
188                                 (*val)++;
189                         }
190
191                         while ((*p == ' ' || *p == '\t') && p != *var) {
192                                 *p = '\0';
193                                 p--;
194                         }
195
196                         p = *val;
197                         while ((*p == ' ' || *p == '\t') && p != end) {
198                                 *p = '\0';
199                                 p++;
200                         }
201                         *val = p;
202                         ret = 1;
203                         break;
204                 }
205         }
206
207
208         return ret;
209
210 }
211
212 ESL_DECLARE(int) esl_config_get_cas_bits(char *strvalue, unsigned char *outbits)
213 {
214         char cas_bits[5];
215         unsigned char bit = 0x8;
216         char *double_colon = strchr(strvalue, ':');
217         int x = 0;
218
219         if (!double_colon) {
220                 esl_log(ESL_LOG_ERROR, "No CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon);
221                 return -1;
222         }
223
224         double_colon++;
225         *outbits = 0;
226         cas_bits[4] = 0;
227
228         if (sscanf(double_colon, "%c%c%c%c", &cas_bits[0], &cas_bits[1], &cas_bits[2], &cas_bits[3]) != 4) {
229                 esl_log(ESL_LOG_ERROR, "Invalid CAS bits specified: %s, :xxxx definition expected, where x is 1 or 0\n", double_colon);
230                 return -1;
231         }
232
233         esl_log(ESL_LOG_DEBUG, "CAS bits specification found: %s\n", cas_bits);
234
235         for (; cas_bits[x]; x++) {
236                 if ('1' == cas_bits[x]) {
237                         *outbits |= bit;
238                 } else if ('0' != cas_bits[x]) {
239                         esl_log(ESL_LOG_ERROR, "Invalid CAS pattern specified: %s, just 0 or 1 allowed for each bit\n");
240                         return -1;
241                 }
242                 bit >>= 1;
243         }
244         return 0;
245 }
246
247 /* For Emacs:
248  * Local Variables:
249  * mode:c
250  * indent-tabs-mode:t
251  * tab-width:4
252  * c-basic-offset:4
253  * End:
254  * For VIM:
255  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
256  */