Sat Apr 26 2014 22:02:45

Asterisk developer's documentation


config_options.c File Reference

Configuration Option-handling. More...

#include "asterisk.h"
#include <regex.h>
#include "asterisk/config.h"
#include "asterisk/config_options.h"
#include "asterisk/stringfields.h"
#include "asterisk/acl.h"
#include "asterisk/frame.h"
Include dependency graph for config_options.c:

Go to the source code of this file.

Data Structures

struct  aco_info_internal
 Bits of aco_info that shouldn't be assigned outside this file. More...
struct  aco_option
struct  aco_type_internal

Defines

#define CONFIG_OPT_BUCKETS   53

Functions

int __aco_option_register (struct aco_info *info, const char *name, enum aco_matchtype matchtype, struct aco_type **types, const char *default_val, enum aco_option_type kind, aco_option_handler handler, unsigned int flags, size_t argc,...)
 register a config option
static int acl_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default handler for ACLs.
void aco_info_destroy (struct aco_info *info)
 Destroy an initialized aco_info struct.
int aco_info_init (struct aco_info *info)
 Initialize an aco_info structure.
struct ao2_containeraco_option_container_alloc (void)
 Allocate a container to hold config options.
static struct aco_optionaco_option_find (struct aco_type *type, const char *name)
int aco_option_register_deprecated (struct aco_info *info, const char *name, struct aco_type **types, const char *aliased_to)
 Register a deprecated (and aliased) config option.
void * aco_pending_config (struct aco_info *info)
 Get pending config changes.
enum aco_process_status aco_process_ast_config (struct aco_info *info, struct aco_file *file, struct ast_config *cfg)
 Process config info from an ast_config via options registered with an aco_info.
int aco_process_category_options (struct aco_type *type, struct ast_config *cfg, const char *cat, void *obj)
 Parse each option defined in a config category.
enum aco_process_status aco_process_config (struct aco_info *info, int reload)
 Process a config info via the options registered with an aco_info.
int aco_process_var (struct aco_type *type, const char *cat, struct ast_variable *var, void *obj)
 Parse a single ast_variable and apply it to an object.
int aco_set_defaults (struct aco_type *type, const char *category, void *obj)
 Set all default options of obj.
static int apply_config (struct aco_info *info)
static aco_option_handler ast_config_option_default_handler (enum aco_option_type type)
static int bool_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default option handler for bools (ast_true/ast_false)
static int boolflag_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default option handler for bools (ast_true/ast_false) that are stored as flags.
static regex_t * build_regex (const char *text)
static int chararray_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default handler for character arrays.
static int codec_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default option handler for codec preferences/capabilities.
static int config_opt_cmp (void *obj, void *arg, int flags)
static int config_opt_hash (const void *obj, const int flags)
static void config_option_destroy (void *obj)
static int double_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default option handler for doubles.
static int find_option_cb (void *obj, void *arg, int flags)
static int int_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default option handler for signed integers.
static struct aco_typeinternal_aco_type_find (struct aco_file *file, struct ast_config *cfg, const char *category)
static void internal_file_types_destroy (struct aco_file *file)
static enum aco_process_status internal_process_ast_config (struct aco_info *info, struct aco_file *file, struct ast_config *cfg)
static void internal_type_destroy (struct aco_type *type)
static int internal_type_init (struct aco_type *type)
static int is_preload (struct aco_file *file, const char *cat)
static int link_option_to_types (struct aco_type **types, struct aco_option *opt)
static int noop_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default handler for doing noithing.
static int process_category (struct ast_config *cfg, struct aco_info *info, struct aco_file *file, const char *cat, int preload)
static int sockaddr_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default handler for ast_sockaddrs.
static int stringfield_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default option handler for stringfields.
static int uint_handler_fn (const struct aco_option *opt, struct ast_variable *var, void *obj)
 Default option handler for unsigned integers.

Detailed Description

Configuration Option-handling.

Author:
Terry Wilson <twilson@digium.com>

Definition in file config_options.c.


Define Documentation

#define CONFIG_OPT_BUCKETS   53

Definition at line 43 of file config_options.c.

Referenced by aco_option_container_alloc().


Function Documentation

int __aco_option_register ( struct aco_info info,
const char *  name,
enum aco_matchtype  match_type,
struct aco_type **  types,
const char *  default_val,
enum aco_option_type  type,
aco_option_handler  handler,
unsigned int  flags,
size_t  argc,
  ... 
)

register a config option

Note:
this should probably only be called by one of the aco_option_register* macros
Parameters:
infoThe aco_info holding this module's config information
nameThe name of the option
typesAn array of valid option types for matching categories to the correct struct type
default_valThe default value of the option in the same format as defined in a config file
typeThe option type (only for default handlers)
handlerThe handler function for the option (only for non-default types)
flagstype specific flags, stored in the option and available to the handler
argcThe number for variadic arguments
...field offsets to store for default handlers
Return values:
0success
-1failure

Definition at line 193 of file config_options.c.

