app_confbridge: Fix reference to cfg in menu_template_handler
[asterisk/asterisk.git] / main / config_options.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  * \brief Configuration Option-handling
21  * \author Terry Wilson <twilson@digium.com>
22  */
23
24 /*** MODULEINFO
25         <support_level>core</support_level>
26  ***/
27
28 #include "asterisk.h"
29
30 #include <regex.h>
31
32 #include "asterisk/_private.h"
33 #include "asterisk/config.h"
34 #include "asterisk/config_options.h"
35 #include "asterisk/stringfields.h"
36 #include "asterisk/acl.h"
37 #include "asterisk/frame.h"
38 #include "asterisk/xmldoc.h"
39 #include "asterisk/cli.h"
40 #include "asterisk/term.h"
41 #include "asterisk/format_cap.h"
42
43 #ifdef LOW_MEMORY
44 #define CONFIG_OPT_BUCKETS 5
45 #else
46 #define CONFIG_OPT_BUCKETS 53
47 #endif /* LOW_MEMORY */
48
49 /*! \brief Bits of aco_info that shouldn't be assigned outside this file
50  * \internal
51  */
52 struct aco_info_internal {
53         void *pending;              /*!< The user-defined config object awaiting application */
54 };
55
56 struct aco_type_internal {
57         regex_t *regex;
58         struct ao2_container *opts; /*!< The container of options registered to the aco_info */
59 };
60
61 struct aco_option {
62         const char *name;
63         const char *aliased_to;
64         const char *default_val;
65         enum aco_matchtype match_type;
66         regex_t *name_regex;
67         struct aco_type **obj;
68         enum aco_option_type type;
69         aco_option_handler handler;
70         unsigned int flags;
71         unsigned int no_doc:1;
72 #ifdef AST_DEVMODE
73         unsigned int doc_unavailable:1;
74 #endif
75         unsigned char deprecated:1;
76         size_t argc;
77         intptr_t args[0];
78 };
79
80 #ifdef AST_XML_DOCS
81 static struct ao2_container *xmldocs;
82 #endif /* AST_XML_DOCS */
83
84 /*! \brief Value of the aco_option_type enum as strings */
85 static char *aco_option_type_string[] = {
86         "ACL",                          /* OPT_ACL_T, */
87         "Boolean",                      /* OPT_BOOL_T, */
88         "Boolean",                      /* OPT_BOOLFLAG_T, */
89         "String",                       /* OPT_CHAR_ARRAY_T, */
90         "Codec",                        /* OPT_CODEC_T, */
91         "Custom",                       /* OPT_CUSTOM_T, */
92         "Double",                       /* OPT_DOUBLE_T, */
93         "Integer",                      /* OPT_INT_T, */
94         "None",                         /* OPT_NOOP_T, */
95         "IP Address",           /* OPT_SOCKADDR_T, */
96         "String",                       /* OPT_STRINGFIELD_T, */
97         "Unsigned Integer",     /* OPT_UINT_T, */
98         "Boolean",                      /* OPT_YESNO_T, */
99 };
100
101 void *aco_pending_config(struct aco_info *info)
102 {
103         if (!(info && info->internal)) {
104                 ast_log(LOG_ERROR, "This may not be called without an initialized aco_info!\n");
105                 return NULL;
106         }
107         return info->internal->pending;
108 }
109
110 static void config_option_destroy(void *obj)
111 {
112         struct aco_option *opt = obj;
113         if (opt->match_type == ACO_REGEX && opt->name_regex) {
114                 regfree(opt->name_regex);
115                 ast_free(opt->name_regex);
116         }
117 }
118
119 static int int_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
120 static int uint_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
121 static int double_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
122 static int sockaddr_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
123 static int stringfield_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
124 static int bool_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
125 static int boolflag_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
126 static int acl_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
127 static int codec_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
128 static int noop_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
129 static int chararray_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj);
130
131 #ifdef AST_XML_DOCS
132 static int xmldoc_update_config_type(const char *module, const char *name, const char *category, const char *matchfield, const char *matchvalue, unsigned int matches);
133 static int xmldoc_update_config_option(struct aco_type **types, const char *module, const char *name, const char *object_name, const char *default_value, unsigned int regex, enum aco_option_type type);
134 #endif
135
136 static aco_option_handler ast_config_option_default_handler(enum aco_option_type type)
137 {
138         switch(type) {
139         case OPT_ACL_T: return acl_handler_fn;
140         case OPT_BOOL_T: return bool_handler_fn;
141         /* Reading from config files, BOOL and YESNO are handled exactly the
142          * same. Their difference is in how they are rendered to users
143          */
144         case OPT_YESNO_T: return bool_handler_fn;
145         case OPT_BOOLFLAG_T: return boolflag_handler_fn;
146         case OPT_CHAR_ARRAY_T: return chararray_handler_fn;
147         case OPT_CODEC_T: return codec_handler_fn;
148         case OPT_DOUBLE_T: return double_handler_fn;
149         case OPT_INT_T: return int_handler_fn;
150         case OPT_NOOP_T: return noop_handler_fn;
151         case OPT_SOCKADDR_T: return sockaddr_handler_fn;
152         case OPT_STRINGFIELD_T: return stringfield_handler_fn;
153         case OPT_UINT_T: return uint_handler_fn;
154
155         case OPT_CUSTOM_T: return NULL;
156         }
157
158         return NULL;
159 }
160
161 static regex_t *build_regex(const char *text)
162 {
163         int res;
164         regex_t *regex;
165
166         if (!(regex = ast_malloc(sizeof(*regex)))) {
167                 return NULL;
168         }
169
170         if ((res = regcomp(regex, text, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
171                 size_t len = regerror(res, regex, NULL, 0);
172                 char buf[len];
173                 regerror(res, regex, buf, len);
174                 ast_log(LOG_ERROR, "Could not compile regex '%s': %s\n", text, buf);
175                 ast_free(regex);
176                 return NULL;
177         }
178
179         return regex;
180 }
181
182 static int link_option_to_types(struct aco_info *info, struct aco_type **types, struct aco_option *opt)
183 {
184         size_t idx = 0;
185         struct aco_type *type;
186
187         while ((type = types[idx++])) {
188                 if (!type->internal) {
189                         ast_log(LOG_ERROR, "Attempting to register option using uninitialized type\n");
190                         return -1;
191                 }
192                 if (!ao2_link(type->internal->opts, opt)) {
193                         do {
194                                 ao2_unlink(types[idx - 1]->internal->opts, opt);
195                         } while (--idx);
196                         return -1;
197                 }
198 #ifdef AST_XML_DOCS
199                 if (!info->hidden && !opt->no_doc &&
200                         xmldoc_update_config_option(types, info->module, opt->name, type->name, opt->default_val, opt->match_type == ACO_REGEX, opt->type)) {
201 #ifdef AST_DEVMODE
202                         opt->doc_unavailable = 1;
203 #endif
204                 }
205 #endif
206         }
207         /* The container(s) should hold the only ref to opt */
208         ao2_ref(opt, -1);
209
210         return 0;
211 }
212
213 int aco_option_register_deprecated(struct aco_info *info, const char *name, struct aco_type **types, const char *aliased_to)
214 {
215         struct aco_option *opt;
216
217         if (!info || ast_strlen_zero(name) || ast_strlen_zero(aliased_to)) {
218                 return -1;
219         }
220
221         if (!(opt = ao2_alloc(sizeof(*opt), config_option_destroy))) {
222                 return -1;
223         }
224
225         opt->name = name;
226         opt->aliased_to = aliased_to;
227         opt->deprecated = 1;
228         opt->match_type = ACO_EXACT;
229
230         if (link_option_to_types(info, types, opt)) {
231                 ao2_ref(opt, -1);
232                 return -1;
233         }
234
235         return 0;
236 }
237
238 unsigned int aco_option_get_flags(const struct aco_option *option)
239 {
240         return option->flags;
241 }
242
243 intptr_t aco_option_get_argument(const struct aco_option *option, unsigned int position)
244 {
245         return option->args[position];
246 }
247
248 #ifdef AST_XML_DOCS
249 /*! \internal
250  * \brief Find a particular ast_xml_doc_item from it's parent config_info, types, and name
251  */
252 static struct ast_xml_doc_item *find_xmldoc_option(struct ast_xml_doc_item *config_info, struct aco_type **types, const char *name)
253 {
254         struct ast_xml_doc_item *iter = config_info;
255
256         if (!iter) {
257                 return NULL;
258         }
259         /* First is just the configInfo, we can skip it */
260         while ((iter = AST_LIST_NEXT(iter, next))) {
261                 size_t x;
262                 if (strcasecmp(iter->name, name)) {
263                         continue;
264                 }
265                 for (x = 0; types[x]; x++) {
266                         /* All we care about is that at least one type has the option */
267                         if (!strcasecmp(types[x]->name, iter->ref)) {
268                                 return iter;
269                         }
270                 }
271         }
272         return NULL;
273 }
274
275 /*! \internal
276  * \brief Find a particular ast_xml_doc_item from it's parent config_info and name
277  */
278 static struct ast_xml_doc_item *find_xmldoc_type(struct ast_xml_doc_item *config_info, const char *name)
279 {
280         struct ast_xml_doc_item *iter = config_info;
281         if (!iter) {
282                 return NULL;
283         }
284         /* First is just the config Info, skip it */
285         while ((iter = AST_LIST_NEXT(iter, next))) {
286                 if (!strcasecmp(iter->type, "configObject") && !strcasecmp(iter->name, name)) {
287                         break;
288                 }
289         }
290         return iter;
291 }
292
293 #endif /* AST_XML_DOCS */
294
295 int __aco_option_register(struct aco_info *info, const char *name, enum aco_matchtype matchtype, struct aco_type **types,
296         const char *default_val, enum aco_option_type kind, aco_option_handler handler, unsigned int flags,
297         unsigned int no_doc, size_t argc, ...)
298 {
299         struct aco_option *opt;
300         va_list ap;
301         int tmp;
302
303         /* Custom option types require a handler */
304         if (!handler && kind == OPT_CUSTOM_T) {
305                 return -1;
306         }
307
308         if (!(types && types[0])) {
309                 return -1;
310         }
311
312         if (!(opt = ao2_alloc(sizeof(*opt) + argc * sizeof(opt->args[0]), config_option_destroy))) {
313                 return -1;
314         }
315
316         if (matchtype == ACO_REGEX && !(opt->name_regex = build_regex(name))) {
317                 ao2_ref(opt, -1);
318                 return -1;
319         }
320
321         va_start(ap, argc);
322         for (tmp = 0; tmp < argc; tmp++) {
323                 opt->args[tmp] = va_arg(ap, size_t);
324         }
325         va_end(ap);
326
327         opt->name = name;
328         opt->match_type = matchtype;
329         opt->default_val = default_val;
330         opt->type = kind;
331         opt->handler = handler;
332         opt->flags = flags;
333         opt->argc = argc;
334         opt->no_doc = no_doc;
335
336         if (!opt->handler && !(opt->handler = ast_config_option_default_handler(opt->type))) {
337                 /* This should never happen */
338                 ast_log(LOG_ERROR, "No handler provided, and no default handler exists for type %u\n", opt->type);
339                 ao2_ref(opt, -1);
340                 return -1;
341         };
342
343         if (link_option_to_types(info, types, opt)) {
344                 ao2_ref(opt, -1);
345                 return -1;
346         }
347
348         return 0;
349 }
350
351 static int config_opt_hash(const void *obj, const int flags)
352 {
353         const struct aco_option *opt = obj;
354         const char *name = (flags & OBJ_KEY) ? obj : opt->name;
355         return ast_str_case_hash(name);
356 }
357
358 static int config_opt_cmp(void *obj, void *arg, int flags)
359 {
360         struct aco_option *opt1 = obj, *opt2 = arg;
361         const char *name = (flags & OBJ_KEY) ? arg : opt2->name;
362         return strcasecmp(opt1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
363 }
364
365 static int find_option_cb(void *obj, void *arg, int flags)
366 {
367         struct aco_option *match = obj;
368         const char *name = arg;
369
370         switch (match->match_type) {
371         case ACO_EXACT:
372                 return strcasecmp(name, match->name) ? 0 : CMP_MATCH | CMP_STOP;
373         case ACO_REGEX:
374                 return regexec(match->name_regex, name, 0, NULL, 0) ? 0 : CMP_MATCH | CMP_STOP;
375         }
376         ast_log(LOG_ERROR, "Unknown match type. This should not be possible.\n");
377         return CMP_STOP;
378 }
379
380 static struct aco_option *aco_option_find(struct aco_type *type, const char *name)
381 {
382         struct aco_option *opt;
383
384         if (!type || !type->internal || !type->internal->opts) {
385                 ast_log(LOG_NOTICE, "Attempting to use NULL or unitialized config type\n");
386                 return NULL;
387         }
388
389         /* Try an exact match with OBJ_KEY for the common/fast case, then iterate through
390          * all options for the regex cases */
391         if (!(opt = ao2_callback(type->internal->opts, OBJ_KEY, find_option_cb, (void *) name))) {
392                 opt = ao2_callback(type->internal->opts, 0, find_option_cb, (void *) name);
393         }
394         return opt;
395 }
396
397 struct ao2_container *aco_option_container_alloc(void)
398 {
399         return ao2_container_alloc(CONFIG_OPT_BUCKETS, config_opt_hash, config_opt_cmp);
400 }
401
402 static struct aco_type *internal_aco_type_find(struct aco_file *file, struct ast_config *cfg, const char *category)
403 {
404         size_t x;
405         struct aco_type *match;
406         const char *val;
407
408         for (x = 0, match = file->types[x]; match; match = file->types[++x]) {
409                 /* First make sure we are an object that can service this category */
410                 if (!regexec(match->internal->regex, category, 0, NULL, 0) == !match->category_match) {
411                         continue;
412                 }
413
414                 /* Then, see if we need to match a particular field */
415                 if (!ast_strlen_zero(match->matchfield) && (!ast_strlen_zero(match->matchvalue) || match->matchfunc)) {
416                         if (!(val = ast_variable_retrieve(cfg, category, match->matchfield))) {
417                                 ast_log(LOG_ERROR, "Required match field '%s' not found\n", match->matchfield);
418                                 return NULL;
419                         }
420                         if (match->matchfunc) {
421                                 if (!match->matchfunc(val)) {
422                                         continue;
423                                 }
424                         } else if (strcasecmp(val, match->matchvalue)) {
425                                 continue;
426                         }
427                 }
428                 /* If we get this far, we're a match */
429                 break;
430         }
431
432         return match;
433 }
434
435 static int is_preload(struct aco_file *file, const char *cat)
436 {
437         int i;
438
439         if (!file->preload) {
440                 return 0;
441         }
442
443         for (i = 0; !ast_strlen_zero(file->preload[i]); i++) {
444                 if (!strcasecmp(cat, file->preload[i])) {
445                         return 1;
446                 }
447         }
448         return 0;
449 }
450
451 static int process_category(struct ast_config *cfg, struct aco_info *info, struct aco_file *file, const char *cat, int preload) {
452         RAII_VAR(void *, new_item, NULL, ao2_cleanup);
453         struct aco_type *type;
454         /* For global types, field is the global option struct. For non-global, it is the container for items.
455          * We do not grab a reference to these objects, as the info already holds references to them. This
456          * pointer is just a convenience. Do not actually store it somewhere. */
457         void **field;
458         regex_t *regex_skip;
459
460         /* Skip preloaded categories if we aren't preloading */
461         if (!preload && is_preload(file, cat)) {
462                 return 0;
463         }
464
465         /* Skip the category if we've been told to ignore it */
466         if (!ast_strlen_zero(file->skip_category)) {
467                 regex_skip = build_regex(file->skip_category);
468                 if (!regexec(regex_skip, cat, 0, NULL, 0)) {
469                         regfree(regex_skip);
470                         ast_free(regex_skip);
471                         return 0;
472                 }
473                 regfree(regex_skip);
474                 ast_free(regex_skip);
475         }
476
477         /* Find aco_type by category, if not found it is an error */
478         if (!(type = internal_aco_type_find(file, cfg, cat))) {
479                 ast_log(LOG_ERROR, "Could not find config type for category '%s' in '%s'\n", cat, file->filename);
480                 return -1;
481         }
482
483         field = info->internal->pending + type->item_offset;
484         if (!*field) {
485                 ast_log(LOG_ERROR, "In %s: %s - No object to update!\n", file->filename, cat);
486                 return -1;
487         }
488
489         if (type->type == ACO_GLOBAL && *field) {
490                 if (aco_process_category_options(type, cfg, cat, *field)) {
491                         ast_log(LOG_ERROR, "In %s: Processing options for %s failed\n", file->filename, cat);
492                         return -1;
493                 }
494         } else if (type->type == ACO_ITEM) {
495                 int new = 0;
496                 /* If we have multiple definitions of a category in a file, or can set the values from multiple
497                  * files, look up the entry if we've already added it so we can merge the values together.
498                  * Otherwise, alloc a new item. */
499                 if (*field) {
500                         if (!(new_item = type->item_find(*field, cat))) {
501                                 if (!(new_item = type->item_alloc(cat))) {
502                                         ast_log(LOG_ERROR, "In %s: Could not create item for %s\n", file->filename, cat);
503                                         return -1;
504                                 }
505                                 if (aco_set_defaults(type, cat, new_item)) {
506                                         ast_log(LOG_ERROR, "In %s: Setting defaults for %s failed\n", file->filename, cat);
507                                         return -1;
508                                 }
509                                 new = 1;
510                         }
511                 }
512
513                 if (type->item_pre_process && type->item_pre_process(new_item)) {
514                         ast_log(LOG_ERROR, "In %s: Preprocess callback for %s failed\n", file->filename, cat);
515                         return -1;
516                 }
517
518                 if (aco_process_category_options(type, cfg, cat, new_item)) {
519                         ast_log(LOG_ERROR, "In %s: Processing options for %s failed\n", file->filename, cat);
520                         return -1;
521                 }
522
523                 if (type->item_prelink && type->item_prelink(new_item)) {
524                         ast_log(LOG_ERROR, "In %s: Pre-link callback for %s failed\n", file->filename, cat);
525                         return -1;
526                 }
527
528                 if (new && !ao2_link(*field, new_item)) {
529                         ast_log(LOG_ERROR, "In %s: Linking config for %s failed\n", file->filename, cat);
530                         return -1;
531                 }
532         }
533         return 0;
534 }
535
536 static int apply_config(struct aco_info *info)
537 {
538         ao2_global_obj_replace_unref(*info->global_obj, info->internal->pending);
539
540         return 0;
541 }
542
543 static enum aco_process_status internal_process_ast_config(struct aco_info *info, struct aco_file *file, struct ast_config *cfg)
544 {
545         const char *cat = NULL;
546
547         if (file->preload) {
548                 int i;
549                 for (i = 0; !ast_strlen_zero(file->preload[i]); i++) {
550                         if (process_category(cfg, info, file, file->preload[i], 1)) {
551                                 return ACO_PROCESS_ERROR;
552                         }
553                 }
554         }
555
556         while ((cat = ast_category_browse(cfg, cat))) {
557                 if (process_category(cfg, info, file, cat, 0)) {
558                         return ACO_PROCESS_ERROR;
559                 }
560         }
561         return ACO_PROCESS_OK;
562 }
563
564 enum aco_process_status aco_process_ast_config(struct aco_info *info, struct aco_file *file, struct ast_config *cfg)
565 {
566         if (!info->internal) {
567                 ast_log(LOG_ERROR, "Attempt to process %s with uninitialized aco_info\n", file->filename);
568                 goto error;
569         }
570
571         if (!(info->internal->pending = info->snapshot_alloc())) {
572                 ast_log(LOG_ERROR, "In %s: Could not allocate temporary objects\n", file->filename);
573                 goto error;
574         }
575
576         if (internal_process_ast_config(info, file, cfg)) {
577                 goto error;
578         }
579
580         if (info->pre_apply_config && info->pre_apply_config()) {
581                 goto error;
582         }
583
584         if (apply_config(info)) {
585                 goto error;
586         };
587
588         ao2_cleanup(info->internal->pending);
589         info->internal->pending = NULL;
590         return ACO_PROCESS_OK;
591
592 error:
593         ao2_cleanup(info->internal->pending);
594         info->internal->pending = NULL;
595
596         return ACO_PROCESS_ERROR;
597 }
598
599 enum aco_process_status aco_process_config(struct aco_info *info, int reload)
600 {
601         struct ast_config *cfg;
602         struct ast_flags cfg_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0, };
603         int res = ACO_PROCESS_OK;
604         int file_count = 0;
605         struct aco_file *file;
606
607         if (!info->internal) {
608                 ast_log(LOG_ERROR, "Attempting to process uninitialized aco_info\n");
609                 return ACO_PROCESS_ERROR;
610         }
611
612         if (!(info->files[0])) {
613                 ast_log(LOG_ERROR, "No filename given, cannot proceed!\n");
614                 return ACO_PROCESS_ERROR;
615         }
616
617         if (!(info->internal->pending = info->snapshot_alloc())) {
618                 ast_log(LOG_ERROR, "In %s: Could not allocate temporary objects\n", info->module);
619                 return ACO_PROCESS_ERROR;
620         }
621
622         while (res != ACO_PROCESS_ERROR && (file = info->files[file_count++])) {
623                 const char *filename = file->filename;
624                 struct aco_type *match;
625                 int i;
626
627                 /* set defaults for global objects */
628                 for (i = 0, match = file->types[i]; match; match = file->types[++i]) {
629                         void **field = info->internal->pending + match->item_offset;
630
631                         if (match->type != ACO_GLOBAL || !*field) {
632                                 continue;
633                         }
634
635                         if (aco_set_defaults(match, match->category, *field)) {
636                                 ast_log(LOG_ERROR, "In %s: Setting defaults for %s failed\n", file->filename, match->category);
637                                 res = ACO_PROCESS_ERROR;
638                                 break;
639                         }
640                 }
641
642                 if (res == ACO_PROCESS_ERROR) {
643                         break;
644                 }
645
646 try_alias:
647                 cfg = ast_config_load(filename, cfg_flags);
648                 if (!cfg || cfg == CONFIG_STATUS_FILEMISSING) {
649                         if (file->alias && strcmp(file->alias, filename)) {
650                                 filename = file->alias;
651                                 goto try_alias;
652                         }
653                         ast_log(LOG_ERROR, "Unable to load config file '%s'\n", file->filename);
654                         res = ACO_PROCESS_ERROR;
655                         break;
656                 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
657                         ast_debug(1, "%s was unchanged\n", file->filename);
658                         res = ACO_PROCESS_UNCHANGED;
659                         continue;
660                 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
661                         ast_log(LOG_ERROR, "Contents of %s are invalid and cannot be parsed\n",
662                                 file->filename);
663                         res = ACO_PROCESS_ERROR;
664                         break;
665                 }
666
667                 /* A file got loaded. */
668                 if (reload) {
669                         /* Must do any subsequent file loads unconditionally. */
670                         reload = 0;
671                         ast_clear_flag(&cfg_flags, CONFIG_FLAG_FILEUNCHANGED);
672
673                         if (file_count != 1) {
674                                 /*
675                                  * Must restart loading to load all config files since a file
676                                  * after the first one changed.
677                                  */
678                                 file_count = 0;
679                         } else {
680                                 res = internal_process_ast_config(info, file, cfg);
681                         }
682                 } else {
683                         res = internal_process_ast_config(info, file, cfg);
684                 }
685                 ast_config_destroy(cfg);
686         }
687
688         if (res != ACO_PROCESS_OK) {
689                 goto end;
690         }
691
692         if (info->pre_apply_config && info->pre_apply_config()) {
693                 res = ACO_PROCESS_ERROR;
694                 goto end;
695         }
696
697         if (apply_config(info)) {
698                 res = ACO_PROCESS_ERROR;
699                 goto end;
700         }
701
702         if (info->post_apply_config) {
703                 info->post_apply_config();
704         }
705
706 end:
707         ao2_cleanup(info->internal->pending);
708         info->internal->pending = NULL;
709
710         return res;
711 }
712 int aco_process_var(struct aco_type *type, const char *cat, struct ast_variable *var, void *obj)
713 {
714         RAII_VAR(struct aco_option *, opt, aco_option_find(type, var->name), ao2_cleanup);
715         if (opt && opt->deprecated && !ast_strlen_zero(opt->aliased_to)) {
716                 const char *alias = ast_strdupa(opt->aliased_to);
717                 ast_log(LOG_WARNING, "At line %d of %s option '%s' is deprecated. Use '%s' instead\n", var->lineno, var->file, var->name, alias);
718                 ao2_ref(opt, -1);
719                 opt = aco_option_find(type, alias);
720         }
721
722         if (!opt) {
723                 ast_log(LOG_ERROR, "Could not find option suitable for category '%s' named '%s' at line %d of %s\n", cat, var->name, var->lineno, var->file);
724                 return -1;
725         }
726
727         if (!opt->handler) {
728                 /* It should be impossible for an option to not have a handler */
729                 ast_log(LOG_ERROR, "BUG! Somehow a config option for %s/%s was created with no handler!\n", cat, var->name);
730                 return -1;
731         }
732
733 #ifdef AST_DEVMODE
734         if (opt->doc_unavailable) {
735                 ast_log(LOG_ERROR, "Config option '%s' of type '%s' is not completely documented and can not be set\n", var->name, type->name);
736                 return -1;
737         }
738 #endif
739
740         if (opt->handler(opt, var, obj)) {
741                 ast_log(LOG_ERROR, "Error parsing %s=%s at line %d of %s\n", var->name, var->value, var->lineno, var->file);
742                 return -1;
743         }
744
745         return 0;
746 }
747
748 int aco_process_category_options(struct aco_type *type, struct ast_config *cfg, const char *cat, void *obj)
749 {
750         struct ast_variable *var;
751
752         for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
753                 if (aco_process_var(type, cat, var, obj)) {
754                         return -1;
755                 }
756         }
757
758         return 0;
759 }
760
761 static void internal_type_destroy(struct aco_type *type)
762 {
763         /* If we've already had all our internal data cleared out,
764          * then there's no need to proceed further
765          */
766         if (!type->internal) {
767                 return;
768         }
769
770         if (type->internal->regex) {
771                 regfree(type->internal->regex);
772                 ast_free(type->internal->regex);
773         }
774         ao2_cleanup(type->internal->opts);
775         type->internal->opts = NULL;
776         ast_free(type->internal);
777         type->internal = NULL;
778 }
779
780 static void internal_file_types_destroy(struct aco_file *file)
781 {
782         size_t x;
783         struct aco_type *t;
784
785         for (x = 0, t = file->types[x]; t; t = file->types[++x]) {
786                 internal_type_destroy(t);
787                 t = NULL;
788         }
789 }
790
791 static int internal_type_init(struct aco_type *type)
792 {
793         if (!(type->internal = ast_calloc(1, sizeof(*type->internal)))) {
794                 return -1;
795         }
796
797         if (!(type->internal->regex = build_regex(type->category))) {
798                 internal_type_destroy(type);
799                 return -1;
800         }
801
802         if (!(type->internal->opts = aco_option_container_alloc())) {
803                 internal_type_destroy(type);
804                 return -1;
805         }
806
807         return 0;
808 }
809
810 int aco_info_init(struct aco_info *info)
811 {
812         size_t x = 0, y = 0;
813         struct aco_file *file;
814         struct aco_type *type;
815
816         if (!(info->internal = ast_calloc(1, sizeof(*info->internal)))) {
817                 return -1;
818         }
819
820         while ((file = info->files[x++])) {
821                 while ((type = file->types[y++])) {
822                         if (internal_type_init(type)) {
823                                 goto error;
824                         }
825 #ifdef AST_XML_DOCS
826                         if (!info->hidden &&
827                                 !type->hidden &&
828                                 xmldoc_update_config_type(info->module, type->name, type->category, type->matchfield, type->matchvalue, type->category_match == ACO_WHITELIST)) {
829                                 goto error;
830                         }
831 #endif /* AST_XML_DOCS */
832                 }
833                 y = 0;
834         }
835
836         return 0;
837 error:
838         aco_info_destroy(info);
839         return -1;
840 }
841
842 void aco_info_destroy(struct aco_info *info)
843 {
844         int x;
845         /* It shouldn't be possible for internal->pending to be in use when this is called because
846          * of the locks in loader.c around reloads and unloads and the fact that internal->pending
847          * only exists while those locks are held */
848         ast_free(info->internal);
849         info->internal = NULL;
850
851         for (x = 0; info->files[x]; x++) {
852                 internal_file_types_destroy(info->files[x]);
853         }
854 }
855
856 int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
857 {
858         struct aco_option *opt;
859         struct ao2_iterator iter;
860
861         if (!type->internal) {
862                 return -1;
863         }
864
865         iter = ao2_iterator_init(type->internal->opts, 0);
866
867         while ((opt = ao2_iterator_next(&iter))) {
868                 RAII_VAR(struct ast_variable *, var, NULL, ast_variables_destroy);
869
870                 if (ast_strlen_zero(opt->default_val)) {
871                         ao2_ref(opt, -1);
872                         continue;
873                 }
874                 if (!(var = ast_variable_new(opt->name, opt->default_val, ""))) {
875                         ao2_ref(opt, -1);
876                         ao2_iterator_destroy(&iter);
877                         return -1;
878                 }
879                 if (opt->handler(opt, var, obj)) {
880                         ast_log(LOG_ERROR, "Unable to set default for %s, %s=%s\n", category, var->name, var->value);
881                         ao2_ref(opt, -1);
882                         ao2_iterator_destroy(&iter);
883                         return -1;
884                 }
885                 ao2_ref(opt, -1);
886         }
887         ao2_iterator_destroy(&iter);
888
889         return 0;
890 }
891
892 #ifdef AST_XML_DOCS
893
894 /*! \internal
895  * \brief Complete the name of the module the user is looking for
896  */
897 static char *complete_config_module(const char *word, int pos, int state)
898 {
899         char *c = NULL;
900         size_t wordlen = strlen(word);
901         int which = 0;
902         struct ao2_iterator i;
903         struct ast_xml_doc_item *cur;
904
905         if (pos != 3) {
906                 return NULL;
907         }
908
909         i = ao2_iterator_init(xmldocs, 0);
910         while ((cur = ao2_iterator_next(&i))) {
911                 if (!strncasecmp(word, cur->name, wordlen) && ++which > state) {
912                         c = ast_strdup(cur->name);
913                         ao2_ref(cur, -1);
914                         break;
915                 }
916                 ao2_ref(cur, -1);
917         }
918         ao2_iterator_destroy(&i);
919
920         return c;
921 }
922
923 /*! \internal
924  * \brief Complete the name of the configuration type the user is looking for
925  */
926 static char *complete_config_type(const char *module, const char *word, int pos, int state)
927 {
928         char *c = NULL;
929         size_t wordlen = strlen(word);
930         int which = 0;
931         RAII_VAR(struct ast_xml_doc_item *, info, NULL, ao2_cleanup);
932         struct ast_xml_doc_item *cur;
933
934         if (pos != 4) {
935                 return NULL;
936         }
937
938         if (!(info = ao2_find(xmldocs, module, OBJ_KEY))) {
939                 return NULL;
940         }
941
942         cur = info;
943         while ((cur = AST_LIST_NEXT(cur, next))) {
944                 if (!strcasecmp(cur->type, "configObject") && !strncasecmp(word, cur->name, wordlen) && ++which > state) {
945                         c = ast_strdup(cur->name);
946                         break;
947                 }
948         }
949         return c;
950 }
951
952 /*! \internal
953  * \brief Complete the name of the configuration option the user is looking for
954  */
955 static char *complete_config_option(const char *module, const char *option, const char *word, int pos, int state)
956 {
957         char *c = NULL;
958         size_t wordlen = strlen(word);
959         int which = 0;
960         RAII_VAR(struct ast_xml_doc_item *, info, NULL, ao2_cleanup);
961         struct ast_xml_doc_item *cur;
962
963         if (pos != 5) {
964                 return NULL;
965         }
966
967         if (!(info = ao2_find(xmldocs, module, OBJ_KEY))) {
968                 return NULL;
969         }
970
971         cur = info;
972         while ((cur = AST_LIST_NEXT(cur, next))) {
973                 if (!strcasecmp(cur->type, "configOption") && !strcasecmp(cur->ref, option) && !strncasecmp(word, cur->name, wordlen) && ++which > state) {
974                         c = ast_strdup(cur->name);
975                         break;
976                 }
977         }
978         return c;
979 }
980
981 /* Define as 0 if we want to allow configurations to be registered without
982  * documentation
983  */
984 #define XMLDOC_STRICT 1
985
986 /*! \internal
987  * \brief Update the XML documentation for a config type based on its registration
988  */
989 static int xmldoc_update_config_type(const char *module, const char *name, const char *category, const char *matchfield, const char *matchvalue, unsigned int matches)
990 {
991         RAII_VAR(struct ast_xml_xpath_results *, results, NULL, ast_xml_xpath_results_free);
992         RAII_VAR(struct ast_xml_doc_item *, config_info, ao2_find(xmldocs, module, OBJ_KEY), ao2_cleanup);
993         struct ast_xml_doc_item *config_type;
994         struct ast_xml_node *type, *syntax, *matchinfo, *tmp;
995
996         /* If we already have a syntax element, bail. This isn't an error, since we may unload a module which
997          * has updated the docs and then load it again. */
998         if ((results = ast_xmldoc_query("//configInfo[@name='%s']/*/configObject[@name='%s']/syntax", module, name))) {
999                 return 0;
1000         }
1001
1002         if (!(results = ast_xmldoc_query("//configInfo[@name='%s']/*/configObject[@name='%s']", module, name))) {
1003                 ast_log(LOG_WARNING, "Cannot update type '%s' in module '%s' because it has no existing documentation!\n", name, module);
1004                 return XMLDOC_STRICT ? -1 : 0;
1005         }
1006
1007         if (!(type = ast_xml_xpath_get_first_result(results))) {
1008                 ast_log(LOG_WARNING, "Could not retrieve documentation for type '%s' in module '%s'\n", name, module);
1009                 return XMLDOC_STRICT ? -1 : 0;
1010         }
1011
1012         if (!(syntax = ast_xml_new_child(type, "syntax"))) {
1013                 ast_log(LOG_WARNING, "Could not create syntax node for type '%s' in module '%s'\n", name, module);
1014                 return XMLDOC_STRICT ? -1 : 0;
1015         }
1016
1017         if (!(matchinfo = ast_xml_new_child(syntax, "matchInfo"))) {
1018                 ast_log(LOG_WARNING, "Could not create matchInfo node for type '%s' in module '%s'\n", name, module);
1019                 return XMLDOC_STRICT ? -1 : 0;
1020         }
1021
1022         if (!(tmp = ast_xml_new_child(matchinfo, "category"))) {
1023                 ast_log(LOG_WARNING, "Could not create category node for type '%s' in module '%s'\n", name, module);
1024                 return XMLDOC_STRICT ? -1 : 0;
1025         }
1026
1027         ast_xml_set_text(tmp, category);
1028         ast_xml_set_attribute(tmp, "match", matches ? "true" : "false");
1029
1030         if (!ast_strlen_zero(matchfield) && !(tmp = ast_xml_new_child(matchinfo, "field"))) {
1031                 ast_log(LOG_WARNING, "Could not add %s attribute for type '%s' in module '%s'\n", matchfield, name, module);
1032                 return XMLDOC_STRICT ? -1 : 0;
1033         }
1034
1035         ast_xml_set_attribute(tmp, "name", matchfield);
1036         ast_xml_set_text(tmp, matchvalue);
1037
1038         if (!config_info || !(config_type = find_xmldoc_type(config_info, name))) {
1039                 ast_log(LOG_WARNING, "Could not obtain XML documentation item for config type %s\n", name);
1040                 return XMLDOC_STRICT ? -1 : 0;
1041         }
1042
1043         if (ast_xmldoc_regenerate_doc_item(config_type)) {
1044                 ast_log(LOG_WARNING, "Could not update type '%s' with values from config type registration\n", name);
1045                 return XMLDOC_STRICT ? -1 : 0;
1046         }
1047
1048         return 0;
1049 }
1050
1051 /*! \internal
1052  * \brief Update the XML documentation for a config option based on its registration
1053  */
1054 static int xmldoc_update_config_option(struct aco_type **types, const char *module, const char *name, const char *object_name, const char *default_value, unsigned int regex, enum aco_option_type type)
1055 {
1056         RAII_VAR(struct ast_xml_xpath_results *, results, NULL, ast_xml_xpath_results_free);
1057         RAII_VAR(struct ast_xml_doc_item *, config_info, ao2_find(xmldocs, module, OBJ_KEY), ao2_cleanup);
1058         struct ast_xml_doc_item * config_option;
1059         struct ast_xml_node *option;
1060
1061         ast_assert(ARRAY_LEN(aco_option_type_string) > type);
1062
1063         if (!config_info || !(config_option = find_xmldoc_option(config_info, types, name))) {
1064                 ast_log(LOG_ERROR, "XML Documentation for option '%s' in modules '%s' not found!\n", name, module);
1065                 return XMLDOC_STRICT ? -1 : 0;
1066         }
1067
1068         if (!(results = ast_xmldoc_query("//configInfo[@name='%s']/*/configObject[@name='%s']/configOption[@name='%s']", module, object_name, name))) {
1069                 ast_log(LOG_WARNING, "Could not find option '%s' with type '%s' in module '%s'\n", name, object_name, module);
1070                 return XMLDOC_STRICT ? -1 : 0;
1071         }
1072
1073         if (!(option = ast_xml_xpath_get_first_result(results))) {
1074                 ast_log(LOG_WARNING, "Could not obtain results for option '%s' with type '%s' in module '%s'\n", name, object_name, module);
1075                 return XMLDOC_STRICT ? -1 : 0;
1076         }
1077         ast_xml_set_attribute(option, "regex", regex ? "true" : "false");
1078         ast_xml_set_attribute(option, "default", default_value);
1079         ast_xml_set_attribute(option, "type", aco_option_type_string[type]);
1080
1081         if (ast_xmldoc_regenerate_doc_item(config_option)) {
1082                 ast_log(LOG_WARNING, "Could not update option '%s' with values from config option registration\n", name);
1083                 return XMLDOC_STRICT ? -1 : 0;
1084         }
1085
1086         return 0;
1087 }
1088
1089 /*! \internal
1090  * \brief Show the modules with configuration information
1091  */
1092 static void cli_show_modules(struct ast_cli_args *a)
1093 {
1094         struct ast_xml_doc_item *item;
1095         struct ao2_iterator it_items;
1096
1097         ast_assert(a->argc == 3);
1098
1099         if (ao2_container_count(xmldocs) == 0) {
1100                 ast_cli(a->fd, "No modules found.\n");
1101                 return;
1102         }
1103
1104         it_items = ao2_iterator_init(xmldocs, 0);
1105         ast_cli(a->fd, "The following modules have configuration information:\n");
1106         while ((item = ao2_iterator_next(&it_items))) {
1107                 ast_cli(a->fd, "\t%s\n", item->name);
1108                 ao2_ref(item, -1);
1109         }
1110         ao2_iterator_destroy(&it_items);
1111 }
1112
1113 /*! \internal
1114  * \brief Show the configuration types for a module
1115  */
1116 static void cli_show_module_types(struct ast_cli_args *a)
1117 {
1118         RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup);
1119         struct ast_xml_doc_item *tmp;
1120
1121         ast_assert(a->argc == 4);
1122
1123         if (!(item = ao2_find(xmldocs, a->argv[3], OBJ_KEY))) {
1124                 ast_cli(a->fd, "Module %s not found.\n", a->argv[3]);
1125                 return;
1126         }
1127
1128         if (ast_str_strlen(item->synopsis)) {
1129                 ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(item->synopsis), 1));
1130         }
1131         if (ast_str_strlen(item->description)) {
1132                 ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(item->description), 1));
1133         }
1134
1135         tmp = item;
1136         ast_cli(a->fd, "Configuration option types for %s:\n", tmp->name);
1137         while ((tmp = AST_LIST_NEXT(tmp, next))) {
1138                 if (!strcasecmp(tmp->type, "configObject")) {
1139                         ast_cli(a->fd, "%-25s -- %-65.65s\n", tmp->name,
1140                                 ast_str_buffer(tmp->synopsis));
1141                 }
1142         }
1143 }
1144
1145 /*! \internal
1146  * \brief Show the information for a configuration type
1147  */
1148 static void cli_show_module_type(struct ast_cli_args *a)
1149 {
1150         RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup);
1151         struct ast_xml_doc_item *tmp;
1152         char option_type[64];
1153         int match = 0;
1154
1155         ast_assert(a->argc == 5);
1156
1157         if (!(item = ao2_find(xmldocs, a->argv[3], OBJ_KEY))) {
1158                 ast_cli(a->fd, "Unknown module %s\n", a->argv[3]);
1159                 return;
1160         }
1161
1162         tmp = item;
1163         while ((tmp = AST_LIST_NEXT(tmp, next))) {
1164                 if (!strcasecmp(tmp->type, "configObject") && !strcasecmp(tmp->name, a->argv[4])) {
1165                         match = 1;
1166                         term_color(option_type, tmp->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(option_type));
1167                         ast_cli(a->fd, "%s", option_type);
1168                         if (ast_str_strlen(tmp->syntax)) {
1169                                 ast_cli(a->fd, ": [%s]\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->syntax), 1));
1170                         } else {
1171                                 ast_cli(a->fd, "\n\n");
1172                         }
1173                         if (ast_str_strlen(tmp->synopsis)) {
1174                                 ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->synopsis), 1));
1175                         }
1176                         if (ast_str_strlen(tmp->description)) {
1177                                 ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->description), 1));
1178                         }
1179                 }
1180         }
1181
1182         if (!match) {
1183                 ast_cli(a->fd, "Unknown configuration type %s\n", a->argv[4]);
1184                 return;
1185         }
1186
1187         /* Now iterate over the options for the type */
1188         tmp = item;
1189         while ((tmp = AST_LIST_NEXT(tmp, next))) {
1190                 if (!strcasecmp(tmp->type, "configOption") && !strcasecmp(tmp->ref, a->argv[4])) {
1191                         ast_cli(a->fd, "%-25s -- %-65.65s\n", tmp->name,
1192                                         ast_str_buffer(tmp->synopsis));
1193                 }
1194         }
1195 }
1196
1197 /*! \internal
1198  * \brief Show detailed information for an option
1199  */
1200 static void cli_show_module_options(struct ast_cli_args *a)
1201 {
1202         RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup);
1203         struct ast_xml_doc_item *tmp;
1204         char option_name[64];
1205         int match = 0;
1206
1207         ast_assert(a->argc == 6);
1208
1209         if (!(item = ao2_find(xmldocs, a->argv[3], OBJ_KEY))) {
1210                 ast_cli(a->fd, "Unknown module %s\n", a->argv[3]);
1211                 return;
1212         }
1213         tmp = item;
1214         while ((tmp = AST_LIST_NEXT(tmp, next))) {
1215                 if (!strcasecmp(tmp->type, "configOption") && !strcasecmp(tmp->ref, a->argv[4]) && !strcasecmp(tmp->name, a->argv[5])) {
1216                         if (match) {
1217                                 ast_cli(a->fd, "\n");
1218                         }
1219                         term_color(option_name, tmp->ref, COLOR_MAGENTA, COLOR_BLACK, sizeof(option_name));
1220                         ast_cli(a->fd, "[%s%s]\n", option_name, ast_term_reset());
1221                         if (ast_str_strlen(tmp->syntax)) {
1222                                 ast_cli(a->fd, "%s\n", ast_xmldoc_printable(ast_str_buffer(tmp->syntax), 1));
1223                         }
1224                         ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(AS_OR(tmp->synopsis, "No information available"), 1));
1225                         if (ast_str_strlen(tmp->description)) {
1226                                 ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->description), 1));
1227                         }
1228
1229                         if (ast_str_strlen(tmp->seealso)) {
1230                                 ast_cli(a->fd, "See Also:\n");
1231                                 ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->seealso), 1));
1232                         }
1233
1234                         match = 1;
1235                 }
1236         }
1237
1238         if (!match) {
1239                 ast_cli(a->fd, "No option %s found for %s:%s\n", a->argv[5], a->argv[3], a->argv[4]);
1240         }
1241 }
1242
1243 static char *cli_show_help(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1244 {
1245         switch (cmd) {
1246         case CLI_INIT:
1247                 e->command = "config show help";
1248                 e->usage =
1249                         "Usage: config show help [<module> [<type> [<option>]]]\n"
1250                         "   Display detailed information about module configuration.\n"
1251                         "     * If nothing is specified, the modules that have\n"
1252                         "       configuration information are listed.\n"
1253                         "     * If <module> is specified, the configuration types\n"
1254                         "       for that module will be listed, along with brief\n"
1255                         "       information about that type.\n"
1256                         "     * If <module> and <type> are specified, detailed\n"
1257                         "       information about the type is displayed, as well\n"
1258                         "       as the available options.\n"
1259                         "     * If <module>, <type>, and <option> are specified,\n"
1260                         "       detailed information will be displayed about that\n"
1261                         "       option.\n"
1262                         "   NOTE: the help documentation is partially generated at run\n"
1263                         "     time when a module is loaded. If a module is not loaded,\n"
1264                         "     configuration help for that module may be incomplete.\n";
1265                 return NULL;
1266         case CLI_GENERATE:
1267                 switch(a->pos) {
1268                 case 3: return complete_config_module(a->word, a->pos, a->n);
1269                 case 4: return complete_config_type(a->argv[3], a->word, a->pos, a->n);
1270                 case 5: return complete_config_option(a->argv[3], a->argv[4], a->word, a->pos, a->n);
1271                 default: return NULL;
1272                 }
1273         }
1274
1275         switch (a->argc) {
1276         case 3:
1277                 cli_show_modules(a);
1278                 break;
1279         case 4:
1280                 cli_show_module_types(a);
1281                 break;
1282         case 5:
1283                 cli_show_module_type(a);
1284                 break;
1285         case 6:
1286                 cli_show_module_options(a);
1287                 break;
1288         default:
1289                 return CLI_SHOWUSAGE;
1290         }
1291
1292         return CLI_SUCCESS;
1293 }
1294
1295 static struct ast_cli_entry cli_aco[] = {
1296         AST_CLI_DEFINE(cli_show_help, "Show configuration help for a module"),
1297 };
1298
1299 static void aco_deinit(void)
1300 {
1301         ast_cli_unregister(cli_aco);
1302         ao2_cleanup(xmldocs);
1303 }
1304 #endif /* AST_XML_DOCS */
1305
1306 int aco_init(void)
1307 {
1308 #ifdef AST_XML_DOCS
1309         ast_register_cleanup(aco_deinit);
1310         if (!(xmldocs = ast_xmldoc_build_documentation("configInfo"))) {
1311                 ast_log(LOG_ERROR, "Couldn't build config documentation\n");
1312                 return -1;
1313         }
1314         ast_cli_register_multiple(cli_aco, ARRAY_LEN(cli_aco));
1315 #endif /* AST_XML_DOCS */
1316         return 0;
1317 }
1318
1319 /* Default config option handlers */
1320
1321 /*! \brief Default option handler for signed integers
1322  * \note For a description of the opt->flags and opt->args values, see the documentation for
1323  * enum aco_option_type in config_options.h
1324  */
1325 static int int_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
1326         int *field = (int *)(obj + opt->args[0]);
1327         unsigned int flags = PARSE_INT32 | opt->flags;
1328         int res = 0;
1329         if (opt->flags & PARSE_IN_RANGE) {
1330                 res = opt->flags & PARSE_DEFAULT ?
1331                         ast_parse_arg(var->value, flags, field, (int) opt->args[1], (int) opt->args[2], opt->args[3]) :
1332                         ast_parse_arg(var->value, flags, field, (int) opt->args[1], (int) opt->args[2]);
1333                 if (res) {
1334                         if (opt->flags & PARSE_RANGE_DEFAULTS) {
1335                                 ast_log(LOG_WARNING, "Failed to set %s=%s. Set to %d instead due to range limit (%d, %d)\n", var->name, var->value, *field, (int) opt->args[1], (int) opt->args[2]);
1336                                 res = 0;
1337                         } else if (opt->flags & PARSE_DEFAULT) {
1338                                 ast_log(LOG_WARNING, "Failed to set %s=%s, Set to default value %d instead.\n", var->name, var->value, *field);
1339                                 res = 0;
1340                         }
1341                 }
1342         } else if ((opt->flags & PARSE_DEFAULT) && ast_parse_arg(var->value, flags, field, (int) opt->args[1])) {
1343                 ast_log(LOG_WARNING, "Attempted to set %s=%s, but set it to %d instead due to default)\n", var->name, var->value, *field);
1344         } else {
1345                 res = ast_parse_arg(var->value, flags, field);
1346         }
1347
1348         return res;
1349 }
1350
1351 /*! \brief Default option handler for unsigned integers
1352  * \note For a description of the opt->flags and opt->args values, see the documentation for
1353  * enum aco_option_type in config_options.h
1354  */
1355 static int uint_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
1356         unsigned int *field = (unsigned int *)(obj + opt->args[0]);
1357         unsigned int flags = PARSE_UINT32 | opt->flags;
1358         int res = 0;
1359         if (opt->flags & PARSE_IN_RANGE) {
1360                 res = opt->flags & PARSE_DEFAULT ?
1361                         ast_parse_arg(var->value, flags, field, (unsigned int) opt->args[1], (unsigned int) opt->args[2], opt->args[3]) :
1362                         ast_parse_arg(var->value, flags, field, (unsigned int) opt->args[1], (unsigned int) opt->args[2]);
1363                 if (res) {
1364                         if (opt->flags & PARSE_RANGE_DEFAULTS) {
1365                                 ast_log(LOG_WARNING, "Failed to set %s=%s. Set to %u instead due to range limit (%d, %d)\n", var->name, var->value, *field, (int) opt->args[1], (int) opt->args[2]);
1366                                 res = 0;
1367                         } else if (opt->flags & PARSE_DEFAULT) {
1368                                 ast_log(LOG_WARNING, "Failed to set %s=%s, Set to default value %u instead.\n", var->name, var->value, *field);
1369                                 res = 0;
1370                         }
1371                 }
1372         } else if ((opt->flags & PARSE_DEFAULT) && ast_parse_arg(var->value, flags, field, (unsigned int) opt->args[1])) {
1373                 ast_log(LOG_WARNING, "Attempted to set %s=%s, but set it to %u instead due to default)\n", var->name, var->value, *field);
1374         } else {
1375                 res = ast_parse_arg(var->value, flags, field);
1376         }
1377
1378         return res;
1379 }
1380
1381 /*! \brief Default option handler for doubles
1382  * \note For a description of the opt->flags and opt->args values, see the documentation for
1383  * enum aco_option_type in config_options.h
1384  */
1385 static int double_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
1386         double *field = (double *)(obj + opt->args[0]);
1387         return ast_parse_arg(var->value, PARSE_DOUBLE | opt->flags, field);
1388 }
1389
1390 /*! \brief Default handler for ACLs
1391  * \note For a description of the opt->flags and opt->args values, see the documentation for
1392  * enum aco_option_type in config_options.h
1393  */
1394 static int acl_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
1395         struct ast_ha **ha = (struct ast_ha **)(obj + opt->args[0]);
1396         int error = 0;
1397         *ha = ast_append_ha(opt->flags ? "permit" : "deny", var->value, *ha, &error);
1398         return error;
1399 }
1400
1401 /*! \brief Default option handler for codec preferences/capabilities
1402  * \note For a description of the opt->flags and opt->args values, see the documentation for
1403  * enum aco_option_type in config_options.h
1404  */
1405 static int codec_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) {
1406         struct ast_format_cap **cap = (struct ast_format_cap **)(obj + opt->args[0]);
1407         return ast_format_cap_update_by_allow_disallow(*cap, var->value, opt->flags);
1408 }
1409
1410 /*! \brief Default option handler for stringfields
1411  * \note For a description of the opt->flags and opt->args values, see the documentation for
1412  * enum aco_option_type in config_options.h
1413  */
1414 static int stringfield_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
1415 {
1416         ast_string_field *field = (const char **)(obj + opt->args[0]);
1417         struct ast_string_field_pool **pool = (struct ast_string_field_pool **)(obj + opt->args[1]);
1418         struct ast_string_field_mgr *mgr = (struct ast_string_field_mgr *)(obj + opt->args[2]);
1419
1420         if (opt->flags && ast_strlen_zero(var->value)) {
1421                 return -1;
1422         }
1423         ast_string_field_ptr_set_by_fields(*pool, *mgr, field, var->value);
1424         return 0;
1425 }
1426
1427 /*! \brief Default option handler for bools (ast_true/ast_false)
1428  * \note For a description of the opt->flags and opt->args values, see the documentation for
1429  * enum aco_option_type in config_options.h
1430  */
1431 static int bool_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
1432 {
1433         unsigned int *field = (unsigned int *)(obj + opt->args[0]);
1434         *field = opt->flags ? ast_true(var->value) : ast_false(var->value);
1435         return 0;
1436 }
1437
1438 /*! \brief Default option handler for bools (ast_true/ast_false) that are stored as flags
1439  * \note For a description of the opt->flags and opt->args values, see the documentation for
1440  * enum aco_option_type in config_options.h
1441  */
1442 static int boolflag_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
1443 {
1444         unsigned int *flags_field = (unsigned int *)(obj + opt->args[0]);
1445         unsigned int val = opt->flags ? ast_true(var->value) : ast_false(var->value);
1446         unsigned int flag = opt->args[1];
1447         if (val) {
1448                 *flags_field |= flag;
1449         } else {
1450                 *flags_field &= ~flag;
1451         }
1452         return 0;
1453 }
1454
1455 /*! \brief Default handler for ast_sockaddrs
1456  * \note For a description of the opt->flags and opt->args values, see the documentation for
1457  * enum aco_option_type in config_options.h
1458  */
1459 static int sockaddr_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
1460 {
1461         struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + opt->args[0]);
1462         return ast_parse_arg(var->value, PARSE_ADDR | opt->flags, field);
1463 }
1464
1465 /*! \brief Default handler for doing nothing
1466  */
1467 static int noop_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
1468 {
1469         return 0;
1470 }
1471
1472 /*! \brief Default handler for character arrays
1473  * \note For a description of the opt->flags and opt->args values, see the documentation for
1474  * enum aco_option_type in config_options.h
1475  */
1476 static int chararray_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj)
1477 {
1478         char *field = (char *)(obj + opt->args[0]);
1479         size_t len = opt->args[1];
1480
1481         if (opt->flags && ast_strlen_zero(var->value)) {
1482                 return -1;
1483         }
1484         ast_copy_string(field, var->value, len);
1485         return 0;
1486 }