]> git.itanic.dy.fi Git - rrdd/blob - config.c
onewire_parser.c: Fix compiler warnings about string lengths
[rrdd] / config.c
1 #include <stdlib.h>
2 #include <string.h>
3
4 #include "debug.h"
5 #include "config.h"
6 #include "rrdtool.h"
7 #include "parser.h"
8
9 #define RRD_DATABASE_LIST "rrd_database"
10 #define RRD_DATABASE_NAME "name"
11
12 static int read_strings_from_list(config_setting_t *list, const char ***strings)
13 {
14         config_setting_t *string;
15         int j;
16         int str_count = config_setting_length(list);
17         const char **strs;
18
19         strs = calloc(sizeof(*strs), str_count + 1);
20
21         for (j = 0; j < str_count; j++) {
22                 const char *str;
23
24                 string = config_setting_get_elem(list, j);
25                 str = config_setting_get_string(string);
26                 strs[j] = strdup(str);
27         }
28         *strings = strs;
29
30         return 0;
31 }
32
33 static int parse_images(config_setting_t *list, struct rrd_database *db)
34 {
35         int i, count;
36         config_setting_t *image, *str_list;
37         const char *database = NULL, *filename = NULL, *timestart = NULL;
38         const char *timeend = NULL, *imageformat = NULL;
39         const char **options = NULL, **text = NULL;
40         const char *updatestr = NULL;
41         int width = 0, height = 0, text_lead = 0;
42
43         count = config_setting_length(list);
44
45         pr_info("%s: Parsing %d images\n", db->name, count);
46         db->images = calloc(sizeof(*db->images), count + 1);
47
48         for (i = 0; i < count; i++) {
49                 image = config_setting_get_elem(list, i);
50                 db->images[i] = calloc(sizeof(*db->images[i]), 1);
51
52                 config_setting_lookup_string(image, "database", &database);
53                 config_setting_lookup_int(image, "text_lead", &text_lead);
54
55                 /*
56                  * The config_setting_lookup_* functions will leave
57                  * the destination unchanged in case requested value
58                  * is not found. If that is the case, the value from
59                  * previous image group is used. That makes it
60                  * possible for the user to only define once all
61                  * fields and then leave identical fields unset on the
62                  * following groups, making it easier to define many
63                  * almost identical images.
64                  */
65
66                 config_setting_lookup_string(image, "filename", &filename);
67                 if (!filename) {
68                         pr_err("Database %s does not have \"filename\" entry "
69                                 " in image data\n",
70                                 db->name);
71                         return -1;
72                 }
73
74                 config_setting_lookup_int(image, "width", &width);
75                 if (!width) {
76                         pr_err("Database %s does not have \"width\" entry "
77                                 " in image data\n",
78                                 db->name);
79                         return -1;
80                 }
81
82                 config_setting_lookup_int(image, "height", &height);
83                 if (!height) {
84                         pr_err("Database %s does not have \"height\" entry "
85                                 " in image data\n",
86                                 db->name);
87                         return -1;
88                 }
89
90                 config_setting_lookup_string(image, "timestart", &timestart);
91                 if (!timestart) {
92                         pr_err("Database %s does not have \"timestart\" entry "
93                                 " in image data\n",
94                                 db->name);
95                         return -1;
96                 }
97
98                 config_setting_lookup_string(image, "timeend", &timeend);
99                 if (!timeend) {
100                         pr_err("Database %s does not have \"timeend\" entry "
101                                 " in image data\n",
102                                 db->name);
103                         return -1;
104                 }
105
106                 config_setting_lookup_string(image, "imageformat",
107                                         &imageformat);
108                 if (!imageformat) {
109                         pr_err("Database %s does not have \"imageformat\" "\
110                                 "entry in image data\n",
111                                 db->name);
112                         return -1;
113                 }
114
115                 config_setting_lookup_string(image, "update_string",
116                                         &updatestr);
117
118                 str_list = config_setting_get_member(image, "options");
119                 if (str_list)
120                         read_strings_from_list(str_list, &options);
121
122                 str_list = config_setting_get_member(image, "text");
123                 if (str_list)
124                         read_strings_from_list(str_list, &text);
125
126                 db->images[i]->rrd_database     =
127                         database ? strdup(database) : NULL;
128                 db->images[i]->image_filename   = strdup(filename);
129                 db->images[i]->width            = width;
130                 db->images[i]->height           = height;
131                 strncpy(db->images[i]->timestart, timestart,
132                         sizeof(db->images[i]->timestart) - 1);
133                 strncpy(db->images[i]->timeend, timeend,
134                         sizeof(db->images[i]->timeend) - 1);
135                 strncpy(db->images[i]->imageformat, imageformat,
136                         sizeof(db->images[i]->imageformat) - 1);
137                 db->images[i]->options          = options;
138                 db->images[i]->text_lead        = text_lead;
139                 db->images[i]->text             = text;
140
141                 if (updatestr)
142                         db->images[i]->updatestr = strdup(updatestr);
143         }
144
145         return 0;
146 }
147
148 static int parse_data_sources(config_setting_t *rrd, struct rrd_database *db)
149 {
150         config_setting_t *list, *group;
151         int i, count;
152         const char *type = NULL, *name = NULL;
153         int heartbeat = 0;
154         double min = 0;
155         double max = 0;
156
157         list = config_setting_get_member(rrd, "sources");
158         if (!list) {
159                 pr_info("No data sources\n");
160                 return 0;
161         }
162
163         if (!config_setting_is_list(list)) {
164                 pr_err("Data sources have no list\n");
165                 return 0;
166         }
167
168         count = config_setting_length(list);
169         db->sources = calloc(sizeof(*db->sources), count + 1);
170
171         for (i = 0; i < count; i++) {
172                 group = config_setting_get_elem(list, i);
173
174                 config_setting_lookup_string(group, "type", &type);
175                 config_setting_lookup_string(group, "name", &name);
176                 config_setting_lookup_float(group, "min", &min);
177                 config_setting_lookup_float(group, "max", &max);
178                 config_setting_lookup_int(group, "heartbeat", &heartbeat);
179
180                 db->sources[i].type = strdup(type);
181                 db->sources[i].name = strdup(name);
182                 db->sources[i].heartbeat = heartbeat;
183                 db->sources[i].min = min;
184                 db->sources[i].max = max;
185         }
186
187         return 0;
188 }
189
190 static int parse_archives(config_setting_t *rrd, struct rrd_database *db)
191 {
192         config_setting_t *list, *group;
193         int i, count;
194         const char *type = NULL;
195         double xff = 0;
196         int steps = 0;
197         int rows = 0;
198
199         list = config_setting_get_member(rrd, "archives");
200         if (!list) {
201                 pr_info("No archive found\n");
202                 return 0;
203         }
204
205         if (!config_setting_is_list(list)) {
206                 pr_err("Archive does not contain a list\n");
207                 return 0;
208         }
209
210         count = config_setting_length(list);
211         db->archives = calloc(sizeof(*db->archives), count + 1);
212
213         for (i = 0; i < count; i++) {
214                 group = config_setting_get_elem(list, i);
215
216                 config_setting_lookup_string(group, "type", &type);
217                 config_setting_lookup_float(group, "xff", &xff);
218                 config_setting_lookup_int(group, "steps", &steps);
219                 config_setting_lookup_int(group, "rows", &rows);
220
221                 db->archives[i].type = strdup(type);
222                 db->archives[i].xff = xff;
223                 db->archives[i].steps = steps;
224                 db->archives[i].rows = rows;
225         }
226
227         return 0;
228 }
229
230 static int parse_database(config_setting_t *rrd, struct rrd_database *db)
231 {
232         config_setting_t *list, *str_list;
233         const char *name, *parser = NULL, *filename, **parser_data;
234         const char **pre_draw_cmd;
235         const char **post_draw_cmd;
236         const char *logfile = NULL, *logfile_timestamp_fmt = NULL;
237
238         if (!config_setting_lookup_string(rrd, "name", &name)) {
239                 pr_err("Database entry does not contain name\n");
240                 return -1;
241         }
242
243         pr_info("parsing database %s\n", name);
244         db->name = strdup(name);
245
246         if (!config_setting_lookup_string(rrd, "filename", &filename))
247                 pr_err("Database %s does not contain filename\n", db->name);
248
249         db->filename = strdup(filename);
250
251         if (!config_setting_lookup_int(rrd, "interval", &db->interval)) {
252                 pr_err("Database %s does not have interval set\n", name);
253                 return -1;
254         }
255
256         /* Parser is not a mandatory parameter */
257         config_setting_lookup_string(rrd, "parser", &parser);
258         db->parser = str_to_parser(parser);
259
260         list = config_setting_get_member(rrd, "image");
261         parse_images(list, db);
262         parse_data_sources(rrd, db);
263         parse_archives(rrd, db);
264
265         str_list = config_setting_get_member(rrd, "parser_data");
266         if (str_list) {
267                 read_strings_from_list(str_list, &parser_data);
268                 db->parser_data = parser_data;
269         }
270
271         str_list = config_setting_get_member(rrd, "pre_draw_cmd");
272         if (str_list) {
273                 read_strings_from_list(str_list, &pre_draw_cmd);
274                 db->pre_draw_cmd = (char *const *)pre_draw_cmd;
275         }
276
277         str_list = config_setting_get_member(rrd, "post_draw_cmd");
278         if (str_list) {
279                 read_strings_from_list(str_list, &post_draw_cmd);
280                 db->post_draw_cmd = (char *const *)post_draw_cmd;
281         }
282
283         config_setting_lookup_string(rrd, "logfile", &logfile);
284         if (logfile)
285                 db->logfile = strdup(logfile);
286
287         config_setting_lookup_string(rrd, "logfile_timestamp_fmt",
288                                 &logfile_timestamp_fmt);
289         if (logfile_timestamp_fmt)
290                 db->logfile_timestamp_fmt = strdup(logfile_timestamp_fmt);
291
292
293         return 0;
294 }
295
296 struct rrd_database **populate_database(const char *conffile)
297 {
298         struct rrd_database **rrd_db = NULL;
299         config_t config;
300         config_setting_t *rrd_database;
301         int i, count;
302
303         config_init(&config);
304
305         if (!config_read_file(&config, conffile)) {
306                 pr_err("%s:%d - %s\n", config_error_file(&config),
307                         config_error_line(&config),
308                         config_error_text(&config));
309                 goto out;
310         }
311
312         rrd_database = config_lookup(&config, "rrd_database");
313         count = config_setting_length(rrd_database);
314
315         /*
316          * Allocate one element extra. The last one is zeroed out to
317          * indicate the end of the db list
318          */
319         rrd_db = calloc(count + 1, sizeof(*rrd_db));
320
321         pr_info("There are %d database entries\n", count);
322
323         for (i = 0; i < count; i++) {
324                 config_setting_t *rrd;
325                 rrd_db[i] = calloc(1, sizeof(*rrd_db[i]));
326                 rrd = config_setting_get_elem(rrd_database, i);
327                 parse_database(rrd, rrd_db[i]);
328         }
329
330 out:
331         config_destroy(&config);
332         return rrd_db;
333 }