References ACO_REGEX, ao2_alloc, ao2_ref, aco_option::argc, aco_option::args, ast_config_option_default_handler(), ast_log(), build_regex(), config_option_destroy(), aco_option::default_val, aco_option::flags, aco_option::handler, link_option_to_types(), LOG_ERROR, aco_option::match_type, name, aco_option::name, aco_option::name_regex, OPT_CUSTOM_T, and aco_option::type.

{
   struct aco_option *opt;
   va_list ap;
   int tmp;

   /* Custom option types require a handler */
   if (!handler && kind == OPT_CUSTOM_T) {
      return -1;
   }

   if (!(types && types[0])) {
      return -1;
   }

   if (!(opt = ao2_alloc(sizeof(*opt) + argc * sizeof(opt->args[0]), config_option_destroy))) {
      return -1;
   }

   if (matchtype == ACO_REGEX && !(opt->name_regex = build_regex(name))) {
      ao2_ref(opt, -1);
      return -1;
   }

   va_start(ap, argc);
   for (tmp = 0; tmp < argc; tmp++) {
      opt->args[tmp] = va_arg(ap, size_t);
   }
   va_end(ap);

   opt->name = name;
   opt->match_type = matchtype;
   opt->default_val = default_val;
   opt->type = kind;
   opt->handler = handler;
   opt->flags = flags;
   opt->argc = argc;

   if (!opt->handler && !(opt->handler = ast_config_option_default_handler(opt->type))) {
      /* This should never happen */
      ast_log(LOG_ERROR, "No handler provided, and no default handler exists for type %d\n", opt->type);
      ao2_ref(opt, -1);
      return -1;
   };

   if (link_option_to_types(types, opt)) {
      ao2_ref(opt, -1);
      return -1;
   }

   return 0;
}
static int acl_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default handler for ACLs.

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 811 of file config_options.c.

References aco_option::args, ast_append_ha(), aco_option::flags, and ast_variable::value.

Referenced by ast_config_option_default_handler().

                                                                                             {
   struct ast_ha **ha = (struct ast_ha **)(obj + opt->args[0]);
   int error = 0;
   *ha = ast_append_ha(opt->flags ? "permit" : "deny", var->value, *ha, &error);
   return error;
}
void aco_info_destroy ( struct aco_info info)

Destroy an initialized aco_info struct.

Parameters:
infoThe address of the aco_info struct to destroy

Definition at line 690 of file config_options.c.

References ast_free, aco_info::files, aco_info::internal, and internal_file_types_destroy().

Referenced by aco_info_init(), ast_named_acl_init(), load_module(), named_acl_cleanup(), udptl_shutdown(), and unload_module().

{
   int x;
   /* It shouldn't be possible for internal->pending to be in use when this is called because
    * of the locks in loader.c around reloads and unloads and the fact that internal->pending
    * only exists while those locks are held */
   ast_free(info->internal);
   info->internal = NULL;

   for (x = 0; info->files[x]; x++) {
      internal_file_types_destroy(info->files[x]);
   }
}
int aco_info_init ( struct aco_info info)

Initialize an aco_info structure.

Note:
aco_info_destroy must be called if this succeeds
Parameters:
infoThe address of an aco_info struct to initialize
Return values:
0Success
non-zeroFailure

Definition at line 668 of file config_options.c.

References aco_info_destroy(), ast_calloc, aco_info::files, aco_info::internal, internal_type_init(), and aco_file::types.

Referenced by ast_named_acl_init(), ast_udptl_init(), and load_module().

{
   size_t x, y;

   if (!(info->internal = ast_calloc(1, sizeof(*info->internal)))) {
      return -1;
   }

   for (x = 0; info->files[x]; x++) {
      for (y = 0; info->files[x]->types[y]; y++) {
         if (internal_type_init(info->files[x]->types[y])) {
            goto error;
         }
      }
   }

   return 0;
error:
   aco_info_destroy(info);
   return -1;
}
struct ao2_container* aco_option_container_alloc ( void  ) [read]

Allocate a container to hold config options.

Definition at line 293 of file config_options.c.

References ao2_container_alloc, CONFIG_OPT_BUCKETS, config_opt_cmp(), and config_opt_hash().

Referenced by internal_type_init().

static struct aco_option* aco_option_find ( struct aco_type type,
const char *  name 
) [static, read]

Definition at line 276 of file config_options.c.

References ao2_callback, ast_log(), find_option_cb(), aco_type::internal, LOG_NOTICE, OBJ_KEY, and aco_type_internal::opts.

Referenced by aco_process_var().

{
   struct aco_option *opt;

   if (!type || !type->internal || !type->internal->opts) {
      ast_log(LOG_NOTICE, "Attempting to use NULL or unitialized config type\n");
      return NULL;
   }

   /* Try an exact match with OBJ_KEY for the common/fast case, then iterate through
    * all options for the regex cases */
   if (!(opt = ao2_callback(type->internal->opts, OBJ_KEY, find_option_cb, (void *) name))) {
      opt = ao2_callback(type->internal->opts, 0, find_option_cb, (void *) name);
   }
   return opt;
}
int aco_option_register_deprecated ( struct aco_info info,
const char *  name,
struct aco_type **  types,
const char *  aliased_to 
)

