93e90e3b14442199f3600547d5084beef065a83c
[collectd.git] / src / daemon / configfile.c
1 /**
2  * collectd - src/configfile.c
3  * Copyright (C) 2005-2011  Florian octo Forster
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Florian octo Forster <octo at collectd.org>
25  *   Sebastian tokkee Harl <sh at tokkee.org>
26  **/
27
28 #include "collectd.h"
29
30 #include "liboconfig/oconfig.h"
31
32 #include "common.h"
33 #include "plugin.h"
34 #include "configfile.h"
35 #include "types_list.h"
36 #include "filter_chain.h"
37
38 #if HAVE_WORDEXP_H
39 # include <wordexp.h>
40 #endif /* HAVE_WORDEXP_H */
41
42 #if HAVE_FNMATCH_H
43 # include <fnmatch.h>
44 #endif /* HAVE_FNMATCH_H */
45
46 #if HAVE_LIBGEN_H
47 # include <libgen.h>
48 #endif /* HAVE_LIBGEN_H */
49
50 #define ESCAPE_NULL(str) ((str) == NULL ? "(null)" : (str))
51
52 /*
53  * Private types
54  */
55 typedef struct cf_callback
56 {
57         const char  *type;
58         int  (*callback) (const char *, const char *);
59         const char **keys;
60         int    keys_num;
61         plugin_ctx_t ctx;
62         struct cf_callback *next;
63 } cf_callback_t;
64
65 typedef struct cf_complex_callback_s
66 {
67         char *type;
68         int (*callback) (oconfig_item_t *);
69         plugin_ctx_t ctx;
70         struct cf_complex_callback_s *next;
71 } cf_complex_callback_t;
72
73 typedef struct cf_value_map_s
74 {
75         const char *key;
76         int (*func) (oconfig_item_t *);
77 } cf_value_map_t;
78
79 typedef struct cf_global_option_s
80 {
81         const char *key;
82         char *value;
83         _Bool from_cli; /* value set from CLI */
84         const char *def;
85 } cf_global_option_t;
86
87 /*
88  * Prototypes of callback functions
89  */
90 static int dispatch_value_typesdb (oconfig_item_t *ci);
91 static int dispatch_value_plugindir (oconfig_item_t *ci);
92 static int dispatch_loadplugin (oconfig_item_t *ci);
93 static int dispatch_block_plugin (oconfig_item_t *ci);
94
95 /*
96  * Private variables
97  */
98 static cf_callback_t *first_callback = NULL;
99 static cf_complex_callback_t *complex_callback_head = NULL;
100
101 static cf_value_map_t cf_value_map[] =
102 {
103         {"TypesDB",    dispatch_value_typesdb},
104         {"PluginDir",  dispatch_value_plugindir},
105         {"LoadPlugin", dispatch_loadplugin},
106         {"Plugin",     dispatch_block_plugin}
107 };
108 static int cf_value_map_num = STATIC_ARRAY_SIZE (cf_value_map);
109
110 static cf_global_option_t cf_global_options[] =
111 {
112         {"BaseDir",              NULL, 0, PKGLOCALSTATEDIR},
113         {"PIDFile",              NULL, 0, PIDFILE},
114         {"Hostname",             NULL, 0, NULL},
115         {"FQDNLookup",           NULL, 0, "true"},
116         {"Interval",             NULL, 0, NULL},
117         {"ReadThreads",          NULL, 0, "5"},
118         {"WriteThreads",         NULL, 0, "5"},
119         {"WriteQueueLimitHigh",  NULL, 0, NULL},
120         {"WriteQueueLimitLow",   NULL, 0, NULL},
121         {"Timeout",              NULL, 0, "2"},
122         {"AutoLoadPlugin",       NULL, 0, "false"},
123         {"CollectInternalStats", NULL, 0, "false"},
124         {"PreCacheChain",        NULL, 0, "PreCache"},
125         {"PostCacheChain",       NULL, 0, "PostCache"},
126         {"MaxReadInterval",      NULL, 0, "86400"}
127 };
128 static int cf_global_options_num = STATIC_ARRAY_SIZE (cf_global_options);
129
130 static int cf_default_typesdb = 1;
131
132 /*
133  * Functions to handle register/unregister, search, and other plugin related
134  * stuff
135  */
136 static cf_callback_t *cf_search (const char *type)
137 {
138         cf_callback_t *cf_cb;
139
140         if (type == NULL)
141                 return (NULL);
142
143         for (cf_cb = first_callback; cf_cb != NULL; cf_cb = cf_cb->next)
144                 if (strcasecmp (cf_cb->type, type) == 0)
145                         break;
146
147         return (cf_cb);
148 }
149
150 static int cf_dispatch (const char *type, const char *orig_key,
151                 const char *orig_value)
152 {
153         cf_callback_t *cf_cb;
154         plugin_ctx_t old_ctx;
155         char *key;
156         char *value;
157         int ret;
158         int i;
159
160         if (orig_key == NULL)
161                 return (EINVAL);
162
163         DEBUG ("type = %s, key = %s, value = %s",
164                         ESCAPE_NULL(type),
165                         orig_key,
166                         ESCAPE_NULL(orig_value));
167
168         if ((cf_cb = cf_search (type)) == NULL)
169         {
170                 WARNING ("Found a configuration for the `%s' plugin, but "
171                                 "the plugin isn't loaded or didn't register "
172                                 "a configuration callback.", type);
173                 return (-1);
174         }
175
176         if ((key = strdup (orig_key)) == NULL)
177                 return (1);
178         if ((value = strdup (orig_value)) == NULL)
179         {
180                 free (key);
181                 return (2);
182         }
183
184         ret = -1;
185
186         old_ctx = plugin_set_ctx (cf_cb->ctx);
187
188         for (i = 0; i < cf_cb->keys_num; i++)
189         {
190                 if ((cf_cb->keys[i] != NULL)
191                                 && (strcasecmp (cf_cb->keys[i], key) == 0))
192                 {
193                         ret = (*cf_cb->callback) (key, value);
194                         break;
195                 }
196         }
197
198         plugin_set_ctx (old_ctx);
199
200         if (i >= cf_cb->keys_num)
201                 WARNING ("Plugin `%s' did not register for value `%s'.", type, key);
202
203         free (key);
204         free (value);
205
206         return (ret);
207 } /* int cf_dispatch */
208
209 static int dispatch_global_option (const oconfig_item_t *ci)
210 {
211         if (ci->values_num != 1)
212                 return (-1);
213         if (ci->values[0].type == OCONFIG_TYPE_STRING)
214                 return (global_option_set (ci->key, ci->values[0].value.string, 0));
215         else if (ci->values[0].type == OCONFIG_TYPE_NUMBER)
216         {
217                 char tmp[128];
218                 ssnprintf (tmp, sizeof (tmp), "%lf", ci->values[0].value.number);
219                 return (global_option_set (ci->key, tmp, 0));
220         }
221         else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
222         {
223                 if (ci->values[0].value.boolean)
224                         return (global_option_set (ci->key, "true", 0));
225                 else
226                         return (global_option_set (ci->key, "false", 0));
227         }
228
229         return (-1);
230 } /* int dispatch_global_option */
231
232 static int dispatch_value_typesdb (oconfig_item_t *ci)
233 {
234         int i = 0;
235
236         assert (strcasecmp (ci->key, "TypesDB") == 0);
237
238         cf_default_typesdb = 0;
239
240         if (ci->values_num < 1) {
241                 ERROR ("configfile: `TypesDB' needs at least one argument.");
242                 return (-1);
243         }
244
245         for (i = 0; i < ci->values_num; ++i)
246         {
247                 if (OCONFIG_TYPE_STRING != ci->values[i].type) {
248                         WARNING ("configfile: TypesDB: Skipping %i. argument which "
249                                         "is not a string.", i + 1);
250                         continue;
251                 }
252
253                 read_types_list (ci->values[i].value.string);
254         }
255         return (0);
256 } /* int dispatch_value_typesdb */
257
258 static int dispatch_value_plugindir (oconfig_item_t *ci)
259 {
260         assert (strcasecmp (ci->key, "PluginDir") == 0);
261
262         if (ci->values_num != 1)
263                 return (-1);
264         if (ci->values[0].type != OCONFIG_TYPE_STRING)
265                 return (-1);
266
267         plugin_set_dir (ci->values[0].value.string);
268         return (0);
269 }
270
271 static int dispatch_loadplugin (oconfig_item_t *ci)
272 {
273         int i;
274         const char *name;
275         unsigned int flags = 0;
276         plugin_ctx_t ctx;
277         plugin_ctx_t old_ctx;
278         int ret_val;
279
280         assert (strcasecmp (ci->key, "LoadPlugin") == 0);
281
282         if (ci->values_num != 1)
283                 return (-1);
284         if (ci->values[0].type != OCONFIG_TYPE_STRING)
285                 return (-1);
286
287         name = ci->values[0].value.string;
288         if (strcmp ("libvirt", name) == 0)
289                 name = "virt";
290
291         /* default to the global interval set before loading this plugin */
292         memset (&ctx, 0, sizeof (ctx));
293         ctx.interval = cf_get_default_interval ();
294         ctx.flush_interval = 0;
295         ctx.flush_timeout = 0;
296
297         for (i = 0; i < ci->children_num; ++i)
298         {
299                 oconfig_item_t *child = ci->children + i;
300
301                 if (strcasecmp("Globals", child->key) == 0)
302                         cf_util_get_flag (child, &flags, PLUGIN_FLAGS_GLOBAL);
303                 else if (strcasecmp ("Interval", child->key) == 0)
304                         cf_util_get_cdtime (child, &ctx.interval);
305                 else if (strcasecmp ("FlushInterval", child->key) == 0)
306                         cf_util_get_cdtime (child, &ctx.flush_interval);
307                 else if (strcasecmp ("FlushTimeout", child->key) == 0)
308                         cf_util_get_cdtime (child, &ctx.flush_timeout);
309                 else {
310                         WARNING("Ignoring unknown LoadPlugin option \"%s\" "
311                                         "for plugin \"%s\"",
312                                         child->key, ci->values[0].value.string);
313                 }
314         }
315
316         old_ctx = plugin_set_ctx (ctx);
317         ret_val = plugin_load (name, (uint32_t) flags);
318         /* reset to the "global" context */
319         plugin_set_ctx (old_ctx);
320
321         return (ret_val);
322 } /* int dispatch_value_loadplugin */
323
324 static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci)
325 {
326         char  buffer[4096];
327         char *buffer_ptr;
328         int   buffer_free;
329         int i;
330
331         buffer_ptr = buffer;
332         buffer_free = sizeof (buffer);
333
334         for (i = 0; i < ci->values_num; i++)
335         {
336                 int status = -1;
337
338                 if (ci->values[i].type == OCONFIG_TYPE_STRING)
339                         status = ssnprintf (buffer_ptr, buffer_free, " %s",
340                                         ci->values[i].value.string);
341                 else if (ci->values[i].type == OCONFIG_TYPE_NUMBER)
342                         status = ssnprintf (buffer_ptr, buffer_free, " %lf",
343                                         ci->values[i].value.number);
344                 else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
345                         status = ssnprintf (buffer_ptr, buffer_free, " %s",
346                                         ci->values[i].value.boolean
347                                         ? "true" : "false");
348
349                 if ((status < 0) || (status >= buffer_free))
350                         return (-1);
351                 buffer_free -= status;
352                 buffer_ptr  += status;
353         }
354         /* skip the initial space */
355         buffer_ptr = buffer + 1;
356
357         return (cf_dispatch (plugin, ci->key, buffer_ptr));
358 } /* int dispatch_value_plugin */
359
360 static int dispatch_value (oconfig_item_t *ci)
361 {
362         int ret = 0;
363         int i;
364
365         for (i = 0; i < cf_value_map_num; i++)
366                 if (strcasecmp (cf_value_map[i].key, ci->key) == 0)
367                 {
368                         ret = cf_value_map[i].func (ci);
369                         break;
370                 }
371
372         for (i = 0; i < cf_global_options_num; i++)
373                 if (strcasecmp (cf_global_options[i].key, ci->key) == 0)
374                 {
375                         ret = dispatch_global_option (ci);
376                         break;
377                 }
378
379         return (ret);
380 } /* int dispatch_value */
381
382 static int dispatch_block_plugin (oconfig_item_t *ci)
383 {
384         int i;
385         const char *name;
386
387         cf_complex_callback_t *cb;
388
389         if (strcasecmp (ci->key, "Plugin") != 0)
390                 return (-1);
391         if (ci->values_num < 1)
392                 return (-1);
393         if (ci->values[0].type != OCONFIG_TYPE_STRING)
394                 return (-1);
395
396         name = ci->values[0].value.string;
397         if (strcmp ("libvirt", name) == 0)
398         {
399                 /* TODO(octo): Remove this legacy. */
400                 WARNING ("The \"libvirt\" plugin has been renamed to \"virt\" to avoid problems with the build system. "
401                                 "Your configuration is still using the old name. "
402                                 "Please change it to use \"virt\" as soon as possible. "
403                                 "This compatibility code will go away eventually.");
404                 name = "virt";
405         }
406
407         if (IS_TRUE (global_option_get ("AutoLoadPlugin")))
408         {
409                 plugin_ctx_t ctx;
410                 plugin_ctx_t old_ctx;
411                 int status;
412
413                 /* default to the global interval set before loading this plugin */
414                 memset (&ctx, 0, sizeof (ctx));
415                 ctx.interval = cf_get_default_interval ();
416
417                 old_ctx = plugin_set_ctx (ctx);
418                 status = plugin_load (name, /* flags = */ 0);
419                 /* reset to the "global" context */
420                 plugin_set_ctx (old_ctx);
421
422                 if (status != 0)
423                 {
424                         ERROR ("Automatically loading plugin \"%s\" failed "
425                                         "with status %i.", name, status);
426                         return (status);
427                 }
428         }
429
430         /* Check for a complex callback first */
431         for (cb = complex_callback_head; cb != NULL; cb = cb->next)
432         {
433                 if (strcasecmp (name, cb->type) == 0)
434                 {
435                         plugin_ctx_t old_ctx;
436                         int ret_val;
437
438                         old_ctx = plugin_set_ctx (cb->ctx);
439                         ret_val = (cb->callback (ci));
440                         plugin_set_ctx (old_ctx);
441                         return (ret_val);
442                 }
443         }
444
445         /* Hm, no complex plugin found. Dispatch the values one by one */
446         for (i = 0; i < ci->children_num; i++)
447         {
448                 if (ci->children[i].children == NULL)
449                         dispatch_value_plugin (name, ci->children + i);
450                 else
451                 {
452                         WARNING ("There is a `%s' block within the "
453                                         "configuration for the %s plugin. "
454                                         "The plugin either only expects "
455                                         "\"simple\" configuration statements "
456                                         "or wasn't loaded using `LoadPlugin'."
457                                         " Please check your configuration.",
458                                         ci->children[i].key, name);
459                 }
460         }
461
462         return (0);
463 }
464
465
466 static int dispatch_block (oconfig_item_t *ci)
467 {
468         if (strcasecmp (ci->key, "LoadPlugin") == 0)
469                 return (dispatch_loadplugin (ci));
470         else if (strcasecmp (ci->key, "Plugin") == 0)
471                 return (dispatch_block_plugin (ci));
472         else if (strcasecmp (ci->key, "Chain") == 0)
473                 return (fc_configure (ci));
474
475         return (0);
476 }
477
478 static int cf_ci_replace_child (oconfig_item_t *dst, oconfig_item_t *src,
479                 int offset)
480 {
481         oconfig_item_t *temp;
482         int i;
483
484         assert (offset >= 0);
485         assert (dst->children_num > offset);
486
487         /* Free the memory used by the replaced child. Usually that's the
488          * `Include "blah"' statement. */
489         temp = dst->children + offset;
490         for (i = 0; i < temp->values_num; i++)
491         {
492                 if (temp->values[i].type == OCONFIG_TYPE_STRING)
493                 {
494                         sfree (temp->values[i].value.string);
495                 }
496         }
497         sfree (temp->values);
498         temp = NULL;
499
500         /* If (src->children_num == 0) the array size is decreased. If offset
501          * is _not_ the last element, (offset < (dst->children_num - 1)), then
502          * we need to move the trailing elements before resizing the array. */
503         if ((src->children_num == 0) && (offset < (dst->children_num - 1)))
504         {
505                 int nmemb = dst->children_num - (offset + 1);
506                 memmove (dst->children + offset, dst->children + offset + 1,
507                                 sizeof (oconfig_item_t) * nmemb);
508         }
509
510         /* Resize the memory containing the children to be big enough to hold
511          * all children. */
512         if (dst->children_num + src->children_num - 1 == 0)
513         {
514                 dst->children_num = 0;
515                 return (0);
516         }
517
518         temp = realloc (dst->children,
519                         sizeof (oconfig_item_t)
520                         * (dst->children_num + src->children_num - 1));
521         if (temp == NULL)
522         {
523                 ERROR ("configfile: realloc failed.");
524                 return (-1);
525         }
526         dst->children = temp;
527
528         /* If there are children behind the include statement, and they have
529          * not yet been moved because (src->children_num == 0), then move them
530          * to the end of the list, so that the new children have room before
531          * them. */
532         if ((src->children_num > 0)
533                         && ((dst->children_num - (offset + 1)) > 0))
534         {
535                 int nmemb = dst->children_num - (offset + 1);
536                 int old_offset = offset + 1;
537                 int new_offset = offset + src->children_num;
538
539                 memmove (dst->children + new_offset,
540                                 dst->children + old_offset,
541                                 sizeof (oconfig_item_t) * nmemb);
542         }
543
544         /* Last but not least: If there are new children, copy them to the
545          * memory reserved for them. */
546         if (src->children_num > 0)
547         {
548                 memcpy (dst->children + offset,
549                                 src->children,
550                                 sizeof (oconfig_item_t) * src->children_num);
551         }
552
553         /* Update the number of children. */
554         dst->children_num += (src->children_num - 1);
555
556         return (0);
557 } /* int cf_ci_replace_child */
558
559 static int cf_ci_append_children (oconfig_item_t *dst, oconfig_item_t *src)
560 {
561         oconfig_item_t *temp;
562
563         if ((src == NULL) || (src->children_num == 0))
564                 return (0);
565
566         temp = realloc (dst->children,
567                         sizeof (oconfig_item_t)
568                         * (dst->children_num + src->children_num));
569         if (temp == NULL)
570         {
571                 ERROR ("configfile: realloc failed.");
572                 return (-1);
573         }
574         dst->children = temp;
575
576         memcpy (dst->children + dst->children_num,
577                         src->children,
578                         sizeof (oconfig_item_t)
579                         * src->children_num);
580         dst->children_num += src->children_num;
581
582         return (0);
583 } /* int cf_ci_append_children */
584
585 #define CF_MAX_DEPTH 8
586 static oconfig_item_t *cf_read_generic (const char *path,
587                 const char *pattern, int depth);
588
589 static int cf_include_all (oconfig_item_t *root, int depth)
590 {
591         int i;
592
593         for (i = 0; i < root->children_num; i++)
594         {
595                 oconfig_item_t *new;
596                 oconfig_item_t *old;
597
598                 char *pattern = NULL;
599
600                 int j;
601
602                 if (strcasecmp (root->children[i].key, "Include") != 0)
603                         continue;
604
605                 old = root->children + i;
606
607                 if ((old->values_num != 1)
608                                 || (old->values[0].type != OCONFIG_TYPE_STRING))
609                 {
610                         ERROR ("configfile: `Include' needs exactly one string argument.");
611                         continue;
612                 }
613
614                 for (j = 0; j < old->children_num; ++j)
615                 {
616                         oconfig_item_t *child = old->children + j;
617
618                         if (strcasecmp (child->key, "Filter") == 0)
619                                 cf_util_get_string (child, &pattern);
620                         else
621                                 ERROR ("configfile: Option `%s' not allowed in <Include> block.",
622                                                 child->key);
623                 }
624
625                 new = cf_read_generic (old->values[0].value.string, pattern, depth + 1);
626                 sfree (pattern);
627
628                 if (new == NULL)
629                         return (-1);
630
631                 /* Now replace the i'th child in `root' with `new'. */
632                 if (cf_ci_replace_child (root, new, i) < 0) {
633                         sfree (new->values);
634                         sfree (new);
635                         return (-1);
636                 }
637
638                 /* ... and go back to the new i'th child. */
639                 --i;
640
641                 sfree (new->values);
642                 sfree (new);
643         } /* for (i = 0; i < root->children_num; i++) */
644
645         return (0);
646 } /* int cf_include_all */
647
648 static oconfig_item_t *cf_read_file (const char *file,
649                 const char *pattern, int depth)
650 {
651         oconfig_item_t *root;
652         int status;
653
654         assert (depth < CF_MAX_DEPTH);
655
656         if (pattern != NULL) {
657 #if HAVE_FNMATCH_H && HAVE_LIBGEN_H
658                 char *tmp = sstrdup (file);
659                 char *filename = basename (tmp);
660
661                 if ((filename != NULL) && (fnmatch (pattern, filename, 0) != 0)) {
662                         DEBUG ("configfile: Not including `%s' because it "
663                                         "does not match pattern `%s'.",
664                                         filename, pattern);
665                         free (tmp);
666                         return (NULL);
667                 }
668
669                 free (tmp);
670 #else
671                 ERROR ("configfile: Cannot apply pattern filter '%s' "
672                                 "to file '%s': functions basename() and / or "
673                                 "fnmatch() not available.", pattern, file);
674 #endif /* HAVE_FNMATCH_H && HAVE_LIBGEN_H */
675         }
676
677         root = oconfig_parse_file (file);
678         if (root == NULL)
679         {
680                 ERROR ("configfile: Cannot read file `%s'.", file);
681                 return (NULL);
682         }
683
684         status = cf_include_all (root, depth);
685         if (status != 0)
686         {
687                 oconfig_free (root);
688                 return (NULL);
689         }
690
691         return (root);
692 } /* oconfig_item_t *cf_read_file */
693
694 static int cf_compare_string (const void *p1, const void *p2)
695 {
696         return strcmp (*(const char **) p1, *(const char **) p2);
697 }
698
699 static oconfig_item_t *cf_read_dir (const char *dir,
700                 const char *pattern, int depth)
701 {
702         oconfig_item_t *root = NULL;
703         DIR *dh;
704         struct dirent *de;
705         char **filenames = NULL;
706         int filenames_num = 0;
707         int status;
708         int i;
709
710         assert (depth < CF_MAX_DEPTH);
711
712         dh = opendir (dir);
713         if (dh == NULL)
714         {
715                 char errbuf[1024];
716                 ERROR ("configfile: opendir failed: %s",
717                                 sstrerror (errno, errbuf, sizeof (errbuf)));
718                 return (NULL);
719         }
720
721         root = calloc (1, sizeof (*root));
722         if (root == NULL)
723         {
724                 ERROR ("configfile: calloc failed.");
725                 closedir (dh);
726                 return (NULL);
727         }
728
729         while ((de = readdir (dh)) != NULL)
730         {
731                 char   name[1024];
732                 char **tmp;
733
734                 if ((de->d_name[0] == '.') || (de->d_name[0] == 0))
735                         continue;
736
737                 status = ssnprintf (name, sizeof (name), "%s/%s",
738                                 dir, de->d_name);
739                 if ((status < 0) || ((size_t) status >= sizeof (name)))
740                 {
741                         ERROR ("configfile: Not including `%s/%s' because its"
742                                         " name is too long.",
743                                         dir, de->d_name);
744                         closedir (dh);
745                         for (i = 0; i < filenames_num; ++i)
746                                 free (filenames[i]);
747                         free (filenames);
748                         free (root);
749                         return (NULL);
750                 }
751
752                 ++filenames_num;
753                 tmp = realloc (filenames,
754                                 filenames_num * sizeof (*filenames));
755                 if (tmp == NULL) {
756                         ERROR ("configfile: realloc failed.");
757                         closedir (dh);
758                         for (i = 0; i < filenames_num - 1; ++i)
759                                 free (filenames[i]);
760                         free (filenames);
761                         free (root);
762                         return (NULL);
763                 }
764                 filenames = tmp;
765
766                 filenames[filenames_num - 1] = sstrdup (name);
767         }
768
769         if (filenames == NULL)
770         {
771                 closedir (dh);
772                 return (root);
773         }
774
775         qsort ((void *) filenames, filenames_num, sizeof (*filenames),
776                         cf_compare_string);
777
778         for (i = 0; i < filenames_num; ++i)
779         {
780                 oconfig_item_t *temp;
781                 char *name = filenames[i];
782
783                 temp = cf_read_generic (name, pattern, depth);
784                 if (temp == NULL)
785                 {
786                         /* An error should already have been reported. */
787                         sfree (name);
788                         continue;
789                 }
790
791                 cf_ci_append_children (root, temp);
792                 sfree (temp->children);
793                 sfree (temp);
794
795                 free (name);
796         }
797
798         closedir (dh);
799         free(filenames);
800         return (root);
801 } /* oconfig_item_t *cf_read_dir */
802
803 /*
804  * cf_read_generic
805  *
806  * Path is stat'ed and either cf_read_file or cf_read_dir is called
807  * accordingly.
808  *
809  * There are two versions of this function: If `wordexp' exists shell wildcards
810  * will be expanded and the function will include all matches found. If
811  * `wordexp' (or, more precisely, it's header file) is not available the
812  * simpler function is used which does not do any such expansion.
813  */
814 #if HAVE_WORDEXP_H
815 static oconfig_item_t *cf_read_generic (const char *path,
816                 const char *pattern, int depth)
817 {
818         oconfig_item_t *root = NULL;
819         int status;
820         const char *path_ptr;
821         wordexp_t we;
822         size_t i;
823
824         if (depth >= CF_MAX_DEPTH)
825         {
826                 ERROR ("configfile: Not including `%s' because the maximum "
827                                 "nesting depth has been reached.", path);
828                 return (NULL);
829         }
830
831         status = wordexp (path, &we, WRDE_NOCMD);
832         if (status != 0)
833         {
834                 ERROR ("configfile: wordexp (%s) failed.", path);
835                 return (NULL);
836         }
837
838         root = calloc (1, sizeof (*root));
839         if (root == NULL)
840         {
841                 ERROR ("configfile: calloc failed.");
842                 return (NULL);
843         }
844
845         /* wordexp() might return a sorted list already. That's not
846          * documented though, so let's make sure we get what we want. */
847         qsort ((void *) we.we_wordv, we.we_wordc, sizeof (*we.we_wordv),
848                         cf_compare_string);
849
850         for (i = 0; i < we.we_wordc; i++)
851         {
852                 oconfig_item_t *temp;
853                 struct stat statbuf;
854
855                 path_ptr = we.we_wordv[i];
856
857                 status = stat (path_ptr, &statbuf);
858                 if (status != 0)
859                 {
860                         char errbuf[1024];
861                         WARNING ("configfile: stat (%s) failed: %s",
862                                         path_ptr,
863                                         sstrerror (errno, errbuf, sizeof (errbuf)));
864                         continue;
865                 }
866
867                 if (S_ISREG (statbuf.st_mode))
868                         temp = cf_read_file (path_ptr, pattern, depth);
869                 else if (S_ISDIR (statbuf.st_mode))
870                         temp = cf_read_dir (path_ptr, pattern, depth);
871                 else
872                 {
873                         WARNING ("configfile: %s is neither a file nor a "
874                                         "directory.", path);
875                         continue;
876                 }
877
878                 if (temp == NULL) {
879                         oconfig_free (root);
880                         return (NULL);
881                 }
882
883                 cf_ci_append_children (root, temp);
884                 sfree (temp->children);
885                 sfree (temp);
886         }
887
888         wordfree (&we);
889
890         return (root);
891 } /* oconfig_item_t *cf_read_generic */
892 /* #endif HAVE_WORDEXP_H */
893
894 #else /* if !HAVE_WORDEXP_H */
895 static oconfig_item_t *cf_read_generic (const char *path,
896                 const char *pattern, int depth)
897 {
898         struct stat statbuf;
899         int status;
900
901         if (depth >= CF_MAX_DEPTH)
902         {
903                 ERROR ("configfile: Not including `%s' because the maximum "
904                                 "nesting depth has been reached.", path);
905                 return (NULL);
906         }
907
908         status = stat (path, &statbuf);
909         if (status != 0)
910         {
911                 char errbuf[1024];
912                 ERROR ("configfile: stat (%s) failed: %s",
913                                 path,
914                                 sstrerror (errno, errbuf, sizeof (errbuf)));
915                 return (NULL);
916         }
917
918         if (S_ISREG (statbuf.st_mode))
919                 return (cf_read_file (path, pattern, depth));
920         else if (S_ISDIR (statbuf.st_mode))
921                 return (cf_read_dir (path, pattern, depth));
922
923         ERROR ("configfile: %s is neither a file nor a directory.", path);
924         return (NULL);
925 } /* oconfig_item_t *cf_read_generic */
926 #endif /* !HAVE_WORDEXP_H */
927
928 /*
929  * Public functions
930  */
931 int global_option_set (const char *option, const char *value, _Bool from_cli)
932 {
933         int i;
934
935         DEBUG ("option = %s; value = %s;", option, value);
936
937         for (i = 0; i < cf_global_options_num; i++)
938                 if (strcasecmp (cf_global_options[i].key, option) == 0)
939                         break;
940
941         if (i >= cf_global_options_num)
942                 return (-1);
943
944         if (cf_global_options[i].from_cli && (! from_cli))
945         {
946                 DEBUG ("Configfile: Ignoring %s `%s' option because "
947                                 "it was overriden by a command-line option.",
948                                 option, value);
949                 return (0);
950         }
951
952         sfree (cf_global_options[i].value);
953
954         if (value != NULL)
955                 cf_global_options[i].value = strdup (value);
956         else
957                 cf_global_options[i].value = NULL;
958
959         cf_global_options[i].from_cli = from_cli;
960
961         return (0);
962 }
963
964 const char *global_option_get (const char *option)
965 {
966         int i;
967
968         for (i = 0; i < cf_global_options_num; i++)
969                 if (strcasecmp (cf_global_options[i].key, option) == 0)
970                         break;
971
972         if (i >= cf_global_options_num)
973                 return (NULL);
974
975         return ((cf_global_options[i].value != NULL)
976                         ? cf_global_options[i].value
977                         : cf_global_options[i].def);
978 } /* char *global_option_get */
979
980 long global_option_get_long (const char *option, long default_value)
981 {
982         const char *str;
983         long value;
984
985         str = global_option_get (option);
986         if (NULL == str)
987                 return (default_value);
988
989         errno = 0;
990         value = strtol (str, /* endptr = */ NULL, /* base = */ 0);
991         if (errno != 0)
992                 return (default_value);
993
994         return (value);
995 } /* char *global_option_get_long */
996
997 cdtime_t global_option_get_time (const char *name, cdtime_t def) /* {{{ */
998 {
999         char const *optstr;
1000         char *endptr = NULL;
1001         double v;
1002
1003         optstr = global_option_get (name);
1004         if (optstr == NULL)
1005                 return (def);
1006
1007         errno = 0;
1008         v = strtod (optstr, &endptr);
1009         if ((endptr == NULL) || (*endptr != 0) || (errno != 0))
1010                 return (def);
1011         else if (v <= 0.0)
1012                 return (def);
1013
1014         return (DOUBLE_TO_CDTIME_T (v));
1015 } /* }}} cdtime_t global_option_get_time */
1016
1017 cdtime_t cf_get_default_interval (void)
1018 {
1019         return (global_option_get_time ("Interval",
1020                                DOUBLE_TO_CDTIME_T (COLLECTD_DEFAULT_INTERVAL)));
1021 }
1022
1023 void cf_unregister (const char *type)
1024 {
1025         cf_callback_t *this, *prev;
1026
1027         for (prev = NULL, this = first_callback;
1028                         this != NULL;
1029                         prev = this, this = this->next)
1030                 if (strcasecmp (this->type, type) == 0)
1031                 {
1032                         if (prev == NULL)
1033                                 first_callback = this->next;
1034                         else
1035                                 prev->next = this->next;
1036
1037                         free (this);
1038                         break;
1039                 }
1040 } /* void cf_unregister */
1041
1042 void cf_unregister_complex (const char *type)
1043 {
1044         cf_complex_callback_t *this, *prev;
1045
1046         for (prev = NULL, this = complex_callback_head;
1047                         this != NULL;
1048                         prev = this, this = this->next)
1049                 if (strcasecmp (this->type, type) == 0)
1050                 {
1051                         if (prev == NULL)
1052                                 complex_callback_head = this->next;
1053                         else
1054                                 prev->next = this->next;
1055
1056                         sfree (this->type);
1057                         sfree (this);
1058                         break;
1059                 }
1060 } /* void cf_unregister */
1061
1062 void cf_register (const char *type,
1063                 int (*callback) (const char *, const char *),
1064                 const char **keys, int keys_num)
1065 {
1066         cf_callback_t *cf_cb;
1067
1068         /* Remove this module from the list, if it already exists */
1069         cf_unregister (type);
1070
1071         /* This pointer will be free'd in `cf_unregister' */
1072         if ((cf_cb = malloc (sizeof (*cf_cb))) == NULL)
1073                 return;
1074
1075         cf_cb->type     = type;
1076         cf_cb->callback = callback;
1077         cf_cb->keys     = keys;
1078         cf_cb->keys_num = keys_num;
1079         cf_cb->ctx      = plugin_get_ctx ();
1080
1081         cf_cb->next = first_callback;
1082         first_callback = cf_cb;
1083 } /* void cf_register */
1084
1085 int cf_register_complex (const char *type, int (*callback) (oconfig_item_t *))
1086 {
1087         cf_complex_callback_t *new;
1088
1089         new = malloc (sizeof (*new));
1090         if (new == NULL)
1091                 return (-1);
1092
1093         new->type = strdup (type);
1094         if (new->type == NULL)
1095         {
1096                 sfree (new);
1097                 return (-1);
1098         }
1099
1100         new->callback = callback;
1101         new->next = NULL;
1102
1103         new->ctx = plugin_get_ctx ();
1104
1105         if (complex_callback_head == NULL)
1106         {
1107                 complex_callback_head = new;
1108         }
1109         else
1110         {
1111                 cf_complex_callback_t *last = complex_callback_head;
1112                 while (last->next != NULL)
1113                         last = last->next;
1114                 last->next = new;
1115         }
1116
1117         return (0);
1118 } /* int cf_register_complex */
1119
1120 int cf_read (const char *filename)
1121 {
1122         oconfig_item_t *conf;
1123         int i;
1124         int ret = 0;
1125
1126         conf = cf_read_generic (filename, /* pattern = */ NULL, /* depth = */ 0);
1127         if (conf == NULL)
1128         {
1129                 ERROR ("Unable to read config file %s.", filename);
1130                 return (-1);
1131         }
1132         else if (conf->children_num == 0)
1133         {
1134                 ERROR ("Configuration file %s is empty.", filename);
1135                 oconfig_free (conf);
1136                 return (-1);
1137         }
1138
1139         for (i = 0; i < conf->children_num; i++)
1140         {
1141                 if (conf->children[i].children == NULL)
1142                 {
1143                         if (dispatch_value (conf->children + i) != 0)
1144                                 ret = -1;
1145                 }
1146                 else
1147                 {
1148                         if (dispatch_block (conf->children + i) != 0)
1149                                 ret = -1;
1150                 }
1151         }
1152
1153         oconfig_free (conf);
1154
1155         /* Read the default types.db if no `TypesDB' option was given. */
1156         if (cf_default_typesdb)
1157         {
1158                 if (read_types_list (PKGDATADIR"/types.db") != 0)
1159                         ret = -1;
1160         }
1161
1162         return ret;
1163 } /* int cf_read */
1164
1165 /* Assures the config option is a string, duplicates it and returns the copy in
1166  * "ret_string". If necessary "*ret_string" is freed first. Returns zero upon
1167  * success. */
1168 int cf_util_get_string (const oconfig_item_t *ci, char **ret_string) /* {{{ */
1169 {
1170         char *string;
1171
1172         if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
1173         {
1174                 ERROR ("cf_util_get_string: The %s option requires "
1175                                 "exactly one string argument.", ci->key);
1176                 return (-1);
1177         }
1178
1179         string = strdup (ci->values[0].value.string);
1180         if (string == NULL)
1181                 return (-1);
1182
1183         if (*ret_string != NULL)
1184                 sfree (*ret_string);
1185         *ret_string = string;
1186
1187         return (0);
1188 } /* }}} int cf_util_get_string */
1189
1190 /* Assures the config option is a string and copies it to the provided buffer.
1191  * Assures null-termination. */
1192 int cf_util_get_string_buffer (const oconfig_item_t *ci, char *buffer, /* {{{ */
1193                 size_t buffer_size)
1194 {
1195         if ((ci == NULL) || (buffer == NULL) || (buffer_size < 1))
1196                 return (EINVAL);
1197
1198         if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
1199         {
1200                 ERROR ("cf_util_get_string_buffer: The %s option requires "
1201                                 "exactly one string argument.", ci->key);
1202                 return (-1);
1203         }
1204
1205         strncpy (buffer, ci->values[0].value.string, buffer_size);
1206         buffer[buffer_size - 1] = 0;
1207
1208         return (0);
1209 } /* }}} int cf_util_get_string_buffer */
1210
1211 /* Assures the config option is a number and returns it as an int. */
1212 int cf_util_get_int (const oconfig_item_t *ci, int *ret_value) /* {{{ */
1213 {
1214         if ((ci == NULL) || (ret_value == NULL))
1215                 return (EINVAL);
1216
1217         if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
1218         {
1219                 ERROR ("cf_util_get_int: The %s option requires "
1220                                 "exactly one numeric argument.", ci->key);
1221                 return (-1);
1222         }
1223
1224         *ret_value = (int) ci->values[0].value.number;
1225
1226         return (0);
1227 } /* }}} int cf_util_get_int */
1228
1229 int cf_util_get_double (const oconfig_item_t *ci, double *ret_value) /* {{{ */
1230 {
1231         if ((ci == NULL) || (ret_value == NULL))
1232                 return (EINVAL);
1233
1234         if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
1235         {
1236                 ERROR ("cf_util_get_double: The %s option requires "
1237                                 "exactly one numeric argument.", ci->key);
1238                 return (-1);
1239         }
1240
1241         *ret_value = ci->values[0].value.number;
1242
1243         return (0);
1244 } /* }}} int cf_util_get_double */
1245
1246 int cf_util_get_boolean (const oconfig_item_t *ci, _Bool *ret_bool) /* {{{ */
1247 {
1248         if ((ci == NULL) || (ret_bool == NULL))
1249                 return (EINVAL);
1250
1251         if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
1252         {
1253                 ERROR ("cf_util_get_boolean: The %s option requires "
1254                                 "exactly one boolean argument.", ci->key);
1255                 return (-1);
1256         }
1257
1258         *ret_bool = ci->values[0].value.boolean ? 1 : 0;
1259
1260         return (0);
1261 } /* }}} int cf_util_get_boolean */
1262
1263 int cf_util_get_flag (const oconfig_item_t *ci, /* {{{ */
1264                 unsigned int *ret_value, unsigned int flag)
1265 {
1266         int status;
1267         _Bool b;
1268
1269         if (ret_value == NULL)
1270                 return (EINVAL);
1271
1272         b = 0;
1273         status = cf_util_get_boolean (ci, &b);
1274         if (status != 0)
1275                 return (status);
1276
1277         if (b)
1278         {
1279                 *ret_value |= flag;
1280         }
1281         else
1282         {
1283                 *ret_value &= ~flag;
1284         }
1285
1286         return (0);
1287 } /* }}} int cf_util_get_flag */
1288
1289 /* Assures that the config option is a string or a number if the correct range
1290  * of 1-65535. The string is then converted to a port number using
1291  * `service_name_to_port_number' and returned.
1292  * Returns the port number in the range [1-65535] or less than zero upon
1293  * failure. */
1294 int cf_util_get_port_number (const oconfig_item_t *ci) /* {{{ */
1295 {
1296         int tmp;
1297
1298         if ((ci->values_num != 1)
1299                         || ((ci->values[0].type != OCONFIG_TYPE_STRING)
1300                                 && (ci->values[0].type != OCONFIG_TYPE_NUMBER)))
1301         {
1302                 ERROR ("cf_util_get_port_number: The \"%s\" option requires "
1303                                 "exactly one string argument.", ci->key);
1304                 return (-1);
1305         }
1306
1307         if (ci->values[0].type == OCONFIG_TYPE_STRING)
1308                 return (service_name_to_port_number (ci->values[0].value.string));
1309
1310         assert (ci->values[0].type == OCONFIG_TYPE_NUMBER);
1311         tmp = (int) (ci->values[0].value.number + 0.5);
1312         if ((tmp < 1) || (tmp > 65535))
1313         {
1314                 ERROR ("cf_util_get_port_number: The \"%s\" option requires "
1315                                 "a service name or a port number. The number "
1316                                 "you specified, %i, is not in the valid "
1317                                 "range of 1-65535.",
1318                                 ci->key, tmp);
1319                 return (-1);
1320         }
1321
1322         return (tmp);
1323 } /* }}} int cf_util_get_port_number */
1324
1325 int cf_util_get_service (const oconfig_item_t *ci, char **ret_string) /* {{{ */
1326 {
1327         int port;
1328         char *service;
1329         int status;
1330
1331         if (ci->values_num != 1)
1332         {
1333                 ERROR ("cf_util_get_service: The %s option requires exactly "
1334                                 "one argument.", ci->key);
1335                 return (-1);
1336         }
1337
1338         if (ci->values[0].type == OCONFIG_TYPE_STRING)
1339                 return (cf_util_get_string (ci, ret_string));
1340         if (ci->values[0].type != OCONFIG_TYPE_NUMBER)
1341         {
1342                 ERROR ("cf_util_get_service: The %s option requires "
1343                                 "exactly one string or numeric argument.",
1344                                 ci->key);
1345         }
1346
1347         port = 0;
1348         status = cf_util_get_int (ci, &port);
1349         if (status != 0)
1350                 return (status);
1351         else if ((port < 1) || (port > 65535))
1352         {
1353                 ERROR ("cf_util_get_service: The port number given "
1354                                 "for the %s option is out of "
1355                                 "range (%i).", ci->key, port);
1356                 return (-1);
1357         }
1358
1359         service = malloc (6);
1360         if (service == NULL)
1361         {
1362                 ERROR ("cf_util_get_service: Out of memory.");
1363                 return (-1);
1364         }
1365         ssnprintf (service, 6, "%i", port);
1366
1367         sfree (*ret_string);
1368         *ret_string = service;
1369
1370         return (0);
1371 } /* }}} int cf_util_get_service */
1372
1373 int cf_util_get_cdtime (const oconfig_item_t *ci, cdtime_t *ret_value) /* {{{ */
1374 {
1375         if ((ci == NULL) || (ret_value == NULL))
1376                 return (EINVAL);
1377
1378         if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
1379         {
1380                 ERROR ("cf_util_get_cdtime: The %s option requires "
1381                                 "exactly one numeric argument.", ci->key);
1382                 return (-1);
1383         }
1384
1385         if (ci->values[0].value.number < 0.0)
1386         {
1387                 ERROR ("cf_util_get_cdtime: The numeric argument of the %s "
1388                                 "option must not be negative.", ci->key);
1389                 return (-1);
1390         }
1391
1392         *ret_value = DOUBLE_TO_CDTIME_T (ci->values[0].value.number);
1393
1394         return (0);
1395 } /* }}} int cf_util_get_cdtime */
1396