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