Register a deprecated (and aliased) config option.

Parameters:
infoA pointer to the aco_info struct
nameThe name of the deprecated option
typesAn array of valid option types for matching categories to the correct struct type
aliased_toThe name of the option that this deprecated option matches to
Return values:
0Success
-1Failure

Definition at line 168 of file config_options.c.

References ACO_EXACT, aco_option::aliased_to, ao2_alloc, ao2_ref, ast_strlen_zero(), config_option_destroy(), aco_option::deprecated, link_option_to_types(), aco_option::match_type, name, and aco_option::name.

{
   struct aco_option *opt;

   if (!info || ast_strlen_zero(name) || ast_strlen_zero(aliased_to)) {
      return -1;
   }

   if (!(opt = ao2_alloc(sizeof(*opt), config_option_destroy))) {
      return -1;
   }

   opt->name = name;
   opt->aliased_to = aliased_to;
   opt->deprecated = 1;
   opt->match_type = ACO_EXACT;

   if (link_option_to_types(types, opt)) {
      ao2_ref(opt, -1);
      return -1;
   }

   return 0;
}
void* aco_pending_config ( struct aco_info info)

Get pending config changes.

Note:
This will most likely be called from the pre_apply_config callback function
Parameters:
infoAn initialized aco_info
Return values:
NULLerror
non-NULLA pointer to the user-defined config object with un-applied changes

Definition at line 73 of file config_options.c.

References ast_log(), aco_info::internal, LOG_ERROR, and aco_info_internal::pending.

Referenced by udptl_pre_apply_config().

{
   if (!(info && info->internal)) {
      ast_log(LOG_ERROR, "This may not be called without an initialized aco_info!\n");
      return NULL;
   }
   return info->internal->pending;
}
enum aco_process_status aco_process_ast_config ( struct aco_info info,
struct aco_file file,
struct ast_config cfg 
)

Process config info from an ast_config via options registered with an aco_info.

Parameters:
infoThe aco_info to be used for handling the config
fileThe file attached to aco_info that the config represents
cfgA pointer to a loaded ast_config to parse
reloadWhether or not this is a reload
Return values:
ACO_PROCESS_OKSuccess
ACO_PROCESS_ERRORFailure

Definition at line 447 of file config_options.c.

References ACO_PROCESS_ERROR, ACO_PROCESS_OK, ao2_cleanup, apply_config(), ast_log(), aco_file::filename, aco_info::internal, internal_process_ast_config(), LOG_ERROR, aco_info_internal::pending, aco_info::pre_apply_config, and aco_info::snapshot_alloc.

{
   if (!info->internal) {
      ast_log(LOG_ERROR, "Attempt to process %s with uninitialized aco_info\n", file->filename);
      goto error;
   }

   if (!(info->internal->pending = info->snapshot_alloc())) {
      ast_log(LOG_ERROR, "In %s: Could not allocate temporary objects\n", file->filename);
      goto error;
   }

   if (internal_process_ast_config(info, file, cfg)) {
      goto error;
   }

   if (info->pre_apply_config && info->pre_apply_config()) {
      goto error;
   }

   if (apply_config(info)) {
      goto error;
   };

   ao2_cleanup(info->internal->pending);
   return ACO_PROCESS_OK;

error:
   ao2_cleanup(info->internal->pending);
   return ACO_PROCESS_ERROR;
}
int aco_process_category_options ( struct aco_type type,
struct ast_config cfg,
const char *  cat,
void *  obj 
)

Parse each option defined in a config category.

Parameters:
typeThe aco_type with the options for parsing
cfgThe ast_config being parsed
catThe config category being parsed
objThe user-defined config object that will store the parsed config items
Return values:
0Success
-1Failure

Definition at line 606 of file config_options.c.

References aco_process_var(), ast_variable_browse(), ast_variable::next, and var.

Referenced by process_category().

{
   struct ast_variable *var;

   for (var = ast_variable_browse(cfg, cat); var; var = var->next) {
      if (aco_process_var(type, cat, var, obj)) {
         return -1;
      }
   }

   return 0;
}
enum aco_process_status aco_process_config ( struct aco_info info,
int  reload 
)

Process a config info via the options registered with an aco_info.

Parameters:
infoThe config_options_info to be used for handling the config
reloadWhether or not this is a reload
Return values:
ACO_PROCESS_OKSuccess
ACO_PROCESS_ERRORFailure
ACO_PROCESS_UNCHANGEDNo change due to unedited config file

Definition at line 479 of file config_options.c.

References ACO_GLOBAL, ACO_PROCESS_ERROR, ACO_PROCESS_OK, ACO_PROCESS_UNCHANGED, aco_set_defaults(), aco_file::alias, ao2_cleanup, apply_config(), ast_config_destroy(), ast_config_load, ast_debug, ast_log(), aco_type::category, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, aco_file::filename, aco_info::files, aco_info::internal, internal_process_ast_config(), aco_type::item_offset, LOG_ERROR, match(), aco_info::module, aco_info_internal::pending, aco_info::post_apply_config, aco_info::pre_apply_config, aco_info::snapshot_alloc, aco_type::type, and aco_file::types.

Referenced by __ast_udptl_reload(), ast_named_acl_init(), ast_named_acl_reload(), load_module(), reload(), and reload_module().

{
   struct ast_config *cfg;
   struct ast_flags cfg_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0, };
   int res = ACO_PROCESS_OK, x = 0;
   struct aco_file *file;

   if (!(info->files[0])) {
      ast_log(LOG_ERROR, "No filename given, cannot proceed!\n");
      return ACO_PROCESS_ERROR;
   }

   if (!info->internal) {
      ast_log(LOG_ERROR, "Attempting to process uninitialized aco_info\n");
      return ACO_PROCESS_ERROR;
   }

   if (!(info->internal->pending = info->snapshot_alloc())) {
      ast_log(LOG_ERROR, "In %s: Could not allocate temporary objects\n", info->module);
      return ACO_PROCESS_ERROR;
   }

   while (res != ACO_PROCESS_ERROR && (file = info->files[x++])) {
      const char *filename = file->filename;
      struct aco_type *match;
      int i;

      /* set defaults for global objects */
      for (i = 0, match = file->types[i]; match; match = file->types[++i]) {
         void **field = info->internal->pending + match->item_offset;

         if (match->type != ACO_GLOBAL || !*field) {
            continue;
         }

         if (aco_set_defaults(match, match->category, *field)) {
            ast_log(LOG_ERROR, "In %s: Setting defaults for %s failed\n", file->filename, match->category);
            res = ACO_PROCESS_ERROR;
            break;
         }
      }

      if (res == ACO_PROCESS_ERROR) {
         break;
      }

try_alias:
      if (!(cfg = ast_config_load(filename, cfg_flags))) {
         if (file->alias && strcmp(file->alias, filename)) {
            filename = file->alias;
            goto try_alias;
         }
         ast_log(LOG_ERROR, "Unable to load config file '%s'\n", file->filename);
         res = ACO_PROCESS_ERROR;
         break;
      } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
         ast_debug(1, "%s was unchanged\n", file->filename);
         res = ACO_PROCESS_UNCHANGED;
         continue;
      } else if (cfg == CONFIG_STATUS_FILEINVALID) {
         ast_log(LOG_ERROR, "Contents of %s are invalid and cannot be parsed\n", file->filename);
         res = ACO_PROCESS_ERROR;
         break;
      } else if (cfg == CONFIG_STATUS_FILEMISSING) {
         if (file->alias && strcmp(file->alias, filename)) {
            filename = file->alias;
            goto try_alias;
         }
         ast_log(LOG_ERROR, "%s is missing! Cannot load %s\n", file->filename, info->module);
         res = ACO_PROCESS_ERROR;
         break;
      }

      res = internal_process_ast_config(info, file, cfg);
      ast_config_destroy(cfg);
   }

   if (res != ACO_PROCESS_OK) {
      goto end;
   }

   if (info->pre_apply_config && (info->pre_apply_config()))  {
      res = ACO_PROCESS_ERROR;
      goto end;
   }

   if (apply_config(info)) {
      res = ACO_PROCESS_ERROR;
      goto end;
   }

   if (info->post_apply_config) {
      info->post_apply_config();
   }

end:
   ao2_cleanup(info->internal->pending);
   return res;
}
int aco_process_var ( struct aco_type type,
const char *  cat,
struct ast_variable var,
void *  obj 
)

Parse a single ast_variable and apply it to an object.

Note:
This function can be used to build up an object by repeatedly passing in the config variable name and values that would be found in a config file. This can be useful if the object is to be populated by a dialplan function, for example.
Parameters:
typeThe aco_type associated with the object
catThe category to use
varA variable to apply to the object
objA pointer to the object to be configured
Return values:
0Success
-1Failure

Definition at line 578 of file config_options.c.

References aco_option_find(), ao2_cleanup, ao2_ref, ast_log(), ast_strlen_zero(), ast_variable::file, ast_variable::lineno, LOG_ERROR, LOG_WARNING, ast_variable::name, and ast_variable::value.

Referenced by aco_process_category_options().

{
   RAII_VAR(struct aco_option *, opt, aco_option_find(type, var->name), ao2_cleanup);
   if (opt && opt->deprecated && !ast_strlen_zero(opt->aliased_to)) {
      const char *alias = ast_strdupa(opt->aliased_to);
      ast_log(LOG_WARNING, "At line %d of %s option '%s' is deprecated. Use '%s' instead\n", var->lineno, var->file, var->name, alias);
      ao2_ref(opt, -1);
      opt = aco_option_find(type, alias);
   }

   if (!opt) {
      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);
      return -1;
   }

   if (!opt->handler) {
      /* It should be impossible for an option to not have a handler */
      ast_log(LOG_ERROR, "BUG! Somehow a config option for %s/%s was created with no handler!\n", cat, var->name);
      return -1;
   }
   if (opt->handler(opt, var, obj)) {
      ast_log(LOG_ERROR, "Error parsing %s=%s at line %d of %s\n", var->name, var->value, var->lineno, var->file);
      return -1;
   }

   return 0;
}
int aco_set_defaults ( struct aco_type type,
const char *  category,
void *  obj 
)

Set all default options of obj.

Parameters:
infoThe aco_type with the options
categoryThe configuration category from which obj is being configured
objThe object being configured
Return values:
0Success
-1Failure

Definition at line 704 of file config_options.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_log(), ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), aco_option::default_val, aco_option::handler, aco_type::internal, LOG_ERROR, aco_option::name, aco_type_internal::opts, and var.

Referenced by __ast_udptl_reload(), aco_process_config(), and process_category().

{
   struct aco_option *opt;
   struct ao2_iterator iter;

   iter = ao2_iterator_init(type->internal->opts, 0);

   while ((opt = ao2_iterator_next(&iter))) {
      RAII_VAR(struct ast_variable *, var, NULL, ast_variables_destroy);

      if (ast_strlen_zero(opt->default_val)) {
         ao2_ref(opt, -1);
         continue;
      }
      if (!(var = ast_variable_new(opt->name, opt->default_val, ""))) {
         ao2_ref(opt, -1);
         ao2_iterator_destroy(&iter);
         return -1;
      }
      if (opt->handler(opt, var, obj)) {
         ast_log(LOG_ERROR, "Unable to set default for %s, %s=%s\n", category, var->name, var->value);
         ao2_ref(opt, -1);
         ao2_iterator_destroy(&iter);
         return -1;
      }
      ao2_ref(opt, -1);
   }
   ao2_iterator_destroy(&iter);

   return 0;
}
static int apply_config ( struct aco_info info) [static]
static int bool_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default option handler for bools (ast_true/ast_false)

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 845 of file config_options.c.

References aco_option::args, ast_false(), ast_true(), aco_option::flags, and ast_variable::value.

Referenced by ast_config_option_default_handler().

{
   unsigned int *field = (unsigned int *)(obj + opt->args[0]);
   *field = opt->flags ? ast_true(var->value) : ast_false(var->value);
   return 0;
}
static int boolflag_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default option handler for bools (ast_true/ast_false) that are stored as flags.

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 856 of file config_options.c.

References aco_option::args, ast_false(), ast_true(), aco_option::flags, and ast_variable::value.

Referenced by ast_config_option_default_handler().

{
   unsigned int *flags_field = (unsigned int *)(obj + opt->args[0]);
   unsigned int val = opt->flags ? ast_true(var->value) : ast_false(var->value);
   unsigned int flag = opt->args[1];
   if (val) {
      *flags_field |= flag;
   } else {
      *flags_field &= ~flag;
   }
   return 0;
}
static regex_t* build_regex ( const char *  text) [static]

Definition at line 124 of file config_options.c.

References ast_free, ast_log(), ast_malloc, len(), LOG_ERROR, and regex().

Referenced by __aco_option_register(), and internal_type_init().

{
   int res;
   regex_t *regex;

   if (!(regex = ast_malloc(sizeof(*regex)))) {
      return NULL;
   }

   if ((res = regcomp(regex, text, REG_EXTENDED | REG_ICASE | REG_NOSUB))) {
      size_t len = regerror(res, regex, NULL, 0);
      char buf[len];
      regerror(res, regex, buf, len);
      ast_log(LOG_ERROR, "Could not compile regex '%s': %s\n", text, buf);
      ast_free(regex);
      return NULL;
   }

   return regex;
}
static int chararray_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default handler for character arrays.

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 890 of file config_options.c.

References aco_option::args, ast_copy_string(), len(), and ast_variable::value.

Referenced by ast_config_option_default_handler().

{
   char *field = (char *)(obj + opt->args[0]);
   size_t len = opt->args[1];

   ast_copy_string(field, var->value, len);
   return 0;
}
static int codec_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default option handler for codec preferences/capabilities.

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 822 of file config_options.c.

References aco_option::args, ast_parse_allow_disallow(), aco_option::flags, and ast_variable::value.

Referenced by ast_config_option_default_handler().

                                                                                               {
   struct ast_codec_pref *pref = (struct ast_codec_pref *)(obj + opt->args[0]);
   struct ast_format_cap **cap = (struct ast_format_cap **)(obj + opt->args[1]);
   return ast_parse_allow_disallow(pref, *cap, var->value, opt->flags);
}
static int config_opt_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 254 of file config_options.c.

References CMP_MATCH, CMP_STOP, name, aco_option::name, aco_option::obj, and OBJ_KEY.

Referenced by aco_option_container_alloc().

{
   struct aco_option *opt1 = obj, *opt2 = arg;
   const char *name = (flags & OBJ_KEY) ? arg : opt2->name;
   return strcasecmp(opt1->name, name) ? 0 : CMP_MATCH | CMP_STOP;
}
static int config_opt_hash ( const void *  obj,
const int  flags 
) [static]

Definition at line 247 of file config_options.c.

References ast_str_case_hash(), name, aco_option::name, aco_option::obj, and OBJ_KEY.

Referenced by aco_option_container_alloc().

{
   const struct aco_option *opt = obj;
   const char *name = (flags & OBJ_KEY) ? obj : opt->name;
   return ast_str_case_hash(name);
}
static void config_option_destroy ( void *  obj) [static]

Definition at line 82 of file config_options.c.

References ACO_REGEX, ast_free, aco_option::match_type, aco_option::name_regex, and aco_option::obj.

Referenced by __aco_option_register(), and aco_option_register_deprecated().

{
   struct aco_option *opt = obj;
   if (opt->match_type == ACO_REGEX && opt->name_regex) {
      regfree(opt->name_regex);
      ast_free(opt->name_regex);
   }
}
static int double_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default option handler for doubles.

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 802 of file config_options.c.

References aco_option::args, ast_parse_arg(), aco_option::flags, PARSE_DOUBLE, and ast_variable::value.

Referenced by ast_config_option_default_handler().

                                                                                                {
   double *field = (double *)(obj + opt->args[0]);
   return ast_parse_arg(var->value, PARSE_DOUBLE | opt->flags, field);
}
static int find_option_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 261 of file config_options.c.

References ACO_EXACT, ACO_REGEX, ast_log(), CMP_MATCH, CMP_STOP, LOG_ERROR, match(), aco_option::match_type, name, aco_option::name, aco_option::name_regex, and aco_option::obj.

Referenced by aco_option_find().

{
   struct aco_option *match = obj;
   const char *name = arg;

   switch (match->match_type) {
   case ACO_EXACT:
      return strcasecmp(name, match->name) ? 0 : CMP_MATCH | CMP_STOP;
   case ACO_REGEX:
      return regexec(match->name_regex, name, 0, NULL, 0) ? 0 : CMP_MATCH | CMP_STOP;
   }
   ast_log(LOG_ERROR, "Unknown match type. This should not be possible.\n");
   return CMP_STOP;
}
static int int_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default option handler for signed integers.

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 742 of file config_options.c.

References aco_option::args, ast_log(), ast_parse_arg(), aco_option::flags, ao2_iterator::flags, LOG_WARNING, ast_variable::name, PARSE_DEFAULT, PARSE_IN_RANGE, PARSE_INT32, PARSE_RANGE_DEFAULTS, and ast_variable::value.

Referenced by ast_config_option_default_handler().

                                                                                             {
   int *field = (int *)(obj + opt->args[0]);
   unsigned int flags = PARSE_INT32 | opt->flags;
   int res = 0;
   if (opt->flags & PARSE_IN_RANGE) {
      res = opt->flags & PARSE_DEFAULT ?
         ast_parse_arg(var->value, flags, field, (int) opt->args[1], (int) opt->args[2], opt->args[3]) :
         ast_parse_arg(var->value, flags, field, (int) opt->args[1], (int) opt->args[2]);
      if (res) {
         if (opt->flags & PARSE_RANGE_DEFAULTS) {
            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]);
            res = 0;
         } else if (opt->flags & PARSE_DEFAULT) {
            ast_log(LOG_WARNING, "Failed to set %s=%s, Set to default value %d instead.\n", var->name, var->value, *field);
            res = 0;
         }
      }
   } else if ((opt->flags & PARSE_DEFAULT) && ast_parse_arg(var->value, flags, field, (int) opt->args[1])) {
      ast_log(LOG_WARNING, "Attempted to set %s=%s, but set it to %d instead due to default)\n", var->name, var->value, *field);
   } else {
      res = ast_parse_arg(var->value, flags, field);
   }

   return res;
}
static struct aco_type* internal_aco_type_find ( struct aco_file file,
struct ast_config cfg,
const char *  category 
) [static, read]

Definition at line 298 of file config_options.c.

References ast_log(), ast_strlen_zero(), ast_variable_retrieve(), aco_type::category_match, aco_type::internal, LOG_ERROR, match(), aco_type::matchfield, aco_type::matchfunc, aco_type::matchvalue, aco_type_internal::regex, and aco_file::types.

Referenced by process_category().

{
   size_t x;
   struct aco_type *match;
   const char *val;

   for (x = 0, match = file->types[x]; match; match = file->types[++x]) {
      /* First make sure we are an object that can service this category */
      if (!regexec(match->internal->regex, category, 0, NULL, 0) == !match->category_match) {
         continue;
      }

      /* Then, see if we need to match a particular field */
      if (!ast_strlen_zero(match->matchfield) && (!ast_strlen_zero(match->matchvalue) || match->matchfunc)) {
         if (!(val = ast_variable_retrieve(cfg, category, match->matchfield))) {
            ast_log(LOG_ERROR, "Required match field '%s' not found\n", match->matchfield);
            return NULL;
         }
         if (match->matchfunc) {
            if (!match->matchfunc(val)) {
               continue;
            }
         } else if (strcasecmp(val, match->matchvalue)) {
            continue;
         }
      }
      /* If we get this far, we're a match */
      break;
   }

   return match;
}
static void internal_file_types_destroy ( struct aco_file file) [static]

Definition at line 638 of file config_options.c.

References internal_type_destroy(), and aco_file::types.

Referenced by aco_info_destroy().

{
   size_t x;
   struct aco_type *t;

   for (x = 0, t = file->types[x]; t; t = file->types[++x]) {
      internal_type_destroy(t);
      t = NULL;
   }
}
static enum aco_process_status internal_process_ast_config ( struct aco_info info,
struct aco_file file,
struct ast_config cfg 
) [static]

Definition at line 426 of file config_options.c.

References ACO_PROCESS_ERROR, ACO_PROCESS_OK, ast_category_browse(), ast_strlen_zero(), aco_file::preload, and process_category().

Referenced by aco_process_ast_config(), and aco_process_config().

{
   const char *cat = NULL;

   if (file->preload) {
      int i;
      for (i = 0; !ast_strlen_zero(file->preload[i]); i++) {
         if (process_category(cfg, info, file, file->preload[i], 1)) {
            return ACO_PROCESS_ERROR;
         }
      }
   }

   while ((cat = ast_category_browse(cfg, cat))) {
      if (process_category(cfg, info, file, cat, 0)) {
         return ACO_PROCESS_ERROR;
      }
   }
   return ACO_PROCESS_OK;
}
static void internal_type_destroy ( struct aco_type type) [static]

Definition at line 619 of file config_options.c.

References ao2_cleanup, ast_free, aco_type::internal, aco_type_internal::opts, and aco_type_internal::regex.

Referenced by internal_file_types_destroy(), and internal_type_init().

{
   /* If we've already had all our internal data cleared out,
    * then there's no need to proceed further
    */
   if (!type->internal) {
      return;
   }

   if (type->internal->regex) {
      regfree(type->internal->regex);
      ast_free(type->internal->regex);
   }
   ao2_cleanup(type->internal->opts);
   type->internal->opts = NULL;
   ast_free(type->internal);
   type->internal = NULL;
}
static int internal_type_init ( struct aco_type type) [static]

Definition at line 649 of file config_options.c.

References aco_option_container_alloc(), ast_calloc, build_regex(), aco_type::category, aco_type::internal, internal_type_destroy(), aco_type_internal::opts, and aco_type_internal::regex.

Referenced by aco_info_init().

{
   if (!(type->internal = ast_calloc(1, sizeof(*type->internal)))) {
      return -1;
   }

   if (!(type->internal->regex = build_regex(type->category))) {
      internal_type_destroy(type);
      return -1;
   }

   if (!(type->internal->opts = aco_option_container_alloc())) {
      internal_type_destroy(type);
      return -1;
   }

   return 0;
}
static int is_preload ( struct aco_file file,
const char *  cat 
) [static]

Definition at line 331 of file config_options.c.

References ast_strlen_zero(), and aco_file::preload.

Referenced by process_category().

{
   int i;

   if (!file->preload) {
      return 0;
   }

   for (i = 0; !ast_strlen_zero(file->preload[i]); i++) {
      if (!strcasecmp(cat, file->preload[i])) {
         return 1;
      }
   }
   return 0;
}
static int link_option_to_types ( struct aco_type **  types,
struct aco_option opt 
) [static]

Definition at line 145 of file config_options.c.

References ao2_link, ao2_ref, ao2_unlink, ast_log(), aco_type::internal, LOG_ERROR, aco_type_internal::opts, and type.

Referenced by __aco_option_register(), and aco_option_register_deprecated().

{
   size_t idx = 0;
   struct aco_type *type;

   while ((type = types[idx++])) {
      if (!type->internal) {
         ast_log(LOG_ERROR, "Attempting to register option using uninitialized type\n");
         return -1;
      }
      if (!ao2_link(type->internal->opts, opt)) {
         do {
            ao2_unlink(types[idx]->internal->opts, opt);
         } while (--idx);
         return -1;
      }
   }
   /* The container(s) should hold the only ref to opt */
   ao2_ref(opt, -1);

   return 0;
}
static int noop_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default handler for doing noithing.

Definition at line 881 of file config_options.c.

Referenced by ast_config_option_default_handler().

{
   return 0;
}
static int process_category ( struct ast_config cfg,
struct aco_info info,
struct aco_file file,
const char *  cat,
int  preload 
) [static]

Definition at line 347 of file config_options.c.

References ACO_GLOBAL, ACO_ITEM, aco_process_category_options(), aco_set_defaults(), ao2_cleanup, ao2_link, ast_log(), aco_file::filename, aco_info::internal, internal_aco_type_find(), is_preload(), aco_type::item_alloc, aco_type::item_find, aco_type::item_offset, aco_type::item_pre_process, aco_type::item_prelink, LOG_ERROR, aco_info_internal::pending, type, and aco_type::type.

Referenced by internal_process_ast_config().

                                                                                                                                {
   RAII_VAR(void *, new_item, NULL, ao2_cleanup);
   struct aco_type *type;
   /* For global types, field is the global option struct. For non-global, it is the container for items.
    * We do not grab a reference to these objects, as the info already holds references to them. This
    * pointer is just a convenience. Do not actually store it somewhere. */
   void **field;

   /* Skip preloaded categories if we aren't preloading */
   if (!preload && is_preload(file, cat)) {
      return 0;
   }

   /* Find aco_type by category, if not found it is an error */
   if (!(type = internal_aco_type_find(file, cfg, cat))) {
      ast_log(LOG_ERROR, "Could not find config type for category '%s' in '%s'\n", cat, file->filename);
      return -1;
   }

   field = info->internal->pending + type->item_offset;
   if (!*field) {
      ast_log(LOG_ERROR, "No object to update!\n");
      return -1;
   }

   if (type->type == ACO_GLOBAL && *field) {
      if (aco_process_category_options(type, cfg, cat, *field)) {
         ast_log(LOG_ERROR, "In %s: Processing options for %s failed\n", file->filename, cat);
         return -1;
      }
   } else if (type->type == ACO_ITEM) {
      int new = 0;
      /* If we have multiple definitions of a category in a file, or can set the values from multiple
       * files, look up the entry if we've already added it so we can merge the values together.
       * Otherwise, alloc a new item. */
      if (*field) {
         if (!(new_item = type->item_find(*field, cat))) {
            if (!(new_item = type->item_alloc(cat))) {
               ast_log(LOG_ERROR, "In %s: Could not create item for %s\n", file->filename, cat);
               return -1;
            }
            if (aco_set_defaults(type, cat, new_item)) {
               ast_log(LOG_ERROR, "In %s: Setting defaults for %s failed\n", file->filename, cat);
               return -1;
            }
            new = 1;
         }
      }

      if (type->item_pre_process && type->item_pre_process(new_item)) {
         ast_log(LOG_ERROR, "In %s: Preprocess callback for %s failed\n", file->filename, cat);
         return -1;
      }

      if (aco_process_category_options(type, cfg, cat, new_item)) {
         ast_log(LOG_ERROR, "In %s: Processing options for %s failed\n", file->filename, cat);
         return -1;
      }

      if (type->item_prelink && type->item_prelink(new_item)) {
         ast_log(LOG_ERROR, "In %s: Pre-link callback for %s failed\n", file->filename, cat);
         return -1;
      }

      if (new && !ao2_link(*field, new_item)) {
         ast_log(LOG_ERROR, "In %s: Linking config for %s failed\n", file->filename, cat);
         return -1;
      }
   }
   return 0;
}
static int sockaddr_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default handler for ast_sockaddrs.

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 873 of file config_options.c.

References aco_option::args, ast_parse_arg(), aco_option::flags, PARSE_ADDR, and ast_variable::value.

Referenced by ast_config_option_default_handler().

{
   struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + opt->args[0]);
   return ast_parse_arg(var->value, PARSE_ADDR | opt->flags, field);
}
static int stringfield_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default option handler for stringfields.

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 832 of file config_options.c.

References aco_option::args, ast_string_field_ptr_set_by_fields, and ast_variable::value.

Referenced by ast_config_option_default_handler().

{
   ast_string_field *field = (const char **)(obj + opt->args[0]);
   struct ast_string_field_pool **pool = (struct ast_string_field_pool **)(obj + opt->args[1]);
   struct ast_string_field_mgr *mgr = (struct ast_string_field_mgr *)(obj + opt->args[2]);
   ast_string_field_ptr_set_by_fields(*pool, *mgr, field, var->value);
   return 0;
}
static int uint_handler_fn ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Default option handler for unsigned integers.

Note:
For a description of the opt->flags and opt->args values, see the documentation for enum aco_option_type in config_options.h

Definition at line 772 of file config_options.c.

References aco_option::args, ast_log(), ast_parse_arg(), aco_option::flags, ao2_iterator::flags, LOG_WARNING, ast_variable::name, PARSE_DEFAULT, PARSE_IN_RANGE, PARSE_INT32, PARSE_RANGE_DEFAULTS, and ast_variable::value.

Referenced by ast_config_option_default_handler().

                                                                                              {
   unsigned int *field = (unsigned int *)(obj + opt->args[0]);
   unsigned int flags = PARSE_INT32 | opt->flags;
   int res = 0;
   if (opt->flags & PARSE_IN_RANGE) {
      res = opt->flags & PARSE_DEFAULT ?
         ast_parse_arg(var->value, flags, field, (unsigned int) opt->args[1], (unsigned int) opt->args[2], opt->args[3]) :
         ast_parse_arg(var->value, flags, field, (unsigned int) opt->args[1], (unsigned int) opt->args[2]);
      if (res) {
         if (opt->flags & PARSE_RANGE_DEFAULTS) {
            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]);
            res = 0;
         } else if (opt->flags & PARSE_DEFAULT) {
            ast_log(LOG_WARNING, "Failed to set %s=%s, Set to default value %d instead.\n", var->name, var->value, *field);
            res = 0;
         }
      }
   } else if ((opt->flags & PARSE_DEFAULT) && ast_parse_arg(var->value, flags, field, (unsigned int) opt->args[1])) {
      ast_log(LOG_WARNING, "Attempted to set %s=%s, but set it to %u instead due to default)\n", var->name, var->value, *field);
   } else {
      res = ast_parse_arg(var->value, flags, field);
   }

   return res;
}