Mon Mar 19 11:30:46 2012

Asterisk developer's documentation


config.c File Reference

Configuration File Parser. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include "asterisk/network.h"
#include <time.h>
#include <sys/stat.h>
#include <math.h>
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/channel.h"
#include "asterisk/app.h"
#include "asterisk/astobj2.h"
#include "asterisk/strings.h"
#include "asterisk/netsock2.h"

Go to the source code of this file.

Data Structures

struct  ast_category
struct  ast_category::template_instance_list
struct  ast_category_template_instance
struct  ast_comment
 Structure to keep comments for rewriting configuration files. More...
struct  ast_config
struct  ast_config_include
struct  ast_config_map
struct  cache_file_include
 Hold the mtime for config files, so if we don't need to reread our config, don't. More...
struct  cache_file_mtime
struct  cache_file_mtime::includes
struct  cfmtime_head
struct  inclfile

Defines

#define AST_INCLUDE_GLOB   1
#define CB_SIZE   250
#define COMMENT_END   "--;"
#define COMMENT_META   ';'
#define COMMENT_START   ";--"
#define COMMENT_TAG   '-'
#define MAX_INCLUDE_LEVEL   10
#define MAX_NESTED_COMMENTS   128
#define MIN_VARIABLE_FNAME_SPACE   40

Enumerations

enum  config_cache_attribute_enum { ATTRIBUTE_INCLUDE = 0, ATTRIBUTE_EXEC = 1 }

Functions

static void __init_appendbuf (void)
static struct ast_commentALLOC_COMMENT (struct ast_str *buffer)
static int append_mapping (const char *name, const char *driver, const char *database, const char *table, int priority)
void ast_category_append (struct ast_config *config, struct ast_category *category)
char * ast_category_browse (struct ast_config *config, const char *prev)
 Goes through categories.
int ast_category_delete (struct ast_config *cfg, const char *category)
void ast_category_destroy (struct ast_category *cat)
ast_variableast_category_detach_variables (struct ast_category *cat)
int ast_category_empty (struct ast_config *cfg, const char *category)
 Removes and destroys all variables within a category.
int ast_category_exist (const struct ast_config *config, const char *category_name)
 Check for category duplicates.
ast_variableast_category_first (struct ast_category *cat)
 given a pointer to a category, return the root variable.
ast_categoryast_category_get (const struct ast_config *config, const char *category_name)
 Retrieve a category if it exists.
void ast_category_insert (struct ast_config *config, struct ast_category *cat, const char *match)
 Inserts new category.
ast_categoryast_category_new (const char *name, const char *in_file, int lineno)
 Create a category structure.
void ast_category_rename (struct ast_category *cat, const char *name)
ast_variableast_category_root (struct ast_config *config, char *cat)
 returns the root ast_variable of a config
int ast_check_realtime (const char *family)
 Check if realtime engine is configured for family.
static void ast_comment_destroy (struct ast_comment **comment)
void ast_config_destroy (struct ast_config *cfg)
 Destroys a config.
int ast_config_engine_deregister (struct ast_config_engine *del)
 Deregister config engine.
int ast_config_engine_register (struct ast_config_engine *new)
 Register config engine.
ast_categoryast_config_get_current_category (const struct ast_config *cfg)
 Retrieve the current category name being built.
ast_configast_config_internal_load (const char *filename, struct ast_config *cfg, struct ast_flags flags, const char *suggested_include_file, const char *who_asked)
ast_configast_config_load2 (const char *filename, const char *who_asked, struct ast_flags flags)
 Load a config file.
ast_configast_config_new (void)
 Create a new base configuration structure.
const char * ast_config_option (struct ast_config *cfg, const char *cat, const char *var)
 Retrieve a configuration variable within the configuration set.
void ast_config_set_current_category (struct ast_config *cfg, const struct ast_category *cat)
 Set the category within the configuration as being current.
int ast_config_text_file_save (const char *configfile, const struct ast_config *cfg, const char *generator)
int ast_destroy_realtime (const char *family, const char *keyfield, const char *lookup,...)
 Destroy realtime configuration.
static void ast_destroy_template_list (struct ast_category *cat)
ast_config_includeast_include_find (struct ast_config *conf, const char *included_file)
ast_config_includeast_include_new (struct ast_config *conf, const char *from_file, const char *included_file, int is_exec, const char *exec_file, int from_lineno, char *real_included_file_name, int real_included_file_name_size)
void ast_include_rename (struct ast_config *conf, const char *from_file, const char *to_file)
static void ast_includes_destroy (struct ast_config_include *incls)
ast_variableast_load_realtime (const char *family,...)
 Retrieve realtime configuration.
ast_variableast_load_realtime_all (const char *family,...)
static struct ast_variableast_load_realtime_helper (const char *family, va_list ap)
ast_configast_load_realtime_multientry (const char *family,...)
 Retrieve realtime configuration.
int ast_parse_arg (const char *arg, enum ast_parse_flags flags, void *p_result,...)
 The argument parsing routine.
char * ast_realtime_decode_chunk (char *chunk)
 Remove standard encoding from realtime values, which ensures that a semicolon embedded within a single value is not treated upon retrieval as multiple values.
int ast_realtime_enabled (void)
 Check if there's any realtime engines loaded.
char * ast_realtime_encode_chunk (struct ast_str **dest, ssize_t maxlen, const char *chunk)
 Encodes a chunk of data for realtime.
int ast_realtime_require_field (const char *family,...)
 Inform realtime what fields that may be stored.
int ast_store_realtime (const char *family,...)
 Create realtime configuration.
int ast_unload_realtime (const char *family)
 Release any resources cached for a realtime family.
int ast_update2_realtime (const char *family,...)
 Update realtime configuration.
int ast_update_realtime (const char *family, const char *keyfield, const char *lookup,...)
 Update realtime configuration.
void ast_variable_append (struct ast_category *category, struct ast_variable *variable)
ast_variableast_variable_browse (const struct ast_config *config, const char *category)
 Goes through variables.
int ast_variable_delete (struct ast_category *category, const char *variable, const char *match, const char *line)
static void ast_variable_destroy (struct ast_variable *doomed)
void ast_variable_insert (struct ast_category *category, struct ast_variable *variable, const char *line)
static void ast_variable_move (struct ast_variable *dst_var, struct ast_variable *src_var)
ast_variableast_variable_new (const char *name, const char *value, const char *filename)
const char * ast_variable_retrieve (const struct ast_config *config, const char *category, const char *variable)
 Gets a variable.
int ast_variable_update (struct ast_category *category, const char *variable, const char *value, const char *match, unsigned int object)
 Update variable value within a config.
void ast_variables_destroy (struct ast_variable *v)
 Free variable list.
ast_variableast_variables_dup (struct ast_variable *var)
 Duplicate variable list.
static struct ast_categorycategory_get (const struct ast_config *config, const char *category_name, int ignored)
static void CB_ADD (struct ast_str **cb, const char *str)
static void CB_ADD_LEN (struct ast_str **cb, const char *str, int len)
static void CB_RESET (struct ast_str *cb, struct ast_str *llb)
static struct cache_file_mtimecfmtime_new (const char *filename, const char *who_asked)
static void clear_config_maps (void)
static void config_cache_attribute (const char *configfile, enum config_cache_attribute_enum attrtype, const char *filename, const char *who_asked)
static struct ast_configconfig_text_file_load (const char *database, const char *table, const char *filename, struct ast_config *cfg, struct ast_flags flags, const char *suggested_include_file, const char *who_asked)
int config_text_file_save (const char *configfile, const struct ast_config *cfg, const char *generator)
static int count_linefeeds (char *str)
static int count_linefeeds_in_comments (struct ast_comment *x)
static struct ast_config_enginefind_engine (const char *family, int priority, char *database, int dbsiz, char *table, int tabsiz)
 Find realtime engine for realtime family.
static void gen_header (FILE *f1, const char *configfile, const char *fn, const char *generator)
static char * handle_cli_config_list (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_config_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_core_show_config_mappings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int hash_string (const void *obj, const int flags)
static int hashtab_compare_strings (void *a, void *b, int flags)
static void inclfile_destroy (void *obj)
static void inherit_category (struct ast_category *new, const struct ast_category *base)
static int init_appendbuf (void *data)
static void insert_leading_blank_lines (FILE *fp, struct inclfile *fi, struct ast_comment *precomments, int lineno)
static void move_variables (struct ast_category *old, struct ast_category *new)
static struct ast_categorynext_available_category (struct ast_category *cat)
static int process_text_line (struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, struct ast_flags flags, struct ast_str *comment_buffer, struct ast_str *lline_buffer, const char *suggested_include_file, struct ast_category **last_cat, struct ast_variable **last_var, const char *who_asked)
 parse one line in the configuration.
int read_config_maps (void)
 Exposed re-initialization method for core process.
int register_config_cli (void)
 Exposed initialization method for core process.
static struct inclfileset_fn (char *fn, int fn_size, const char *file, const char *configfile, struct ao2_container *fileset)
static struct ast_variablevariable_clone (const struct ast_variable *old)

Variables

static struct ast_threadstorage appendbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_appendbuf , .custom_init = init_appendbuf , }
static struct ast_cli_entry cli_config []
static struct ast_config_engineconfig_engine_list
static ast_mutex_t config_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static struct ast_config_mapconfig_maps
static char * extconfig_conf = "extconfig.conf"
static struct ast_config_engine text_file_engine


Detailed Description

Configuration File Parser.

Author:
Mark Spencer <markster@digium.com>
Includes the Asterisk Realtime API - ARA See http://wiki.asterisk.org

Definition in file config.c.


Define Documentation

#define AST_INCLUDE_GLOB   1

Definition at line 40 of file config.c.

#define CB_SIZE   250

Definition at line 106 of file config.c.

Referenced by config_text_file_load().

#define COMMENT_END   "--;"

Definition at line 54 of file config.c.

#define COMMENT_META   ';'

Definition at line 55 of file config.c.

Referenced by config_text_file_load().

#define COMMENT_START   ";--"

Definition at line 53 of file config.c.

#define COMMENT_TAG   '-'

Definition at line 56 of file config.c.

Referenced by config_text_file_load().

#define MAX_INCLUDE_LEVEL   10

Definition at line 194 of file config.c.

Referenced by ast_config_new().

#define MAX_NESTED_COMMENTS   128

Definition at line 52 of file config.c.

Referenced by config_text_file_load().

#define MIN_VARIABLE_FNAME_SPACE   40

Define the minimum filename space to reserve for each ast_variable in case the filename is renamed later by ast_include_rename().

Definition at line 63 of file config.c.

Referenced by ast_variable_new().


Enumeration Type Documentation

enum config_cache_attribute_enum

Enumerator:
ATTRIBUTE_INCLUDE 
ATTRIBUTE_EXEC 

Definition at line 1050 of file config.c.

01050                                  {
01051    ATTRIBUTE_INCLUDE = 0,
01052    ATTRIBUTE_EXEC = 1,
01053 };


Function Documentation

static void __init_appendbuf ( void   )  [static]

Definition at line 103 of file config.c.

00109 {

static struct ast_comment* ALLOC_COMMENT ( struct ast_str buffer  )  [static]

Definition at line 130 of file config.c.

References ast_calloc, ast_str_buffer(), and ast_str_strlen().

Referenced by config_text_file_load(), and process_text_line().

00131 { 
00132    struct ast_comment *x = NULL;
00133    if (!buffer || !ast_str_strlen(buffer)) {
00134       return NULL;
00135    }
00136    if ((x = ast_calloc(1, sizeof(*x) + ast_str_strlen(buffer) + 1))) {
00137       strcpy(x->cmt, ast_str_buffer(buffer)); /* SAFE */
00138    }
00139    return x;
00140 }

static int append_mapping ( const char *  name,
const char *  driver,
const char *  database,
const char *  table,
int  priority 
) [static]

Definition at line 2073 of file config.c.

References ast_calloc, ast_verb, config_maps, and map.

Referenced by read_config_maps().

02074 {
02075    struct ast_config_map *map;
02076    char *dst;
02077    int length;
02078 
02079    length = sizeof(*map);
02080    length += strlen(name) + 1;
02081    length += strlen(driver) + 1;
02082    length += strlen(database) + 1;
02083    if (table)
02084       length += strlen(table) + 1;
02085 
02086    if (!(map = ast_calloc(1, length)))
02087       return -1;
02088 
02089    dst = map->stuff; /* writable space starts here */
02090    map->name = strcpy(dst, name);
02091    dst += strlen(dst) + 1;
02092    map->driver = strcpy(dst, driver);
02093    dst += strlen(dst) + 1;
02094    map->database = strcpy(dst, database);
02095    if (table) {
02096       dst += strlen(dst) + 1;
02097       map->table = strcpy(dst, table);
02098    }
02099    map->priority = priority;
02100    map->next = config_maps;
02101    config_maps = map;
02102 
02103    ast_verb(2, "Binding %s to %s/%s/%s\n", map->name, map->driver, map->database, map->table ? map->table : map->name);
02104 
02105    return 0;
02106 }

void ast_category_append ( struct ast_config config,
struct ast_category category 
)

Definition at line 679 of file config.c.

References config, and ast_category::include_level.

Referenced by add_cfg_entry(), add_rt_multi_cfg_entry(), config_curl(), config_ldap(), config_odbc(), config_pgsql(), handle_updates(), process_text_line(), realtime_directory(), realtime_multi_curl(), realtime_multi_ldap(), realtime_multi_odbc(), realtime_multi_pgsql(), and write_password_to_file().

00680 {
00681    if (config->last)
00682       config->last->next = category;
00683    else
00684       config->root = category;
00685    category->include_level = config->include_level;
00686    config->last = category;
00687    config->current = category;
00688 }

char* ast_category_browse ( struct ast_config config,
const char *  prev 
)

Goes through categories.

Parameters:
config Which config structure you wish to "browse"
prev A pointer to a previous category.
This function is kind of non-intuitive in it's use. To begin, one passes NULL as the second argument. It will return a pointer to the string of the first category in the file. From here on after, one must then pass the previous usage's return value as the second pointer, and it will return a pointer to the category name afterwards.

Return values:
a category on success
NULL on failure/no-more-categories

Definition at line 766 of file config.c.

References config, ast_category::name, ast_category::next, and next_available_category().

Referenced by __queues_show(), action_getconfig(), action_getconfigjson(), action_listcategories(), actual_load_config(), aji_load_config(), ast_cli_perms_init(), complete_sipnotify(), conf_exec(), config_load(), get_insecure_variable_from_config(), get_insecure_variable_from_sipregs(), gtalk_load_config(), iax_provision_reload(), jingle_load_config(), load_config(), load_indications(), load_module(), load_moh_classes(), load_odbc_config(), load_pktccops_config(), load_tech_calendars(), misdn_cfg_init(), osp_load(), parse_config(), pbx_load_config(), pbx_load_users(), queues_data_provider_get(), read_agent_config(), realtime_directory(), realtime_switch_common(), reload(), reload_config(), reload_followme(), reload_queue_rules(), reload_queues(), rpt_master(), search_directory(), search_directory_sub(), set_config(), setup_dahdi_int(), show_users_realtime(), sla_load_config(), update_realtime_members(), and vm_change_password().

00767 {  
00768    struct ast_category *cat;
00769 
00770    if (!prev) {
00771       /* First time browse. */
00772       cat = config->root;
00773    } else if (config->last_browse && (config->last_browse->name == prev)) {
00774       /* Simple last browse found. */
00775       cat = config->last_browse->next;
00776    } else {
00777       /*
00778        * Config changed since last browse.
00779        *
00780        * First try cheap last browse search. (Rebrowsing a different
00781        * previous category?)
00782        */
00783       for (cat = config->root; cat; cat = cat->next) {
00784          if (cat->name == prev) {
00785             /* Found it. */
00786             cat = cat->next;
00787             break;
00788          }
00789       }
00790       if (!cat) {
00791          /*
00792           * Have to do it the hard way. (Last category was deleted and
00793           * re-added?)
00794           */
00795          for (cat = config->root; cat; cat = cat->next) {
00796             if (!strcasecmp(cat->name, prev)) {
00797                /* Found it. */
00798                cat = cat->next;
00799                break;
00800             }
00801          }
00802       }
00803    }
00804    
00805    if (cat)
00806       cat = next_available_category(cat);
00807 
00808    config->last_browse = cat;
00809    return (cat) ? cat->name : NULL;
00810 }

int ast_category_delete ( struct ast_config cfg,
const char *  category 
)

Definition at line 932 of file config.c.

References ast_category_destroy(), ast_config::last, ast_category::next, and ast_config::root.

Referenced by handle_updates().

00933 {
00934    struct ast_category *prev=NULL, *cat;
00935 
00936    cat = cfg->root;
00937    while (cat) {
00938       if (cat->name == category) {
00939          if (prev) {
00940             prev->next = cat->next;
00941             if (cat == cfg->last)
00942                cfg->last = prev;
00943          } else {
00944             cfg->root = cat->next;
00945             if (cat == cfg->last)
00946                cfg->last = NULL;
00947          }
00948          ast_category_destroy(cat);
00949          return 0;
00950       }
00951       prev = cat;
00952       cat = cat->next;
00953    }
00954 
00955    prev = NULL;
00956    cat = cfg->root;
00957    while (cat) {
00958       if (!strcasecmp(cat->name, category)) {
00959          if (prev) {
00960             prev->next = cat->next;
00961             if (cat == cfg->last)
00962                cfg->last = prev;
00963          } else {
00964             cfg->root = cat->next;
00965             if (cat == cfg->last)
00966                cfg->last = NULL;
00967          }
00968          ast_category_destroy(cat);
00969          return 0;
00970       }
00971       prev = cat;
00972       cat = cat->next;
00973    }
00974    return -1;
00975 }

void ast_category_destroy ( struct ast_category cat  ) 

Definition at line 718 of file config.c.

References ast_comment_destroy(), ast_destroy_template_list(), ast_free, ast_variables_destroy(), ast_category::file, ast_category::last, ast_category::precomments, ast_category::root, ast_category::sameline, and ast_category::trailing.

Referenced by add_cfg_entry(), ast_category_delete(), ast_category_new(), ast_config_destroy(), process_text_line(), and realtime_multi_odbc().

00719 {
00720    ast_variables_destroy(cat->root);
00721    cat->root = NULL;
00722    cat->last = NULL;
00723    ast_comment_destroy(&cat->precomments);
00724    ast_comment_destroy(&cat->sameline);
00725    ast_comment_destroy(&cat->trailing);
00726    ast_destroy_template_list(cat);
00727    ast_free(cat->file);
00728    ast_free(cat);
00729 }

struct ast_variable* ast_category_detach_variables ( struct ast_category cat  ) 

Definition at line 812 of file config.c.

References ast_category::last, and ast_category::root.

Referenced by realtime_switch_common().

00813 {
00814    struct ast_variable *v;
00815 
00816    v = cat->root;
00817    cat->root = NULL;
00818    cat->last = NULL;
00819 
00820    return v;
00821 }

int ast_category_empty ( struct ast_config cfg,
const char *  category 
)

Removes and destroys all variables within a category.

Return values:
0 if the category was found and emptied
-1 if the category was not found

Definition at line 977 of file config.c.

References ast_variables_destroy(), ast_category::last, ast_category::name, ast_category::next, ast_category::root, and ast_config::root.

Referenced by handle_updates().

00978 {
00979    struct ast_category *cat;
00980 
00981    for (cat = cfg->root; cat; cat = cat->next) {
00982       if (!strcasecmp(cat->name, category))
00983          continue;
00984       ast_variables_destroy(cat->root);
00985       cat->root = NULL;
00986       cat->last = NULL;
00987       return 0;
00988    }
00989 
00990    return -1;
00991 }

int ast_category_exist ( const struct ast_config config,
const char *  category_name 
)

Check for category duplicates.

Parameters:
config which config to use
category_name name of the category you're looking for
This will search through the categories within a given config file for a match.

Returns:
non-zero if found

Definition at line 674 of file config.c.

References ast_category_get(), and config.

00675 {
00676    return !!ast_category_get(config, category_name);
00677 }

struct ast_variable* ast_category_first ( struct ast_category cat  ) 

given a pointer to a category, return the root variable.

return the first var of a category

Definition at line 752 of file config.c.

References ast_category::root.

Referenced by process_text_line().

00753 {
00754    return (cat) ? cat->root : NULL;
00755 }

struct ast_category* ast_category_get ( const struct ast_config config,
const char *  category_name 
)

Retrieve a category if it exists.

Parameters:
config which config to use
category_name name of the category you're looking for
This will search through the categories within a given config file for a match.

Return values:
pointer to category if found
NULL if not.

Definition at line 669 of file config.c.

References category_get(), and config.

Referenced by ast_category_exist(), ast_category_root(), ast_variable_browse(), handle_updates(), realtime_directory(), realtime_switch_common(), vm_change_password(), and vm_forwardoptions().

00670 {
00671    return category_get(config, category_name, 0);
00672 }

void ast_category_insert ( struct ast_config config,
struct ast_category cat,
const char *  match 
)

Inserts new category.

Parameters:
config which config to use
cat newly created category to insert
match which category to insert above
This function is used to insert a new category above another category matching the match parameter.

Definition at line 690 of file config.c.

References config, ast_category::name, and ast_category::next.

Referenced by handle_updates().

00691 {
00692    struct ast_category *cur_category;
00693 
00694    if (!cat || !match)
00695       return;
00696    if (!strcasecmp(config->root->name, match)) {
00697       cat->next = config->root;
00698       config->root = cat;
00699       return;
00700    } 
00701    for (cur_category = config->root; cur_category; cur_category = cur_category->next) {
00702       if (!strcasecmp(cur_category->next->name, match)) {
00703          cat->next = cur_category->next;
00704          cur_category->next = cat;
00705          break;
00706       }
00707    }
00708 }

struct ast_category* ast_category_new ( const char *  name,
const char *  in_file,
int  lineno 
)

Create a category structure.

Definition at line 633 of file config.c.

References ast_calloc, ast_category_destroy(), ast_copy_string(), and ast_strdup.

Referenced by add_cfg_entry(), add_rt_multi_cfg_entry(), config_curl(), config_ldap(), config_odbc(), config_pgsql(), handle_updates(), process_text_line(), realtime_directory(), realtime_multi_curl(), realtime_multi_ldap(), realtime_multi_odbc(), realtime_multi_pgsql(), and write_password_to_file().

00634 {
00635    struct ast_category *category;
00636 
00637    category = ast_calloc(1, sizeof(*category));
00638    if (!category) {
00639       return NULL;
00640    }
00641    category->file = ast_strdup(in_file);
00642    if (!category->file) {
00643       ast_category_destroy(category);
00644       return NULL;
00645    }
00646    ast_copy_string(category->name, name, sizeof(category->name));
00647    category->lineno = lineno; /* if you don't know the lineno, set it to 999999 or something real big */
00648    return category;
00649 }

void ast_category_rename ( struct ast_category cat,
const char *  name 
)

Definition at line 823 of file config.c.

References ast_copy_string(), and ast_category::name.

Referenced by handle_updates(), realtime_multi_curl(), realtime_multi_ldap(), realtime_multi_odbc(), and realtime_multi_pgsql().

00824 {
00825    ast_copy_string(cat->name, name, sizeof(cat->name));
00826 }

struct ast_variable* ast_category_root ( struct ast_config config,
char *  cat 
)

returns the root ast_variable of a config

Parameters:
config pointer to an ast_config data structure
cat name of the category for which you want the root
Returns:
the category specified

Definition at line 757 of file config.c.

References ast_category_get(), config, and ast_category::root.

Referenced by get_insecure_variable_from_config(), and get_insecure_variable_from_sipregs().

00758 {
00759    struct ast_category *category = ast_category_get(config, cat);
00760 
00761    if (category)
00762       return category->root;
00763    return NULL;
00764 }

int ast_check_realtime ( const char *  family  ) 

Check if realtime engine is configured for family.

Parameters:
family which family/config to be checked
Returns:
1 if family is configured in realtime and engine exists

Definition at line 2394 of file config.c.

References ast_realtime_enabled(), and find_engine().

Referenced by __queues_show(), _sip_show_peer(), _sip_show_peers(), ast_queue_log(), close_mailbox(), copy_plain_file(), destroy_association(), find_realtime_gw(), handle_response_peerpoke(), handle_voicemail_show_users(), load_module(), load_moh_classes(), local_ast_moh_start(), logger_queue_rt_start(), realtime_peer(), realtime_update_peer(), rename_file(), sip_poke_noanswer(), sip_show_settings(), and vm_delete().

02395 {
02396    struct ast_config_engine *eng;
02397    if (!ast_realtime_enabled()) {
02398       return 0;   /* There are no engines at all so fail early */
02399    }
02400 
02401    eng = find_engine(family, 1, NULL, 0, NULL, 0);
02402    if (eng)
02403       return 1;
02404    return 0;
02405 }

static void ast_comment_destroy ( struct ast_comment **  comment  )  [static]

Definition at line 508 of file config.c.

References ast_free, comment, and ast_comment::next.

Referenced by ast_category_destroy(), and ast_variable_destroy().

00509 {
00510    struct ast_comment *n, *p;
00511 
00512    for (p = *comment; p; p = n) {
00513       n = p->next;
00514       ast_free(p);
00515    }
00516 
00517    *comment = NULL;
00518 }

void ast_config_destroy ( struct ast_config config  ) 

Destroys a config.

Parameters:
config pointer to config data structure
Free memory associated with a given config

Definition at line 993 of file config.c.

References ast_category_destroy(), ast_free, ast_includes_destroy(), ast_config::includes, ast_category::next, and ast_config::root.

Referenced by __ast_http_post_load(), __ast_udptl_reload(), __queues_show(), _dsp_init(), action_getconfig(), action_getconfigjson(), action_listcategories(), action_updateconfig(), advanced_options(), ast_config_load2(), ast_load_realtime_multientry(), conf_exec(), config_function_read(), config_load(), config_module(), directory_exec(), do_reload(), festival_exec(), find_conf(), get_insecure_variable_from_sippeers(), get_insecure_variable_from_sipregs(), handle_cli_dialplan_save(), iax_provision_reload(), initialize_cc_max_requests(), load_config(), load_config_meetme(), load_indications(), load_module(), load_realtime_queue(), load_rpt_vars(), make_email_file(), misdn_cfg_init(), node_lookup(), odbc_load_module(), osp_load(), parse_config(), pbx_load_users(), play_message(), prep_email_sub_vars(), private_enum_init(), queues_data_provider_get(), read_agent_config(), read_config_maps(), realtime_directory(), realtime_multi_handler(), realtime_multi_pgsql(), realtime_switch_common(), reload(), reload_config(), reload_followme(), reload_module(), reload_queue_rules(), reload_queues(), rpt_master(), rtp_reload(), run_startup_commands(), set_config(), setup_dahdi_int(), show_users_realtime(), sla_load_config(), store_config(), tds_load_module(), unload_module(), update_realtime_members(), and vm_forwardoptions().

00994 {
00995    struct ast_category *cat, *catn;
00996 
00997    if (!cfg)
00998       return;
00999 
01000    ast_includes_destroy(cfg->includes);
01001 
01002    cat = cfg->root;
01003    while (cat) {
01004       catn = cat;
01005       cat = cat->next;
01006       ast_category_destroy(catn);
01007    }
01008    ast_free(cfg);
01009 }

int ast_config_engine_deregister ( struct ast_config_engine del  ) 

Deregister config engine.

Return values:
0 Always

Definition at line 2204 of file config.c.

References ast_mutex_lock, ast_mutex_unlock, config_engine_list, config_lock, last, and ast_config_engine::next.

Referenced by unload_module().

02205 {
02206    struct ast_config_engine *ptr, *last=NULL;
02207 
02208    ast_mutex_lock(&config_lock);
02209 
02210    for (ptr = config_engine_list; ptr; ptr=ptr->next) {
02211       if (ptr == del) {
02212          if (last)
02213             last->next = ptr->next;
02214          else
02215             config_engine_list = ptr->next;
02216          break;
02217       }
02218       last = ptr;
02219    }
02220 
02221    ast_mutex_unlock(&config_lock);
02222 
02223    return 0;
02224 }

int ast_config_engine_register ( struct ast_config_engine newconfig  ) 

Register config engine.

Return values:
1 Always

Definition at line 2185 of file config.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, config_engine_list, config_lock, LOG_NOTICE, ast_config_engine::name, and ast_config_engine::next.

Referenced by load_module().

02186 {
02187    struct ast_config_engine *ptr;
02188 
02189    ast_mutex_lock(&config_lock);
02190 
02191    if (!config_engine_list) {
02192       config_engine_list = new;
02193    } else {
02194       for (ptr = config_engine_list; ptr->next; ptr=ptr->next);
02195       ptr->next = new;
02196    }
02197 
02198    ast_mutex_unlock(&config_lock);
02199    ast_log(LOG_NOTICE,"Registered Config Engine %s\n", new->name);
02200 
02201    return 1;
02202 }

struct ast_category* ast_config_get_current_category ( const struct ast_config cfg  ) 

Retrieve the current category name being built.

API for backend configuration engines while building a configuration set.

Definition at line 1011 of file config.c.

References ast_config::current.

Referenced by config_curl(), config_odbc(), and config_text_file_load().

01012 {
01013    return cfg->current;
01014 }

struct ast_config* ast_config_internal_load ( const char *  filename,
struct ast_config cfg,
struct ast_flags  flags,
const char *  suggested_include_file,
const char *  who_asked 
)

Definition at line 2266 of file config.c.

References ast_log(), ast_test_flag, config_engine_list, CONFIG_FLAG_NOREALTIME, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, db, find_engine(), ast_config::include_level, ast_config_engine::load_func, LOG_WARNING, ast_config::max_include_level, table, and text_file_engine.

Referenced by add_cfg_entry(), ast_config_load2(), config_curl(), config_ldap(), config_odbc(), config_pgsql(), process_text_line(), and read_config_maps().

02267 {
02268    char db[256];
02269    char table[256];
02270    struct ast_config_engine *loader = &text_file_engine;
02271    struct ast_config *result; 
02272 
02273    /* The config file itself bumps include_level by 1 */
02274    if (cfg->max_include_level > 0 && cfg->include_level == cfg->max_include_level + 1) {
02275       ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
02276       return NULL;
02277    }
02278 
02279    cfg->include_level++;
02280 
02281    if (!ast_test_flag(&flags, CONFIG_FLAG_NOREALTIME) && config_engine_list) {
02282       struct ast_config_engine *eng;
02283 
02284       eng = find_engine(filename, 1, db, sizeof(db), table, sizeof(table));
02285 
02286 
02287       if (eng && eng->load_func) {
02288          loader = eng;
02289       } else {
02290          eng = find_engine("global", 1, db, sizeof(db), table, sizeof(table));
02291          if (eng && eng->load_func)
02292             loader = eng;
02293       }
02294    }
02295 
02296    result = loader->load_func(db, table, filename, cfg, flags, suggested_include_file, who_asked);
02297 
02298    if (result && result != CONFIG_STATUS_FILEINVALID && result != CONFIG_STATUS_FILEUNCHANGED)
02299       result->include_level--;
02300    else if (result != CONFIG_STATUS_FILEINVALID)
02301       cfg->include_level--;
02302 
02303    return result;
02304 }

struct ast_config* ast_config_load2 ( const char *  filename,
const char *  who_asked,
struct ast_flags  flags 
)

Load a config file.

Parameters:
filename path of file to open. If no preceding '/' character, path is considered relative to AST_CONFIG_DIR
who_asked The module which is making this request.
flags Optional flags: CONFIG_FLAG_WITHCOMMENTS - load the file with comments intact; CONFIG_FLAG_FILEUNCHANGED - check the file mtime and return CONFIG_STATUS_FILEUNCHANGED if the mtime is the same; or CONFIG_FLAG_NOCACHE - don't cache file mtime (main purpose of this option is to save memory on temporary files).
Create a config structure from a given configuration file.

Returns:
an ast_config data structure on success
Return values:
NULL on error

Definition at line 2306 of file config.c.

References ast_config_destroy(), ast_config_internal_load(), ast_config_new(), CONFIG_STATUS_FILEINVALID, and CONFIG_STATUS_FILEUNCHANGED.

Referenced by __ast_http_load(), __ast_http_post_load(), __ast_udptl_reload(), __init_manager(), _dsp_init(), action_getconfig(), action_getconfigjson(), action_listcategories(), action_updateconfig(), ast_cli_perms_init(), ast_readconfig(), do_reload(), iax_provision_reload(), init_logger_chain(), initialize_cc_max_requests(), load_config(), load_indications(), load_modules(), misdn_cfg_init(), private_enum_init(), rtp_reload(), run_startup_commands(), and set_config().

02307 {
02308    struct ast_config *cfg;
02309    struct ast_config *result;
02310 
02311    cfg = ast_config_new();
02312    if (!cfg)
02313       return NULL;
02314 
02315    result = ast_config_internal_load(filename, cfg, flags, "", who_asked);
02316    if (!result || result == CONFIG_STATUS_FILEUNCHANGED || result == CONFIG_STATUS_FILEINVALID)
02317       ast_config_destroy(cfg);
02318 
02319    return result;
02320 }

struct ast_config* ast_config_new ( void   ) 

Create a new base configuration structure.

Definition at line 844 of file config.c.

References ast_calloc, config, and MAX_INCLUDE_LEVEL.

Referenced by ast_config_load2(), load_realtime_queue(), read_config_maps(), realtime_multi_curl(), realtime_multi_handler(), realtime_multi_ldap(), realtime_multi_odbc(), realtime_multi_pgsql(), setup_dahdi_int(), and write_password_to_file().

00845 {
00846    struct ast_config *config;
00847 
00848    if ((config = ast_calloc(1, sizeof(*config))))
00849       config->max_include_level = MAX_INCLUDE_LEVEL;
00850    return config;
00851 }

const char* ast_config_option ( struct ast_config cfg,
const char *  cat,
const char *  var 
)

Retrieve a configuration variable within the configuration set.

Retrieves the named variable var within category cat of configuration set cfg. If not found, attempts to retrieve the named variable var from within category general.

Returns:
Value of var, or NULL if not found.

Definition at line 574 of file config.c.

References ast_variable_retrieve().

Referenced by actual_load_config(), pbx_load_users(), and search_directory_sub().

00575 {
00576    const char *tmp;
00577    tmp = ast_variable_retrieve(cfg, cat, var);
00578    if (!tmp) {
00579       tmp = ast_variable_retrieve(cfg, "general", var);
00580    }
00581    return tmp;
00582 }

void ast_config_set_current_category ( struct ast_config cfg,
const struct ast_category cat 
)

Set the category within the configuration as being current.

API for backend configuration engines while building a configuration set.

Definition at line 1016 of file config.c.

References ast_config::current.

01017 {
01018    /* cast below is just to silence compiler warning about dropping "const" */
01019    cfg->current = (struct ast_category *) cat;
01020 }

int ast_config_text_file_save ( const char *  configfile,
const struct ast_config cfg,
const char *  generator 
)

Definition at line 1803 of file config.c.

References ao2_container_alloc, ao2_ref, ast_debug, AST_LIST_EMPTY, AST_LIST_LAST, AST_LIST_TRAVERSE, ast_verb, ast_comment::cmt, errno, ast_config_include::exec, ast_config_include::exec_file, f, ast_category::file, gen_header(), hash_string(), hashtab_compare_strings(), ast_category::ignored, ast_config_include::include_location_file, ast_config_include::include_location_lineno, ast_config_include::included_file, ast_config::includes, insert_leading_blank_lines(), ast_category_template_instance::inst, ast_category::lineno, ast_variable::name, ast_category_template_instance::name, ast_category::name, ast_category::next, ast_variable::next, ast_category_template_instance::next, ast_comment::next, ast_config_include::next, option_debug, ast_config_include::output, ast_category::precomments, ast_category::root, ast_config::root, ast_category::sameline, set_fn(), ast_category::template_instances, ast_category::trailing, ast_variable::value, and var.

Referenced by action_updateconfig(), config_text_file_save(), vm_change_password(), vm_forwardoptions(), and write_password_to_file().

01804 {
01805    FILE *f;
01806    char fn[PATH_MAX];
01807    struct ast_variable *var;
01808    struct ast_category *cat;
01809    struct ast_comment *cmt;
01810    struct ast_config_include *incl;
01811    int blanklines = 0;
01812    struct ao2_container *fileset;
01813    struct inclfile *fi;
01814 
01815    fileset = ao2_container_alloc(1023, hash_string, hashtab_compare_strings);
01816    if (!fileset) {
01817       /* Container creation failed. */
01818       return -1;
01819    }
01820 
01821    /* reset all the output flags, in case this isn't our first time saving this data */
01822    for (incl = cfg->includes; incl; incl = incl->next) {
01823       incl->output = 0;
01824    }
01825 
01826    /* go thru all the inclusions and make sure all the files involved (configfile plus all its inclusions)
01827       are all truncated to zero bytes and have that nice header*/
01828    for (incl = cfg->includes; incl; incl = incl->next) {
01829       if (!incl->exec) { /* leave the execs alone -- we'll write out the #exec directives, but won't zero out the include files or exec files*/
01830          /* normally, fn is just set to incl->included_file, prepended with config dir if relative */
01831          fi = set_fn(fn, sizeof(fn), incl->included_file, configfile, fileset);
01832          f = fopen(fn, "w");
01833          if (f) {
01834             gen_header(f, configfile, fn, generator);
01835             fclose(f); /* this should zero out the file */
01836          } else {
01837             ast_debug(1, "Unable to open for writing: %s\n", fn);
01838             ast_verb(2, "Unable to write %s (%s)", fn, strerror(errno));
01839          }
01840          if (fi) {
01841             ao2_ref(fi, -1);
01842          }
01843       }
01844    }
01845 
01846    /* just set fn to absolute ver of configfile */
01847    fi = set_fn(fn, sizeof(fn), 0, configfile, fileset);
01848    if (
01849 #ifdef __CYGWIN__
01850       (f = fopen(fn, "w+"))
01851 #else
01852       (f = fopen(fn, "w"))
01853 #endif
01854       ) {
01855       ast_verb(2, "Saving '%s': ", fn);
01856       gen_header(f, configfile, fn, generator);
01857       cat = cfg->root;
01858       fclose(f);
01859       if (fi) {
01860          ao2_ref(fi, -1);
01861       }
01862 
01863       /* from here out, we open each involved file and concat the stuff we need to add to the end and immediately close... */
01864       /* since each var, cat, and associated comments can come from any file, we have to be
01865          mobile, and open each file, print, and close it on an entry-by-entry basis */
01866 
01867       while (cat) {
01868          fi = set_fn(fn, sizeof(fn), cat->file, configfile, fileset);
01869          f = fopen(fn, "a");
01870          if (!f) {
01871             ast_debug(1, "Unable to open for writing: %s\n", fn);
01872             ast_verb(2, "Unable to write %s (%s)", fn, strerror(errno));
01873             if (fi) {
01874                ao2_ref(fi, -1);
01875             }
01876             ao2_ref(fileset, -1);
01877             return -1;
01878          }
01879 
01880          /* dump any includes that happen before this category header */
01881          for (incl=cfg->includes; incl; incl = incl->next) {
01882             if (strcmp(incl->include_location_file, cat->file) == 0){
01883                if (cat->lineno > incl->include_location_lineno && !incl->output) {
01884                   if (incl->exec)
01885                      fprintf(f,"#exec \"%s\"\n", incl->exec_file);
01886                   else
01887                      fprintf(f,"#include \"%s\"\n", incl->included_file);
01888                   incl->output = 1;
01889                }
01890             }
01891          }
01892 
01893          insert_leading_blank_lines(f, fi, cat->precomments, cat->lineno);
01894          /* Dump section with any appropriate comment */
01895          for (cmt = cat->precomments; cmt; cmt=cmt->next) {
01896             char *cmtp = cmt->cmt;
01897             while (*cmtp == ';' && *(cmtp+1) == '!') {
01898                char *cmtp2 = strchr(cmtp+1, '\n');
01899                if (cmtp2)
01900                   cmtp = cmtp2+1;
01901                else cmtp = 0;
01902             }
01903             if (cmtp)
01904                fprintf(f,"%s", cmtp);
01905          }
01906          fprintf(f, "[%s]", cat->name);
01907          if (cat->ignored || !AST_LIST_EMPTY(&cat->template_instances)) {
01908             fprintf(f, "(");
01909             if (cat->ignored) {
01910                fprintf(f, "!");
01911             }
01912             if (cat->ignored && !AST_LIST_EMPTY(&cat->template_instances)) {
01913                fprintf(f, ",");
01914             }
01915             if (!AST_LIST_EMPTY(&cat->template_instances)) {
01916                struct ast_category_template_instance *x;
01917                AST_LIST_TRAVERSE(&cat->template_instances, x, next) {
01918                   fprintf(f,"%s",x->name);
01919                   if (x != AST_LIST_LAST(&cat->template_instances))
01920                      fprintf(f,",");
01921                }
01922             }
01923             fprintf(f, ")");
01924          }
01925          for(cmt = cat->sameline; cmt; cmt=cmt->next)
01926          {
01927             fprintf(f,"%s", cmt->cmt);
01928          }
01929          if (!cat->sameline)
01930             fprintf(f,"\n");
01931          for (cmt = cat->trailing; cmt; cmt=cmt->next) {
01932             if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
01933                fprintf(f,"%s", cmt->cmt);
01934          }
01935          fclose(f);
01936          if (fi) {
01937             ao2_ref(fi, -1);
01938          }
01939 
01940          var = cat->root;
01941          while (var) {
01942             struct ast_category_template_instance *x;
01943             int found = 0;
01944             AST_LIST_TRAVERSE(&cat->template_instances, x, next) {
01945                struct ast_variable *v;
01946                for (v = x->inst->root; v; v = v->next) {
01947                   if (!strcasecmp(var->name, v->name) && !strcmp(var->value, v->value)) {
01948                      found = 1;
01949                      break;
01950                   }
01951                }
01952                if (found)
01953                   break;
01954             }
01955             if (found) {
01956                var = var->next;
01957                continue;
01958             }
01959             fi = set_fn(fn, sizeof(fn), var->file, configfile, fileset);
01960             f = fopen(fn, "a");
01961             if (!f) {
01962                ast_debug(1, "Unable to open for writing: %s\n", fn);
01963                ast_verb(2, "Unable to write %s (%s)", fn, strerror(errno));
01964                if (fi) {
01965                   ao2_ref(fi, -1);
01966                }
01967                ao2_ref(fileset, -1);
01968                return -1;
01969             }
01970 
01971             /* dump any includes that happen before this category header */
01972             for (incl=cfg->includes; incl; incl = incl->next) {
01973                if (strcmp(incl->include_location_file, var->file) == 0){
01974                   if (var->lineno > incl->include_location_lineno && !incl->output) {
01975                      if (incl->exec)
01976                         fprintf(f,"#exec \"%s\"\n", incl->exec_file);
01977                      else
01978                         fprintf(f,"#include \"%s\"\n", incl->included_file);
01979                      incl->output = 1;
01980                   }
01981                }
01982             }
01983 
01984             insert_leading_blank_lines(f, fi, var->precomments, var->lineno);
01985             for (cmt = var->precomments; cmt; cmt=cmt->next) {
01986                if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
01987                   fprintf(f,"%s", cmt->cmt);
01988             }
01989             if (var->sameline)
01990                fprintf(f, "%s %s %s  %s", var->name, (var->object ? "=>" : "="), var->value, var->sameline->cmt);
01991             else
01992                fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value);
01993             for (cmt = var->trailing; cmt; cmt=cmt->next) {
01994                if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
01995                   fprintf(f,"%s", cmt->cmt);
01996             }
01997             if (var->blanklines) {
01998                blanklines = var->blanklines;
01999                while (blanklines--)
02000                   fprintf(f, "\n");
02001             }
02002 
02003             fclose(f);
02004             if (fi) {
02005                ao2_ref(fi, -1);
02006             }
02007 
02008             var = var->next;
02009          }
02010          cat = cat->next;
02011       }
02012       if (!option_debug)
02013          ast_verb(2, "Saved\n");
02014    } else {
02015       ast_debug(1, "Unable to open for writing: %s\n", fn);
02016       ast_verb(2, "Unable to write (%s)", strerror(errno));
02017       if (fi) {
02018          ao2_ref(fi, -1);
02019       }
02020       ao2_ref(fileset, -1);
02021       return -1;
02022    }
02023 
02024    /* Now, for files with trailing #include/#exec statements,
02025       we have to make sure every entry is output */
02026    for (incl=cfg->includes; incl; incl = incl->next) {
02027       if (!incl->output) {
02028          /* open the respective file */
02029          fi = set_fn(fn, sizeof(fn), incl->include_location_file, configfile, fileset);
02030          f = fopen(fn, "a");
02031          if (!f) {
02032             ast_debug(1, "Unable to open for writing: %s\n", fn);
02033             ast_verb(2, "Unable to write %s (%s)", fn, strerror(errno));
02034             if (fi) {
02035                ao2_ref(fi, -1);
02036             }
02037             ao2_ref(fileset, -1);
02038             return -1;
02039          }
02040 
02041          /* output the respective include */
02042          if (incl->exec)
02043             fprintf(f,"#exec \"%s\"\n", incl->exec_file);
02044          else
02045             fprintf(f,"#include \"%s\"\n", incl->included_file);
02046          fclose(f);
02047          incl->output = 1;
02048          if (fi) {
02049             ao2_ref(fi, -1);
02050          }
02051       }
02052    }
02053    ao2_ref(fileset, -1); /* this should destroy the hash container */
02054 
02055    return 0;
02056 }

int ast_destroy_realtime ( const char *  family,
const char *  keyfield,
const char *  lookup,
  ... 
)

Destroy realtime configuration.

Parameters:
family which family/config to be destroyed
keyfield which field to use as the key
lookup which value to look for in the key field to match the entry.
This function is used to destroy an entry in realtime configuration space. Additional params are used as keys.

Returns:
Number of rows affected, or -1 on error.
Note:
You should use the constant SENTINEL to terminate arguments, in order to preserve cross-platform compatibility.

Definition at line 2557 of file config.c.

References db, ast_config_engine::destroy_func, find_engine(), and table.

Referenced by cli_realtime_destroy(), function_realtime_readdestroy(), and vm_delete().

02558 {
02559    struct ast_config_engine *eng;
02560    int res = -1, i;
02561    char db[256];
02562    char table[256];
02563    va_list ap;
02564 
02565    va_start(ap, lookup);
02566    for (i = 1; ; i++) {
02567       if ((eng = find_engine(family, i, db, sizeof(db), table, sizeof(table)))) {
02568          if (eng->destroy_func && !(res = eng->destroy_func(db, table, keyfield, lookup, ap))) {
02569             break;
02570          }
02571       } else {
02572          break;
02573       }
02574    }
02575    va_end(ap);
02576 
02577    return res;
02578 }

static void ast_destroy_template_list ( struct ast_category cat  )  [static]

Definition at line 710 of file config.c.

References ast_free, AST_LIST_REMOVE_HEAD, ast_category_template_instance::next, and ast_category::template_instances.

Referenced by ast_category_destroy().

00711 {
00712    struct ast_category_template_instance *x;
00713 
00714    while ((x = AST_LIST_REMOVE_HEAD(&cat->template_instances, next)))
00715       ast_free(x);
00716 }

struct ast_config_include* ast_include_find ( struct ast_config conf,
const char *  included_file 
)

Definition at line 460 of file config.c.

References ast_config_include::included_file, ast_config::includes, and ast_config_include::next.

Referenced by ast_include_new().

00461 {
00462    struct ast_config_include *x;
00463    for (x=conf->includes;x;x=x->next) {
00464       if (strcmp(x->included_file,included_file) == 0)
00465          return x;
00466    }
00467    return 0;
00468 }

struct ast_config_include* ast_include_new ( struct ast_config conf,
const char *  from_file,
const char *  included_file,
int  is_exec,
const char *  exec_file,
int  from_lineno,
char *  real_included_file_name,
int  real_included_file_name_size 
)

Definition at line 320 of file config.c.

References ast_calloc, ast_include_find(), ast_includes_destroy(), ast_log(), ast_strdup, ast_strlen_zero(), ast_config::includes, and LOG_WARNING.

Referenced by process_text_line().

00321 {
00322    /* a file should be included ONCE. Otherwise, if one of the instances is changed,
00323     * then all be changed. -- how do we know to include it? -- Handling modified 
00324     * instances is possible, I'd have
00325     * to create a new master for each instance. */
00326    struct ast_config_include *inc;
00327    struct stat statbuf;
00328    
00329    inc = ast_include_find(conf, included_file);
00330    if (inc) {
00331       do {
00332          inc->inclusion_count++;
00333          snprintf(real_included_file_name, real_included_file_name_size, "%s~~%d", included_file, inc->inclusion_count);
00334       } while (stat(real_included_file_name, &statbuf) == 0);
00335       ast_log(LOG_WARNING,"'%s', line %d:  Same File included more than once! This data will be saved in %s if saved back to disk.\n", from_file, from_lineno, real_included_file_name);
00336    } else
00337       *real_included_file_name = 0;
00338    
00339    inc = ast_calloc(1,sizeof(struct ast_config_include));
00340    if (!inc) {
00341       return NULL;
00342    }
00343    inc->include_location_file = ast_strdup(from_file);
00344    inc->include_location_lineno = from_lineno;
00345    if (!ast_strlen_zero(real_included_file_name))
00346       inc->included_file = ast_strdup(real_included_file_name);
00347    else
00348       inc->included_file = ast_strdup(included_file);
00349    
00350    inc->exec = is_exec;
00351    if (is_exec)
00352       inc->exec_file = ast_strdup(exec_file);
00353 
00354    if (!inc->include_location_file
00355       || !inc->included_file
00356       || (is_exec && !inc->exec_file)) {
00357       ast_includes_destroy(inc);
00358       return NULL;
00359    }
00360 
00361    /* attach this new struct to the conf struct */
00362    inc->next = conf->includes;
00363    conf->includes = inc;
00364    
00365    return inc;
00366 }

void ast_include_rename ( struct ast_config conf,
const char *  from_file,
const char *  to_file 
)

Definition at line 368 of file config.c.

References ast_free, ast_strdup, ast_variable_destroy(), ast_variable_move(), ast_variable_new(), ast_variable::file, ast_category::file, ast_config_include::include_location_file, ast_config::includes, ast_category::last, ast_variable::name, ast_variable::next, ast_category::next, ast_config_include::next, ast_category::root, ast_config::root, str, and ast_variable::value.

Referenced by action_updateconfig().

00369 {
00370    struct ast_config_include *incl;
00371    struct ast_category *cat;
00372    char *str;
00373 
00374    int from_len = strlen(from_file);
00375    int to_len = strlen(to_file);
00376    
00377    if (strcmp(from_file, to_file) == 0) /* no use wasting time if the name is the same */
00378       return;
00379    
00380    /* the manager code allows you to read in one config file, then
00381     * write it back out under a different name. But, the new arrangement
00382     * ties output lines to the file name. So, before you try to write
00383     * the config file to disk, better riffle thru the data and make sure
00384     * the file names are changed.
00385     */
00386    /* file names are on categories, includes (of course), and on variables. So,
00387     * traverse all this and swap names */
00388 
00389    for (incl = conf->includes; incl; incl=incl->next) {
00390       if (strcmp(incl->include_location_file,from_file) == 0) {
00391          if (from_len >= to_len)
00392             strcpy(incl->include_location_file, to_file);
00393          else {
00394             /* Keep the old filename if the allocation fails. */
00395             str = ast_strdup(to_file);
00396             if (str) {
00397                ast_free(incl->include_location_file);
00398                incl->include_location_file = str;
00399             }
00400          }
00401       }
00402    }
00403    for (cat = conf->root; cat; cat = cat->next) {
00404       struct ast_variable **prev;
00405       struct ast_variable *v;
00406       struct ast_variable *new_var;
00407 
00408       if (strcmp(cat->file,from_file) == 0) {
00409          if (from_len >= to_len)
00410             strcpy(cat->file, to_file);
00411          else {
00412             /* Keep the old filename if the allocation fails. */
00413             str = ast_strdup(to_file);
00414             if (str) {
00415                ast_free(cat->file);
00416                cat->file = str;
00417             }
00418          }
00419       }
00420       for (prev = &cat->root, v = cat->root; v; prev = &v->next, v = v->next) {
00421          if (strcmp(v->file, from_file)) {
00422             continue;
00423          }
00424 
00425          /*
00426           * Calculate actual space available.  The file string is
00427           * intentionally stuffed before the name string just so we can
00428           * do this.
00429           */
00430          if (to_len < v->name - v->file) {
00431             /* The new name will fit in the available space. */
00432             str = (char *) v->file;/* Stupid compiler complains about discarding qualifiers even though I used a cast. */
00433             strcpy(str, to_file);/* SAFE */
00434             continue;
00435          }
00436 
00437          /* Keep the old filename if the allocation fails. */
00438          new_var = ast_variable_new(v->name, v->value, to_file);
00439          if (!new_var) {
00440             continue;
00441          }
00442 
00443          /* Move items from the old list node to the replacement node. */
00444          ast_variable_move(new_var, v);
00445 
00446          /* Replace the old node in the list with the new node. */
00447          new_var->next = v->next;
00448          if (cat->last == v) {
00449             cat->last = new_var;
00450          }
00451          *prev = new_var;
00452 
00453          ast_variable_destroy(v);
00454 
00455          v = new_var;
00456       }
00457    }
00458 }

static void ast_includes_destroy ( struct ast_config_include incls  )  [static]

Definition at line 731 of file config.c.

References ast_free, ast_config_include::exec_file, ast_config_include::include_location_file, ast_config_include::included_file, and ast_config_include::next.

Referenced by ast_config_destroy(), and ast_include_new().

00732 {
00733    struct ast_config_include *incl,*inclnext;
00734    
00735    for (incl=incls; incl; incl = inclnext) {
00736       inclnext = incl->next;
00737       ast_free(incl->include_location_file);
00738       ast_free(incl->exec_file);
00739       ast_free(incl->included_file);
00740       ast_free(incl);
00741    }
00742 }

struct ast_variable* ast_load_realtime ( const char *  family,
  ... 
)

Retrieve realtime configuration.

Parameters:
family which family/config to lookup
This will use builtin configuration backends to look up a particular entity in realtime and return a variable list of its parameters.

Note:
Unlike the variables in ast_config, the resulting list of variables MUST be freed with ast_variables_destroy() as there is no container.

The difference between these two calls is that ast_load_realtime excludes fields whose values are NULL, while ast_load_realtime_all loads all columns.

You should use the constant SENTINEL to terminate arguments, in order to preserve cross-platform compatibility.

Definition at line 2355 of file config.c.

References ast_load_realtime_helper(), ast_strlen_zero(), ast_variable_destroy(), ast_variable::next, and ast_variable::value.

Referenced by conf_run(), copy_plain_file(), find_conf_realtime(), find_realtime(), find_realtime_gw(), find_user_realtime(), leave_queue(), load_realtime_queue(), local_ast_moh_start(), queue_function_queuewaitingcount(), realtime_alias(), realtime_peer(), realtime_peer_by_addr(), realtime_peer_by_name(), realtime_peer_get_sippeer_helper(), realtime_switch_common(), realtime_user(), and rt_extend_conf().

02356 {
02357    struct ast_variable *res;
02358    struct ast_variable *cur;
02359    struct ast_variable **prev;
02360    va_list ap;
02361 
02362    va_start(ap, family);
02363    res = ast_load_realtime_helper(family, ap);
02364    va_end(ap);
02365 
02366    /* Filter the list. */
02367    prev = &res;
02368    cur = res;
02369    while (cur) {
02370       if (ast_strlen_zero(cur->value)) {
02371          /* Eliminate empty entries */
02372          struct ast_variable *next;
02373 
02374          next = cur->next;
02375          *prev = next;
02376          ast_variable_destroy(cur);
02377          cur = next;
02378       } else {
02379          /* Make blank entries empty and keep them. */
02380          if (cur->value[0] == ' ' && cur->value[1] == '\0') {
02381             char *vptr = (char *) cur->value;
02382 
02383             vptr[0] = '\0';
02384          }
02385 
02386          prev = &cur->next;
02387          cur = cur->next;
02388       }
02389    }
02390    return res;
02391 }

struct ast_variable* ast_load_realtime_all ( const char *  family,
  ... 
)

Definition at line 2343 of file config.c.

References ast_load_realtime_helper().

Referenced by cli_realtime_load(), function_realtime_read(), function_realtime_readdestroy(), and realtimefield_read().

02344 {
02345    struct ast_variable *res;
02346    va_list ap;
02347 
02348    va_start(ap, family);
02349    res = ast_load_realtime_helper(family, ap);
02350    va_end(ap);
02351 
02352    return res;
02353 }

static struct ast_variable* ast_load_realtime_helper ( const char *  family,
va_list  ap 
) [static]

Definition at line 2322 of file config.c.

References db, find_engine(), ast_config_engine::realtime_func, and table.

Referenced by ast_load_realtime(), and ast_load_realtime_all().

02323 {
02324    struct ast_config_engine *eng;
02325    char db[256];
02326    char table[256];
02327    struct ast_variable *res=NULL;
02328    int i;
02329 
02330    for (i = 1; ; i++) {
02331       if ((eng = find_engine(family, i, db, sizeof(db), table, sizeof(table)))) {
02332          if (eng->realtime_func && (res = eng->realtime_func(db, table, ap))) {
02333             return res;
02334          }
02335       } else {
02336          return NULL;
02337       }
02338    }
02339 
02340    return res;
02341 }

struct ast_config* ast_load_realtime_multientry ( const char *  family,
  ... 
)

Retrieve realtime configuration.

Parameters:
family which family/config to lookup
This will use builtin configuration backends to look up a particular entity in realtime and return a variable list of its parameters. Unlike the ast_load_realtime, this function can return more than one entry and is thus stored inside a traditional ast_config structure rather than just returning a linked list of variables.

Returns:
An ast_config with one or more results
Return values:
NULL Error or no results returned
Note:
You should use the constant SENTINEL to terminate arguments, in order to preserve cross-platform compatibility.

Definition at line 2457 of file config.c.

References ast_config_destroy(), db, find_engine(), ast_config_engine::realtime_multi_func, ast_config::root, and table.

Referenced by __queues_show(), conf_exec(), get_insecure_variable_from_sippeers(), get_insecure_variable_from_sipregs(), load_realtime_queue(), queues_data_provider_get(), realtime_directory(), realtime_switch_common(), show_users_realtime(), and update_realtime_members().

02458 {
02459    struct ast_config_engine *eng;
02460    char db[256];
02461    char table[256];
02462    struct ast_config *res = NULL;
02463    va_list ap;
02464    int i;
02465 
02466    va_start(ap, family);
02467    for (i = 1; ; i++) {
02468       if ((eng = find_engine(family, i, db, sizeof(db), table, sizeof(table)))) {
02469          if (eng->realtime_multi_func && (res = eng->realtime_multi_func(db, table, ap))) {
02470             /* If we were returned an empty cfg, destroy it and return NULL */
02471             if (!res->root) {
02472                ast_config_destroy(res);
02473                res = NULL;
02474             }
02475             break;
02476          }
02477       } else {
02478          break;
02479       }
02480    }
02481    va_end(ap);
02482 
02483    return res;
02484 }

int ast_parse_arg ( const char *  arg,
enum ast_parse_flags  flags,
void *  result,
  ... 
)

The argument parsing routine.

Parameters:
arg the string to parse. It is not modified.
flags combination of ast_parse_flags to specify the return type and additional checks.
result pointer to the result. NULL is valid here, and can be used to perform only the validity checks.
... extra arguments are required according to flags.
Return values:
0 in case of success, != 0 otherwise.
result returns the parsed value in case of success, the default value in case of error, or it is left unchanged in case of error and no default specified. Note that in certain cases (e.g. sockaddr_in, with multi-field return values) some of the fields in result may be changed even if an error occurs.
Examples of use: ast_parse_arg("223", PARSE_INT32|PARSE_IN_RANGE, &a, -1000, 1000); returns 0, a = 223 ast_parse_arg("22345", PARSE_INT32|PARSE_IN_RANGE|PARSE_DEFAULT, &a, 9999, 10, 100); returns 1, a = 9999 ast_parse_arg("22345ssf", PARSE_UINT32|PARSE_IN_RANGE, &b, 10, 100); returns 1, b unchanged ast_parse_arg("www.foo.biz:44", PARSE_INADDR, &sa); returns 0, sa contains address and port ast_parse_arg("www.foo.biz", PARSE_INADDR|PARSE_PORT_REQUIRE, &sa); returns 1 because port is missing, sa contains address

Definition at line 2612 of file config.c.

References ahp, ast_debug, ast_gethostbyname(), ast_inet_ntoa(), ast_sockaddr_parse(), ast_sockaddr_stringify(), ast_strdupa, hp, PARSE_ADDR, PARSE_DEFAULT, PARSE_DOUBLE, PARSE_IN_RANGE, PARSE_INADDR, PARSE_INT32, PARSE_OUT_RANGE, PARSE_PORT_FORBID, PARSE_PORT_IGNORE, PARSE_PORT_MASK, PARSE_PORT_REQUIRE, PARSE_TYPE, PARSE_UINT32, and strsep().

Referenced by ast_tls_read_conf(), and check_via_response().

02614 {
02615    va_list ap;
02616    int error = 0;
02617 
02618    va_start(ap, p_result);
02619    switch (flags & PARSE_TYPE) {
02620    case PARSE_INT32:
02621        {
02622       int32_t *result = p_result;
02623       int32_t x, def = result ? *result : 0,
02624          high = (int32_t)0x7fffffff,
02625          low  = (int32_t)0x80000000;
02626       /* optional argument: first default value, then range */
02627       if (flags & PARSE_DEFAULT)
02628          def = va_arg(ap, int32_t);
02629       if (flags & (PARSE_IN_RANGE|PARSE_OUT_RANGE)) {
02630          /* range requested, update bounds */
02631          low = va_arg(ap, int32_t);
02632          high = va_arg(ap, int32_t);
02633       }
02634       x = strtol(arg, NULL, 0);
02635       error = (x < low) || (x > high);
02636       if (flags & PARSE_OUT_RANGE)
02637          error = !error;
02638       if (result)
02639          *result  = error ? def : x;
02640       ast_debug(3,
02641          "extract int from [%s] in [%d, %d] gives [%d](%d)\n",
02642          arg, low, high,
02643          result ? *result : x, error);
02644       break;
02645        }
02646 
02647    case PARSE_UINT32:
02648        {
02649       uint32_t *result = p_result;
02650       uint32_t x, def = result ? *result : 0,
02651          low = 0, high = (uint32_t)~0;
02652       /* optional argument: first default value, then range */
02653       if (flags & PARSE_DEFAULT)
02654          def = va_arg(ap, uint32_t);
02655       if (flags & (PARSE_IN_RANGE|PARSE_OUT_RANGE)) {
02656          /* range requested, update bounds */
02657          low = va_arg(ap, uint32_t);
02658          high = va_arg(ap, uint32_t);
02659       }
02660       x = strtoul(arg, NULL, 0);
02661       error = (x < low) || (x > high);
02662       if (flags & PARSE_OUT_RANGE)
02663          error = !error;
02664       if (result)
02665          *result  = error ? def : x;
02666       ast_debug(3,
02667          "extract uint from [%s] in [%u, %u] gives [%u](%d)\n",
02668          arg, low, high,
02669          result ? *result : x, error);
02670       break;
02671        }
02672 
02673    case PARSE_DOUBLE:
02674        {
02675       double *result = p_result;
02676       double x, def = result ? *result : 0,
02677          low = -HUGE_VAL, high = HUGE_VAL;
02678 
02679       /* optional argument: first default value, then range */
02680       if (flags & PARSE_DEFAULT)
02681          def = va_arg(ap, double);
02682       if (flags & (PARSE_IN_RANGE|PARSE_OUT_RANGE)) {
02683          /* range requested, update bounds */
02684          low = va_arg(ap, double);
02685          high = va_arg(ap, double);
02686       }
02687       x = strtod(arg, NULL);
02688       error = (x < low) || (x > high);
02689       if (flags & PARSE_OUT_RANGE)
02690          error = !error;
02691       if (result)
02692          *result  = error ? def : x;
02693       ast_debug(3,
02694          "extract double from [%s] in [%f, %f] gives [%f](%d)\n",
02695          arg, low, high,
02696          result ? *result : x, error);
02697       break;
02698        }
02699    case PARSE_ADDR:
02700        {
02701       struct ast_sockaddr *addr = (struct ast_sockaddr *)p_result;
02702 
02703       if (!ast_sockaddr_parse(addr, arg, flags & PARSE_PORT_MASK)) {
02704          error = 1;
02705       }
02706 
02707       ast_debug(3, "extract addr from %s gives %s(%d)\n",
02708            arg, ast_sockaddr_stringify(addr), error);
02709 
02710       break;
02711        }
02712    case PARSE_INADDR:   /* TODO Remove this (use PARSE_ADDR instead). */
02713        {
02714       char *port, *buf;
02715       struct sockaddr_in _sa_buf;   /* buffer for the result */
02716       struct sockaddr_in *sa = p_result ?
02717          (struct sockaddr_in *)p_result : &_sa_buf;
02718       /* default is either the supplied value or the result itself */
02719       struct sockaddr_in *def = (flags & PARSE_DEFAULT) ?
02720          va_arg(ap, struct sockaddr_in *) : sa;
02721       struct hostent *hp;
02722       struct ast_hostent ahp;
02723 
02724       memset(&_sa_buf, '\0', sizeof(_sa_buf)); /* clear buffer */
02725       /* duplicate the string to strip away the :port */
02726       port = ast_strdupa(arg);
02727       buf = strsep(&port, ":");
02728       sa->sin_family = AF_INET;  /* assign family */
02729       /*
02730        * honor the ports flag setting, assign default value
02731        * in case of errors or field unset.
02732        */
02733       flags &= PARSE_PORT_MASK; /* the only flags left to process */
02734       if (port) {
02735          if (flags == PARSE_PORT_FORBID) {
02736             error = 1;  /* port was forbidden */
02737             sa->sin_port = def->sin_port;
02738          } else if (flags == PARSE_PORT_IGNORE)
02739             sa->sin_port = def->sin_port;
02740          else /* accept or require */
02741             sa->sin_port = htons(strtol(port, NULL, 0));
02742       } else {
02743          sa->sin_port = def->sin_port;
02744          if (flags == PARSE_PORT_REQUIRE)
02745             error = 1;
02746       }
02747       /* Now deal with host part, even if we have errors before. */
02748       hp = ast_gethostbyname(buf, &ahp);
02749       if (hp)  /* resolved successfully */
02750          memcpy(&sa->sin_addr, hp->h_addr, sizeof(sa->sin_addr));
02751       else {
02752          error = 1;
02753          sa->sin_addr = def->sin_addr;
02754       }
02755       ast_debug(3,
02756          "extract inaddr from [%s] gives [%s:%d](%d)\n",
02757          arg, ast_inet_ntoa(sa->sin_addr),
02758          ntohs(sa->sin_port), error);
02759          break;
02760        }
02761    }
02762    va_end(ap);
02763    return error;
02764 }

char* ast_realtime_decode_chunk ( char *  chunk  ) 

Remove standard encoding from realtime values, which ensures that a semicolon embedded within a single value is not treated upon retrieval as multiple values.

Parameters:
chunk Data to be decoded
Returns:
The decoded data, in the original buffer
Since:
1.8 This function modifies the original buffer

Definition at line 2580 of file config.c.

Referenced by realtime_multi_pgsql(), and realtime_pgsql().

02581 {
02582    char *orig = chunk;
02583    for (; *chunk; chunk++) {
02584       if (*chunk == '^' && strchr("0123456789ABCDEFabcdef", chunk[1]) && strchr("0123456789ABCDEFabcdef", chunk[2])) {
02585          sscanf(chunk + 1, "%02hhX", chunk);
02586          memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
02587       }
02588    }
02589    return orig;
02590 }

int ast_realtime_enabled ( void   ) 

Check if there's any realtime engines loaded.

Definition at line 2408 of file config.c.

References config_maps.

Referenced by action_coresettings(), ast_check_realtime(), and handle_show_settings().

02409 {
02410    return config_maps ? 1 : 0;
02411 }

char* ast_realtime_encode_chunk ( struct ast_str **  dest,
ssize_t  maxlen,
const char *  chunk 
)

Encodes a chunk of data for realtime.

Parameters:
dest Destination buffer
maxlen Length passed through to ast_str_* functions
chunk Source data to be encoded
Returns:
Buffer within dest
Since:
1.8

Definition at line 2592 of file config.c.

References ast_str_append(), ast_str_buffer(), ast_str_reset(), and ast_str_set().

02593 {
02594    if (!strchr(chunk, ';') && !strchr(chunk, '^')) {
02595       ast_str_set(dest, maxlen, "%s", chunk);
02596    } else {
02597       ast_str_reset(*dest);
02598       for (; *chunk; chunk++) {
02599          if (strchr(";^", *chunk)) {
02600             ast_str_append(dest, maxlen, "^%02hhX", *chunk);
02601          } else {
02602             ast_str_append(dest, maxlen, "%c", *chunk);
02603          }
02604       }
02605    }
02606    return ast_str_buffer(*dest);
02607 }

int ast_realtime_require_field ( const char *  family,
  ... 
)

Inform realtime what fields that may be stored.

Since:
1.6.1
Parameters:
family which family/config is referenced
This will inform builtin configuration backends that particular fields may be updated during the use of that configuration section. This is mainly to be used during startup routines, to ensure that various fields exist in the backend. The backends may take various actions, such as creating new fields in the data store or warning the administrator that new fields may need to be created, in order to ensure proper function.

The arguments are specified in groups of 3: column name, column type, and column size. The column types are specified as integer constants, defined by the enum require_type. Note that the size is specified as the number of equivalent character fields that a field may take up, even if a field is otherwise specified as an integer type. This is due to the fact that some fields have historically been specified as character types, even if they contained integer values.

A family should always specify its fields to the minimum necessary requirements to fulfill all possible values (within reason; for example, a timeout value may reasonably be specified as an INTEGER2, with size 5. Even though values above 32767 seconds are possible, they are unlikely to be useful, and we should not complain about that size).

Return values:
0 Required fields met specified standards
-1 One or more fields was missing or insufficient
Note:
You should use the constant SENTINEL to terminate arguments, in order to preserve cross-platform compatibility.

Definition at line 2413 of file config.c.

References db, find_engine(), ast_config_engine::require_func, and table.

Referenced by ast_queue_log(), change_password_realtime(), conf_run(), load_module(), and logger_queue_rt_start().

02414 {
02415    struct ast_config_engine *eng;
02416    char db[256];
02417    char table[256];
02418    va_list ap;
02419    int res = -1, i;
02420 
02421    va_start(ap, family);
02422    for (i = 1; ; i++) {
02423       if ((eng = find_engine(family, i, db, sizeof(db), table, sizeof(table)))) {
02424          /* If the require succeeds, it returns 0. */
02425          if (eng->require_func && !(res = eng->require_func(db, table, ap))) {
02426             break;
02427          }
02428       } else {
02429          break;
02430       }
02431    }
02432    va_end(ap);
02433 
02434    return res;
02435 }

int ast_store_realtime ( const char *  family,
  ... 
)

Create realtime configuration.

Parameters:
family which family/config to be created
This function is used to create a parameter in realtime configuration space.

Returns:
Number of rows affected, or -1 on error.
Note:
On the MySQL engine only, for reasons of backwards compatibility, the return value is the insert ID. This value is nonportable and may be changed in a future version to match the other engines.

You should use the constant SENTINEL to terminate arguments, in order to preserve cross-platform compatibility.

Definition at line 2533 of file config.c.

References db, find_engine(), ast_config_engine::store_func, and table.

Referenced by ast_queue_log(), cli_realtime_store(), and function_realtime_store().

02534 {
02535    struct ast_config_engine *eng;
02536    int res = -1, i;
02537    char db[256];
02538    char table[256];
02539    va_list ap;
02540 
02541    va_start(ap, family);
02542    for (i = 1; ; i++) {
02543       if ((eng = find_engine(family, i, db, sizeof(db), table, sizeof(table)))) {
02544          /* If the store succeeds, it returns 0. */
02545          if (eng->store_func && !(res = eng->store_func(db, table, ap))) {
02546             break;
02547          }
02548       } else {
02549          break;
02550       }
02551    }
02552    va_end(ap);
02553 
02554    return res;
02555 }

int ast_unload_realtime ( const char *  family  ) 

Release any resources cached for a realtime family.

Since:
1.6.1
Parameters:
family which family/config to destroy
Various backends may cache attributes about a realtime data storage facility; on reload, a front end resource may request to purge that cache.

Return values:
0 If any cache was purged
-1 If no cache was found

Definition at line 2437 of file config.c.

References db, find_engine(), table, and ast_config_engine::unload_func.

Referenced by __unload_module(), load_config(), logger_queue_init(), reload(), reload_config(), reload_logger(), and unload_module().

02438 {
02439    struct ast_config_engine *eng;
02440    char db[256];
02441    char table[256];
02442    int res = -1, i;
02443 
02444    for (i = 1; ; i++) {
02445       if ((eng = find_engine(family, i, db, sizeof(db), table, sizeof(table)))) {
02446          if (eng->unload_func) {
02447             /* Do this for ALL engines */
02448             res = eng->unload_func(db, table);
02449          }
02450       } else {
02451          break;
02452       }
02453    }
02454    return res;
02455 }

int ast_update2_realtime ( const char *  family,
  ... 
)

Update realtime configuration.

Parameters:
family which family/config to be updated
This function is used to update a parameter in realtime configuration space. It includes the ability to lookup a row based upon multiple key criteria. As a result, this function includes two sentinel values, one to terminate lookup values and the other to terminate the listing of fields to update.

Returns:
Number of rows affected, or -1 on error.
Note:
You should use the constant SENTINEL to terminate arguments, in order to preserve cross-platform compatibility.

Definition at line 2510 of file config.c.

References db, find_engine(), table, and ast_config_engine::update2_func.

Referenced by change_password_realtime(), and cli_realtime_update2().

02511 {
02512    struct ast_config_engine *eng;
02513    int res = -1, i;
02514    char db[256];
02515    char table[256];
02516    va_list ap;
02517 
02518    va_start(ap, family);
02519    for (i = 1; ; i++) {
02520       if ((eng = find_engine(family, i, db, sizeof(db), table, sizeof(table)))) {
02521          if (eng->update2_func && !(res = eng->update2_func(db, table, ap))) {
02522             break;
02523          }
02524       } else {
02525          break;
02526       }
02527    }
02528    va_end(ap);
02529 
02530    return res;
02531 }

int ast_update_realtime ( const char *  family,
const char *  keyfield,
const char *  lookup,
  ... 
)

Update realtime configuration.

Parameters:
family which family/config to be updated
keyfield which field to use as the key
lookup which value to look for in the key field to match the entry.
This function is used to update a parameter in realtime configuration space.

Returns:
Number of rows affected, or -1 on error.
Note:
You should use the constant SENTINEL to terminate arguments, in order to preserve cross-platform compatibility.

Definition at line 2486 of file config.c.

References db, find_engine(), table, and ast_config_engine::update_func.

Referenced by cli_realtime_update(), conf_run(), destroy_association(), function_realtime_write(), handle_response_peerpoke(), realtime_update_peer(), rename_file(), rt_extend_conf(), sip_poke_noanswer(), and update_realtime_member_field().

02487 {
02488    struct ast_config_engine *eng;
02489    int res = -1, i;
02490    char db[256];
02491    char table[256];
02492    va_list ap;
02493 
02494    va_start(ap, lookup);
02495    for (i = 1; ; i++) {
02496       if ((eng = find_engine(family, i, db, sizeof(db), table, sizeof(table)))) {
02497          /* If the update succeeds, it returns 0. */
02498          if (eng->update_func && !(res = eng->update_func(db, table, keyfield, lookup, ap))) {
02499             break;
02500          }
02501       } else {
02502          break;
02503       }
02504    }
02505    va_end(ap);
02506 
02507    return res;
02508 }

void ast_variable_append ( struct ast_category category,
struct ast_variable variable 
)

Definition at line 471 of file config.c.

References ast_category::last, ast_variable::next, and ast_category::root.

Referenced by add_cfg_entry(), add_rt_multi_cfg_entry(), config_curl(), config_ldap(), config_odbc(), config_pgsql(), handle_updates(), inherit_category(), move_variables(), process_text_line(), realtime_directory(), realtime_multi_curl(), realtime_multi_ldap(), realtime_multi_odbc(), realtime_multi_pgsql(), vm_change_password(), and write_password_to_file().

00472 {
00473    if (!variable)
00474       return;
00475    if (category->last)
00476       category->last->next = variable;
00477    else
00478       category->root = variable;
00479    category->last = variable;
00480    while (category->last->next)
00481       category->last = category->last->next;
00482 }

struct ast_variable* ast_variable_browse ( const struct ast_config config,
const char *  category 
)

Goes through variables.

Somewhat similar in intent as the ast_category_browse. List variables of config file category

Return values:
ast_variable list on success
NULL on failure

Definition at line 561 of file config.c.

References ast_category_get(), config, and ast_category::root.

Referenced by __ast_http_load(), __ast_http_post_load(), __init_manager(), action_getconfig(), action_getconfigjson(), actual_load_config(), adsi_load(), aji_load_config(), ast_cli_perms_init(), ast_plc_reload(), ast_readconfig(), ast_variable_retrieve(), build_calendar(), build_device(), build_event_channel(), caldav_load_calendar(), check_tx_freq(), collect_function_digits(), conf_exec(), config_load(), config_module(), do_say(), do_scheduler(), ewscal_load_calendar(), exchangecal_load_calendar(), find_conf(), gtalk_load_config(), handle_cli_dialplan_save(), iax_template_parse(), ical_load_calendar(), init_logger_chain(), jingle_load_config(), load_config(), load_module(), load_modules(), load_moh_classes(), load_odbc_config(), load_pktccops_config(), load_rpt_vars(), misdn_cfg_init(), node_lookup(), odbc_load_module(), osp_create_provider(), parse_config(), parse_tone_zone(), pbx_load_config(), process_config(), read_agent_config(), read_config_maps(), reload(), reload_config(), reload_followme(), reload_module(), reload_queue_rules(), reload_single_queue(), run_startup_commands(), search_directory_sub(), set_config(), setup_dahdi_int(), show_users_realtime(), sip_cli_notify(), sla_build_station(), sla_build_trunk(), smdi_load(), store_config(), and tds_load_module().

00562 {
00563    struct ast_category *cat = NULL;
00564 
00565    if (category && config->last_browse && (config->last_browse->name == category)) {
00566       cat = config->last_browse;
00567    } else {
00568       cat = ast_category_get(config, category);
00569    }
00570 
00571    return (cat) ? cat->root : NULL;
00572 }

int ast_variable_delete ( struct ast_category category,
const char *  variable,
const char *  match,
const char *  line 
)

Definition at line 853 of file config.c.

References ast_strlen_zero(), ast_variable_destroy(), ast_category::last, ast_variable::name, ast_variable::next, ast_category::root, and ast_variable::value.

Referenced by handle_updates().

00854 {
00855    struct ast_variable *cur, *prev=NULL, *curn;
00856    int res = -1;
00857    int num_item = 0;
00858    int req_item;
00859 
00860    req_item = -1;
00861    if (!ast_strlen_zero(line)) {
00862       /* Requesting to delete by item number. */
00863       if (sscanf(line, "%30d", &req_item) != 1
00864          || req_item < 0) {
00865          /* Invalid item number to delete. */
00866          return -1;
00867       }
00868    }
00869 
00870    prev = NULL;
00871    cur = category->root;
00872    while (cur) {
00873       curn = cur->next;
00874       /* Delete by item number or by variable name with optional value. */
00875       if ((0 <= req_item && num_item == req_item)
00876          || (req_item < 0 && !strcasecmp(cur->name, variable)
00877             && (ast_strlen_zero(match) || !strcasecmp(cur->value, match)))) {
00878          if (prev) {
00879             prev->next = cur->next;
00880             if (cur == category->last)
00881                category->last = prev;
00882          } else {
00883             category->root = cur->next;
00884             if (cur == category->last)
00885                category->last = NULL;
00886          }
00887          ast_variable_destroy(cur);
00888          res = 0;
00889       } else
00890          prev = cur;
00891 
00892       cur = curn;
00893       ++num_item;
00894    }
00895    return res;
00896 }

static void ast_variable_destroy ( struct ast_variable doomed  )  [static]

Definition at line 520 of file config.c.

References ast_comment_destroy(), ast_free, ast_variable::precomments, ast_variable::sameline, and ast_variable::trailing.

Referenced by ast_include_rename(), ast_load_realtime(), ast_variable_delete(), ast_variable_update(), and ast_variables_destroy().

00521 {
00522    ast_comment_destroy(&doomed->precomments);
00523    ast_comment_destroy(&doomed->sameline);
00524    ast_comment_destroy(&doomed->trailing);
00525    ast_free(doomed);
00526 }

void ast_variable_insert ( struct ast_category category,
struct ast_variable variable,
const char *  line 
)

Definition at line 484 of file config.c.

References ast_variable::next, and ast_category::root.

Referenced by handle_updates().

00485 {
00486    struct ast_variable *cur = category->root;
00487    int lineno;
00488    int insertline;
00489 
00490    if (!variable || sscanf(line, "%30d", &insertline) != 1) {
00491       return;
00492    }
00493    if (!insertline) {
00494       variable->next = category->root;
00495       category->root = variable;
00496    } else {
00497       for (lineno = 1; lineno < insertline; lineno++) {
00498          cur = cur->next;
00499          if (!cur->next) {
00500             break;
00501          }
00502       }
00503       variable->next = cur->next;
00504       cur->next = variable;
00505    }
00506 }

static void ast_variable_move ( struct ast_variable dst_var,
struct ast_variable src_var 
) [static]

Definition at line 307 of file config.c.

References ast_variable::blanklines, ast_variable::lineno, ast_variable::object, ast_variable::precomments, ast_variable::sameline, and ast_variable::trailing.

Referenced by ast_include_rename(), and ast_variable_update().

00308 {
00309    dst_var->lineno = src_var->lineno;
00310    dst_var->object = src_var->object;
00311    dst_var->blanklines = src_var->blanklines;
00312    dst_var->precomments = src_var->precomments;
00313    src_var->precomments = NULL;
00314    dst_var->sameline = src_var->sameline;
00315    src_var->sameline = NULL;
00316    dst_var->trailing = src_var->trailing;
00317    src_var->trailing = NULL;
00318 }

struct ast_variable* ast_variable_new ( const char *  name,
const char *  value,
const char *  filename 
)

Definition at line 266 of file config.c.

References __ast_calloc(), ast_calloc, and MIN_VARIABLE_FNAME_SPACE.

Referenced by add_cfg_entry(), add_rt_cfg_entry(), add_rt_multi_cfg_entry(), add_var(), apply_outgoing(), ast_channeltype_list(), ast_include_rename(), ast_variable_update(), ast_variables_dup(), build_user(), check_access(), config_curl(), config_ldap(), config_odbc(), config_pgsql(), copy_vars(), create_vmaccount(), dup_vars(), handle_updates(), handle_uri(), httpd_helper_thread(), iax_parse_ies(), ldap_table_config_add_attribute(), man_do_variable_value(), manager_sipnotify(), parkandannounce_exec(), parse_cookies(), process_text_line(), realtime_curl(), realtime_directory(), realtime_ldap_entry_to_var(), realtime_ldap_result_to_vars(), realtime_multi_curl(), realtime_multi_odbc(), realtime_multi_pgsql(), realtime_odbc(), realtime_pgsql(), sip_cli_notify(), variable_clone(), vm_change_password(), and write_password_to_file().

00268 {
00269    struct ast_variable *variable;
00270    int name_len = strlen(name) + 1;
00271    int val_len = strlen(value) + 1;
00272    int fn_len = strlen(filename) + 1;
00273 
00274    /* Ensure a minimum length in case the filename is changed later. */
00275    if (fn_len < MIN_VARIABLE_FNAME_SPACE) {
00276       fn_len = MIN_VARIABLE_FNAME_SPACE;
00277    }
00278 
00279    if (
00280 #ifdef MALLOC_DEBUG
00281       (variable = __ast_calloc(1, fn_len + name_len + val_len + sizeof(*variable), file, lineno, func))
00282 #else
00283       (variable = ast_calloc(1, fn_len + name_len + val_len + sizeof(*variable)))
00284 #endif
00285       ) {
00286       char *dst = variable->stuff;  /* writable space starts here */
00287 
00288       /* Put file first so ast_include_rename() can calculate space available. */
00289       variable->file = strcpy(dst, filename);
00290       dst += fn_len;
00291       variable->name = strcpy(dst, name);
00292       dst += name_len;
00293       variable->value = strcpy(dst, value);
00294    }
00295    return variable;
00296 }

const char* ast_variable_retrieve ( const struct ast_config config,
const char *  category,
const char *  variable 
)

Gets a variable.

Parameters:
config which (opened) config to use
category category under which the variable lies
variable which variable you wish to get the data for
Goes through a given config file in the given category and searches for the given variable

Return values:
The variable value on success
NULL if unable to find it.

Definition at line 585 of file config.c.

References ast_variable_browse(), config, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by __ast_udptl_reload(), _dsp_init(), actual_load_config(), advanced_options(), aji_load_config(), ast_config_option(), build_extension(), conf_exec(), config_function_read(), config_module(), directory_exec(), do_reload(), do_scheduler(), festival_exec(), function_macro(), get_insecure_variable_from_config(), get_insecure_variable_from_sipregs(), get_wait_interval(), gtalk_load_config(), iax_template_parse(), init_acf_query(), init_logger_chain(), initialize_cc_max_requests(), jingle_load_config(), load_config(), load_config_meetme(), load_indications(), load_module(), load_rpt_vars(), load_tech_calendars(), make_email_file(), node_lookup(), odbc_load_module(), osp_load(), parse_config(), pbx_load_config(), pbx_load_users(), play_message(), prep_email_sub_vars(), private_enum_init(), queue_set_global_params(), read_agent_config(), read_password_from_file(), realtime_directory(), reload_config(), reload_followme(), reload_single_queue(), retreive_memory(), retrieve_astcfgint(), rpt(), rpt_master(), rpt_tele_thread(), rpt_telemetry(), rtp_reload(), saynode(), search_directory(), search_directory_sub(), set_config(), setup_dahdi_int(), sla_build_station(), sla_build_trunk(), sla_load_config(), tds_load_module(), telem_lookup(), update_realtime_members(), vm_change_password(), and vm_forwardoptions().

00586 {
00587    struct ast_variable *v;
00588 
00589    if (category) {
00590       for (v = ast_variable_browse(config, category); v; v = v->next) {
00591          if (!strcasecmp(variable, v->name)) {
00592             return v->value;
00593          }
00594       }
00595    } else {
00596       struct ast_category *cat;
00597 
00598       for (cat = config->root; cat; cat = cat->next) {
00599          for (v = cat->root; v; v = v->next) {
00600             if (!strcasecmp(variable, v->name)) {
00601                return v->value;
00602             }
00603          }
00604       }
00605    }
00606 
00607    return NULL;
00608 }

int ast_variable_update ( struct ast_category category,
const char *  variable,
const char *  value,
const char *  match,
unsigned int  object 
)

Update variable value within a config.

Parameters:
category Category element within the config
variable Name of the variable to change
value New value of the variable
match If set, previous value of the variable (if NULL or zero-length, no matching will be done)
object Boolean of whether to make the new variable an object
Returns:
0 on success or -1 on failure.

Definition at line 898 of file config.c.

References ast_strlen_zero(), ast_variable_destroy(), ast_variable_move(), ast_variable_new(), ast_variable::file, ast_category::last, ast_variable::name, ast_variable::next, ast_category::root, and ast_variable::value.

Referenced by handle_updates(), process_text_line(), vm_change_password(), and vm_forwardoptions().

00900 {
00901    struct ast_variable *cur, *prev=NULL, *newer=NULL;
00902 
00903    for (cur = category->root; cur; prev = cur, cur = cur->next) {
00904       if (strcasecmp(cur->name, variable) ||
00905          (!ast_strlen_zero(match) && strcasecmp(cur->value, match)))
00906          continue;
00907 
00908       if (!(newer = ast_variable_new(variable, value, cur->file)))
00909          return -1;
00910 
00911       ast_variable_move(newer, cur);
00912       newer->object = newer->object || object;
00913 
00914       /* Replace the old node in the list with the new node. */
00915       newer->next = cur->next;
00916       if (prev)
00917          prev->next = newer;
00918       else
00919          category->root = newer;
00920       if (category->last == cur)
00921          category->last = newer;
00922 
00923       ast_variable_destroy(cur);
00924 
00925       return 0;
00926    }
00927 
00928    /* Could not find variable to update */
00929    return -1;
00930 }

void ast_variables_destroy ( struct ast_variable var  ) 

Free variable list.

Parameters:
var the linked list of variables to free
This function frees a list of variables.

Definition at line 550 of file config.c.

References ast_variable_destroy(), and ast_variable::next.

Referenced by __sip_destroy(), action_originate(), ast_category_destroy(), ast_category_empty(), ast_http_get_cookies(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_var_channel_types(), ast_var_channel_types_table(), ast_variables_dup(), build_peer(), build_user(), check_peer_ok(), cli_realtime_load(), conf_run(), destroy_dahdi_pvt(), dup_vars(), find_conf_realtime(), find_realtime(), find_user_realtime(), free_entry(), free_outgoing(), free_user(), function_realtime_read(), function_realtime_readdestroy(), get_insecure_variable_from_sipregs(), handle_uri(), httpd_helper_thread(), httpstatus_callback(), ldap_loadentry(), leave_queue(), load_realtime_queue(), local_ast_moh_start(), parkandannounce_exec(), pvt_destructor(), queue_function_queuewaitingcount(), realtime_alias(), realtime_canmatch(), realtime_common(), realtime_exists(), realtime_handler(), realtime_ldap_base_ap(), realtime_ldap_result_to_vars(), realtime_matchmore(), realtime_odbc(), realtime_peer(), realtime_peer_by_addr(), realtime_peer_by_name(), realtime_peer_get_sippeer_helper(), realtime_user(), rt_extend_conf(), sip_destroy_peer(), socket_process(), table_configs_free(), and user_destructor().

00551 {
00552    struct ast_variable *vn;
00553 
00554    while (v) {
00555       vn = v;
00556       v = v->next;
00557       ast_variable_destroy(vn);
00558    }
00559 }

struct ast_variable* ast_variables_dup ( struct ast_variable var  ) 

Duplicate variable list.

Parameters:
var the linked list of variables to clone
Returns:
A duplicated list which you'll need to free with ast_variables_destroy or NULL when out of memory.
Note:
Do not depend on this to copy more than just name, value and filename (the arguments to ast_variables_new).

Definition at line 528 of file config.c.

References ast_variable_new(), ast_variables_destroy(), ast_variable::next, and var.

Referenced by get_insecure_variable_from_sippeers(), and get_insecure_variable_from_sipregs().

00529 {
00530    struct ast_variable *cloned;
00531    struct ast_variable *tmp;
00532 
00533    if (!(cloned = ast_variable_new(var->name, var->value, var->file))) {
00534       return NULL;
00535    }
00536 
00537    tmp = cloned;
00538 
00539    while ((var = var->next)) {
00540       if (!(tmp->next = ast_variable_new(var->name, var->value, var->file))) {
00541          ast_variables_destroy(cloned);
00542          return NULL;
00543       }
00544       tmp = tmp->next;
00545    }
00546 
00547    return cloned;
00548 }

static struct ast_category* category_get ( const struct ast_config config,
const char *  category_name,
int  ignored 
) [static]

Definition at line 651 of file config.c.

References config, ast_category::ignored, ast_category::name, and ast_category::next.

Referenced by ast_category_get(), and process_text_line().

00652 {
00653    struct ast_category *cat;
00654 
00655    /* try exact match first, then case-insensitive match */
00656    for (cat = config->root; cat; cat = cat->next) {
00657       if (cat->name == category_name && (ignored || !cat->ignored))
00658          return cat;
00659    }
00660 
00661    for (cat = config->root; cat; cat = cat->next) {
00662       if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
00663          return cat;
00664    }
00665 
00666    return NULL;
00667 }

static void CB_ADD ( struct ast_str **  cb,
const char *  str 
) [static]

Definition at line 108 of file config.c.

References ast_str_append().

Referenced by config_text_file_load().

00109 {
00110    ast_str_append(cb, 0, "%s", str);
00111 }

static void CB_ADD_LEN ( struct ast_str **  cb,
const char *  str,
int  len 
) [static]

Definition at line 113 of file config.c.

References ast_copy_string(), and ast_str_append().

Referenced by config_text_file_load().

00114 {
00115    char *s = alloca(len + 1);
00116    ast_copy_string(s, str, len);
00117    ast_str_append(cb, 0, "%s", str);
00118 }

static void CB_RESET ( struct ast_str cb,
struct ast_str llb 
) [static]

Definition at line 120 of file config.c.

References ast_str_reset().

Referenced by config_text_file_load(), and process_text_line().

00121 { 
00122    if (cb) {
00123       ast_str_reset(cb);
00124    }
00125    if (llb) {
00126       ast_str_reset(llb);
00127    }
00128 }

static struct cache_file_mtime* cfmtime_new ( const char *  filename,
const char *  who_asked 
) [static]

Definition at line 1032 of file config.c.

References ast_calloc.

Referenced by config_cache_attribute(), and config_text_file_load().

01033 {
01034    struct cache_file_mtime *cfmtime;
01035    char *dst;
01036 
01037    cfmtime = ast_calloc(1,
01038       sizeof(*cfmtime) + strlen(filename) + 1 + strlen(who_asked) + 1);
01039    if (!cfmtime) {
01040       return NULL;
01041    }
01042    dst = cfmtime->filename;   /* writable space starts here */
01043    strcpy(dst, filename);
01044    dst += strlen(dst) + 1;
01045    cfmtime->who_asked = strcpy(dst, who_asked);
01046 
01047    return cfmtime;
01048 }

static void clear_config_maps ( void   )  [static]

Definition at line 2058 of file config.c.

References ast_free, ast_mutex_lock, ast_mutex_unlock, config_lock, config_maps, map, and ast_config_map::next.

Referenced by read_config_maps().

02059 {
02060    struct ast_config_map *map;
02061 
02062    ast_mutex_lock(&config_lock);
02063 
02064    while (config_maps) {
02065       map = config_maps;
02066       config_maps = config_maps->next;
02067       ast_free(map);
02068    }
02069       
02070    ast_mutex_unlock(&config_lock);
02071 }

static void config_cache_attribute ( const char *  configfile,
enum config_cache_attribute_enum  attrtype,
const char *  filename,
const char *  who_asked 
) [static]

Definition at line 1055 of file config.c.

References ast_calloc, AST_LIST_INSERT_SORTALPHA, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ATTRIBUTE_EXEC, ATTRIBUTE_INCLUDE, cfmtime_new(), cache_file_mtime::filename, cache_file_mtime::has_exec, cache_file_include::include, cache_file_mtime::includes, cache_file_mtime::mtime, and cache_file_mtime::who_asked.

Referenced by process_text_line().

01056 {
01057    struct cache_file_mtime *cfmtime;
01058    struct cache_file_include *cfinclude;
01059    struct stat statbuf = { 0, };
01060 
01061    /* Find our cached entry for this configuration file */
01062    AST_LIST_LOCK(&cfmtime_head);
01063    AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
01064       if (!strcmp(cfmtime->filename, configfile) && !strcmp(cfmtime->who_asked, who_asked))
01065          break;
01066    }
01067    if (!cfmtime) {
01068       cfmtime = cfmtime_new(configfile, who_asked);
01069       if (!cfmtime) {
01070          AST_LIST_UNLOCK(&cfmtime_head);
01071          return;
01072       }
01073       /* Note that the file mtime is initialized to 0, i.e. 1970 */
01074       AST_LIST_INSERT_SORTALPHA(&cfmtime_head, cfmtime, list, filename);
01075    }
01076 
01077    if (!stat(configfile, &statbuf))
01078       cfmtime->mtime = 0;
01079    else
01080       cfmtime->mtime = statbuf.st_mtime;
01081 
01082    switch (attrtype) {
01083    case ATTRIBUTE_INCLUDE:
01084       AST_LIST_TRAVERSE(&cfmtime->includes, cfinclude, list) {
01085          if (!strcmp(cfinclude->include, filename)) {
01086             AST_LIST_UNLOCK(&cfmtime_head);
01087             return;
01088          }
01089       }
01090       cfinclude = ast_calloc(1, sizeof(*cfinclude) + strlen(filename) + 1);
01091       if (!cfinclude) {
01092          AST_LIST_UNLOCK(&cfmtime_head);
01093          return;
01094       }
01095       strcpy(cfinclude->include, filename);
01096       AST_LIST_INSERT_TAIL(&cfmtime->includes, cfinclude, list);
01097       break;
01098    case ATTRIBUTE_EXEC:
01099       cfmtime->has_exec = 1;
01100       break;
01101    }
01102    AST_LIST_UNLOCK(&cfmtime_head);
01103 }

static struct ast_config* config_text_file_load ( const char *  database,
const char *  table,
const char *  filename,
struct ast_config cfg,
struct ast_flags  flags,
const char *  suggested_include_file,
const char *  who_asked 
) [static]

Definition at line 1360 of file config.c.

References ALLOC_COMMENT(), ast_clear_flag, ast_config_AST_CONFIG_DIR, ast_config_get_current_category(), ast_copy_string(), ast_debug, ast_free, AST_LIST_INSERT_SORTALPHA, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_str_buffer(), ast_str_create(), ast_str_reset(), ast_str_strlen(), ast_strip(), ast_strlen_zero(), ast_test_flag, ast_verb, CB_ADD(), CB_ADD_LEN(), CB_RESET(), CB_SIZE, cfmtime_new(), comment, COMMENT_META, COMMENT_TAG, CONFIG_FLAG_FILEUNCHANGED, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, errno, f, cache_file_mtime::filename, GLOB_ABORTED, cache_file_mtime::has_exec, cache_file_include::include, cache_file_mtime::includes, LOG_ERROR, LOG_WARNING, MAX_NESTED_COMMENTS, cache_file_mtime::mtime, MY_GLOB_FLAGS, process_text_line(), ast_variable::trailing, ast_category::trailing, and cache_file_mtime::who_asked.

01361 {
01362    char fn[256];
01363 #if defined(LOW_MEMORY)
01364    char buf[512];
01365 #else
01366    char buf[8192];
01367 #endif
01368    char *new_buf, *comment_p, *process_buf;
01369    FILE *f;
01370    int lineno=0;
01371    int comment = 0, nest[MAX_NESTED_COMMENTS];
01372    struct ast_category *cat = NULL;
01373    int count = 0;
01374    struct stat statbuf;
01375    struct cache_file_mtime *cfmtime = NULL;
01376    struct cache_file_include *cfinclude;
01377    struct ast_variable *last_var = 0;
01378    struct ast_category *last_cat = 0;
01379    /*! Growable string buffer */
01380    struct ast_str *comment_buffer = NULL; /*!< this will be a comment collector.*/
01381    struct ast_str *lline_buffer = NULL;   /*!< A buffer for stuff behind the ; */
01382 
01383    if (cfg)
01384       cat = ast_config_get_current_category(cfg);
01385 
01386    if (filename[0] == '/') {
01387       ast_copy_string(fn, filename, sizeof(fn));
01388    } else {
01389       snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
01390    }
01391 
01392    if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
01393       comment_buffer = ast_str_create(CB_SIZE);
01394       if (comment_buffer)
01395          lline_buffer = ast_str_create(CB_SIZE);
01396       if (!lline_buffer) {
01397          ast_free(comment_buffer);
01398          ast_log(LOG_ERROR, "Failed to initialize the comment buffer!\n");
01399          return NULL;
01400       }
01401    }
01402 #ifdef AST_INCLUDE_GLOB
01403    {
01404       int glob_ret;
01405       glob_t globbuf;
01406       globbuf.gl_offs = 0; /* initialize it to silence gcc */
01407       glob_ret = glob(fn, MY_GLOB_FLAGS, NULL, &globbuf);
01408       if (glob_ret == GLOB_NOSPACE)
01409          ast_log(LOG_WARNING,
01410             "Glob Expansion of pattern '%s' failed: Not enough memory\n", fn);
01411       else if (glob_ret  == GLOB_ABORTED)
01412          ast_log(LOG_WARNING,
01413             "Glob Expansion of pattern '%s' failed: Read error\n", fn);
01414       else  {
01415          /* loop over expanded files */
01416          int i;
01417          for (i=0; i<globbuf.gl_pathc; i++) {
01418             ast_copy_string(fn, globbuf.gl_pathv[i], sizeof(fn));
01419 #endif
01420    /*
01421     * The following is not a loop, but just a convenient way to define a block
01422     * (using do { } while(0) ), and be able to exit from it with 'continue'
01423     * or 'break' in case of errors. Nice trick.
01424     */
01425    do {
01426       if (stat(fn, &statbuf))
01427          continue;
01428 
01429       if (!S_ISREG(statbuf.st_mode)) {
01430          ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn);
01431          continue;
01432       }
01433 
01434       if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) {
01435          /* Find our cached entry for this configuration file */
01436          AST_LIST_LOCK(&cfmtime_head);
01437          AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
01438             if (!strcmp(cfmtime->filename, fn) && !strcmp(cfmtime->who_asked, who_asked))
01439                break;
01440          }
01441          if (!cfmtime) {
01442             cfmtime = cfmtime_new(fn, who_asked);
01443             if (!cfmtime)
01444                continue;
01445             /* Note that the file mtime is initialized to 0, i.e. 1970 */
01446             AST_LIST_INSERT_SORTALPHA(&cfmtime_head, cfmtime, list, filename);
01447          }
01448       }
01449 
01450       if (cfmtime && (!cfmtime->has_exec) && (cfmtime->mtime == statbuf.st_mtime) && ast_test_flag(&flags, CONFIG_FLAG_FILEUNCHANGED)) {
01451          /* File is unchanged, what about the (cached) includes (if any)? */
01452          int unchanged = 1;
01453          AST_LIST_TRAVERSE(&cfmtime->includes, cfinclude, list) {
01454             /* We must glob here, because if we did not, then adding a file to globbed directory would
01455              * incorrectly cause no reload to be necessary. */
01456             char fn2[256];
01457 #ifdef AST_INCLUDE_GLOB
01458             int glob_return;
01459             glob_t glob_buf = { .gl_offs = 0 };
01460             glob_return = glob(cfinclude->include, MY_GLOB_FLAGS, NULL, &glob_buf);
01461             /* On error, we reparse */
01462             if (glob_return == GLOB_NOSPACE || glob_return  == GLOB_ABORTED)
01463                unchanged = 0;
01464             else  {
01465                /* loop over expanded files */
01466                int j;
01467                for (j = 0; j < glob_buf.gl_pathc; j++) {
01468                   ast_copy_string(fn2, glob_buf.gl_pathv[j], sizeof(fn2));
01469 #else
01470                   ast_copy_string(fn2, cfinclude->include);
01471 #endif
01472                   if (config_text_file_load(NULL, NULL, fn2, NULL, flags, "", who_asked) == NULL) {
01473                      /* that second-to-last field needs to be looked at in this case... TODO */
01474                      unchanged = 0;
01475                      /* One change is enough to short-circuit and reload the whole shebang */
01476                      break;
01477                   }
01478 #ifdef AST_INCLUDE_GLOB
01479                }
01480             }
01481 #endif
01482          }
01483 
01484          if (unchanged) {
01485             AST_LIST_UNLOCK(&cfmtime_head);
01486             return CONFIG_STATUS_FILEUNCHANGED;
01487          }
01488       }
01489       if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
01490          AST_LIST_UNLOCK(&cfmtime_head);
01491 
01492       /* If cfg is NULL, then we just want an answer */
01493       if (cfg == NULL) {
01494          ast_free(comment_buffer);
01495          ast_free(lline_buffer);
01496          return NULL;
01497       }
01498 
01499       if (cfmtime)
01500          cfmtime->mtime = statbuf.st_mtime;
01501 
01502       ast_verb(2, "Parsing '%s': ", fn);
01503          fflush(stdout);
01504       if (!(f = fopen(fn, "r"))) {
01505          ast_debug(1, "No file to parse: %s\n", fn);
01506          ast_verb(2, "Not found (%s)\n", strerror(errno));
01507          continue;
01508       }
01509       count++;
01510       /* If we get to this point, then we're loading regardless */
01511       ast_clear_flag(&flags, CONFIG_FLAG_FILEUNCHANGED);
01512       ast_debug(1, "Parsing %s\n", fn);
01513       ast_verb(2, "Found\n");
01514       while (!feof(f)) {
01515          lineno++;
01516          if (fgets(buf, sizeof(buf), f)) {
01517             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && lline_buffer && ast_str_strlen(lline_buffer)) {
01518                CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer));       /* add the current lline buffer to the comment buffer */
01519                ast_str_reset(lline_buffer);        /* erase the lline buffer */
01520             }
01521             
01522             new_buf = buf;
01523             if (comment) 
01524                process_buf = NULL;
01525             else
01526                process_buf = buf;
01527             
01528             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer) && (ast_strlen_zero(buf) || strlen(buf) == strspn(buf," \t\n\r"))) {
01529                /* blank line? really? Can we add it to an existing comment and maybe preserve inter- and post- comment spacing? */
01530                CB_ADD(&comment_buffer, "\n");       /* add a newline to the comment buffer */
01531                continue; /* go get a new line, then */
01532             }
01533             
01534             while ((comment_p = strchr(new_buf, COMMENT_META))) {
01535                if ((comment_p > new_buf) && (*(comment_p - 1) == '\\')) {
01536                   /* Escaped semicolons aren't comments. */
01537                   new_buf = comment_p + 1;
01538                } else if (comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) {
01539                   /* Meta-Comment start detected ";--" */
01540                   if (comment < MAX_NESTED_COMMENTS) {
01541                      *comment_p = '\0';
01542                      new_buf = comment_p + 3;
01543                      comment++;
01544                      nest[comment-1] = lineno;
01545                   } else {
01546                      ast_log(LOG_ERROR, "Maximum nest limit of %d reached.\n", MAX_NESTED_COMMENTS);
01547                   }
01548                } else if ((comment_p >= new_buf + 2) &&
01549                      (*(comment_p - 1) == COMMENT_TAG) &&
01550                      (*(comment_p - 2) == COMMENT_TAG)) {
01551                   /* Meta-Comment end detected */
01552                   comment--;
01553                   new_buf = comment_p + 1;
01554                   if (!comment) {
01555                      /* Back to non-comment now */
01556                      if (process_buf) {
01557                         /* Actually have to move what's left over the top, then continue */
01558                         char *oldptr;
01559                         oldptr = process_buf + strlen(process_buf);
01560                         if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
01561                            CB_ADD(&comment_buffer, ";");
01562                            CB_ADD_LEN(&comment_buffer, oldptr+1, new_buf-oldptr-1);
01563                         }
01564                         
01565                         memmove(oldptr, new_buf, strlen(new_buf) + 1);
01566                         new_buf = oldptr;
01567                      } else
01568                         process_buf = new_buf;
01569                   }
01570                } else {
01571                   if (!comment) {
01572                      /* If ; is found, and we are not nested in a comment, 
01573                         we immediately stop all comment processing */
01574                      if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
01575                         CB_ADD(&lline_buffer, comment_p);
01576                      }
01577                      *comment_p = '\0'; 
01578                      new_buf = comment_p;
01579                   } else
01580                      new_buf = comment_p + 1;
01581                }
01582             }
01583             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment && !process_buf ) {
01584                CB_ADD(&comment_buffer, buf);  /* the whole line is a comment, store it */
01585             }
01586             
01587             if (process_buf) {
01588                char *buffer = ast_strip(process_buf);
01589                if (!ast_strlen_zero(buffer)) {
01590                   if (process_text_line(cfg, &cat, buffer, lineno, fn, flags, comment_buffer, lline_buffer, suggested_include_file, &last_cat, &last_var, who_asked)) {
01591                      cfg = CONFIG_STATUS_FILEINVALID;
01592                      break;
01593                   }
01594                }
01595             }
01596          }
01597       }
01598       /* end of file-- anything in a comment buffer? */
01599       if (last_cat) {
01600          if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) {
01601             if (lline_buffer && ast_str_strlen(lline_buffer)) {
01602                CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer));       /* add the current lline buffer to the comment buffer */
01603                ast_str_reset(lline_buffer);        /* erase the lline buffer */
01604             }
01605             last_cat->trailing = ALLOC_COMMENT(comment_buffer);
01606          }
01607       } else if (last_var) {
01608          if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) {
01609             if (lline_buffer && ast_str_strlen(lline_buffer)) {
01610                CB_ADD(&comment_buffer, ast_str_buffer(lline_buffer));       /* add the current lline buffer to the comment buffer */
01611                ast_str_reset(lline_buffer);        /* erase the lline buffer */
01612             }
01613             last_var->trailing = ALLOC_COMMENT(comment_buffer);
01614          }
01615       } else {
01616          if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && ast_str_strlen(comment_buffer)) {
01617             ast_debug(1, "Nothing to attach comments to, discarded: %s\n", ast_str_buffer(comment_buffer));
01618          }
01619       }
01620       if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01621          CB_RESET(comment_buffer, lline_buffer);
01622 
01623       fclose(f);
01624    } while (0);
01625    if (comment) {
01626       ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment - 1]);
01627    }
01628 #ifdef AST_INCLUDE_GLOB
01629                if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
01630                   break;
01631                }
01632             }
01633             globfree(&globbuf);
01634          }
01635       }
01636 #endif
01637 
01638    if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg != CONFIG_STATUS_FILEINVALID && cfg->include_level == 1 && ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
01639       ast_free(comment_buffer);
01640       ast_free(lline_buffer);
01641       comment_buffer = NULL;
01642       lline_buffer = NULL;
01643    }
01644    
01645    if (count == 0)
01646       return NULL;
01647 
01648    return cfg;
01649 }

int config_text_file_save ( const char *  configfile,
const struct ast_config cfg,
const char *  generator 
)

Definition at line 1798 of file config.c.

References ast_config_text_file_save().

01799 {
01800    return ast_config_text_file_save(configfile, cfg, generator);
01801 }

static int count_linefeeds ( char *  str  )  [static]

Definition at line 1739 of file config.c.

Referenced by count_linefeeds_in_comments().

01740 {
01741    int count = 0;
01742 
01743    while (*str) {
01744       if (*str =='\n')
01745          count++;
01746       str++;
01747    }
01748    return count;
01749 }

static int count_linefeeds_in_comments ( struct ast_comment x  )  [static]

Definition at line 1751 of file config.c.

References ast_comment::cmt, count_linefeeds(), and ast_comment::next.

Referenced by insert_leading_blank_lines().

01752 {
01753    int count = 0;
01754 
01755    while (x) {
01756       count += count_linefeeds(x->cmt);
01757       x = x->next;
01758    }
01759    return count;
01760 }

static struct ast_config_engine* find_engine ( const char *  family,
int  priority,
char *  database,
int  dbsiz,
char *  table,
int  tabsiz 
) [static]

Find realtime engine for realtime family.

Definition at line 2227 of file config.c.

References ast_copy_string(), ast_mutex_lock, config_lock, config_maps, and map.

Referenced by ast_check_realtime(), ast_config_internal_load(), ast_destroy_realtime(), ast_load_realtime_helper(), ast_load_realtime_multientry(), ast_realtime_require_field(), ast_speech_new(), ast_speech_register(), ast_store_realtime(), ast_unload_realtime(), ast_update2_realtime(), and ast_update_realtime().

02228 {
02229    struct ast_config_engine *eng, *ret = NULL;
02230    struct ast_config_map *map;
02231 
02232    ast_mutex_lock(&config_lock);
02233 
02234    for (map = config_maps; map; map = map->next) {
02235       if (!strcasecmp(family, map->name) && (priority == map->priority)) {
02236          if (database)
02237             ast_copy_string(database, map->database, dbsiz);
02238          if (table)
02239             ast_copy_string(table, map->table ? map->table : family, tabsiz);
02240          break;
02241       }
02242    }
02243 
02244    /* Check if the required driver (engine) exist */
02245    if (map) {
02246       for (eng = config_engine_list; !ret && eng; eng = eng->next) {
02247          if (!strcasecmp(eng->name, map->driver))
02248             ret = eng;
02249       }
02250    }
02251 
02252    ast_mutex_unlock(&config_lock);
02253    
02254    /* if we found a mapping, but the engine is not available, then issue a warning */
02255    if (map && !ret)
02256       ast_log(LOG_WARNING, "Realtime mapping for '%s' found to engine '%s', but the engine is not available\n", map->name, map->driver);
02257 
02258    return ret;
02259 }

static void gen_header ( FILE *  f1,
const char *  configfile,
const char *  fn,
const char *  generator 
) [static]

Definition at line 1672 of file config.c.

References ast_copy_string().

Referenced by ast_config_text_file_save().

01673 {
01674    char date[256]="";
01675    time_t t;
01676 
01677    time(&t);
01678    ast_copy_string(date, ctime(&t), sizeof(date));
01679 
01680    fprintf(f1, ";!\n");
01681    fprintf(f1, ";! Automatically generated configuration file\n");
01682    if (strcmp(configfile, fn))
01683       fprintf(f1, ";! Filename: %s (%s)\n", configfile, fn);
01684    else
01685       fprintf(f1, ";! Filename: %s\n", configfile);
01686    fprintf(f1, ";! Generator: %s\n", generator);
01687    fprintf(f1, ";! Creation Date: %s", date);
01688    fprintf(f1, ";!\n");
01689 }

static char* handle_cli_config_list ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2865 of file config.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, cache_file_mtime::filename, cache_file_mtime::list, S_OR, ast_cli_entry::usage, and cache_file_mtime::who_asked.

02866 {
02867    struct cache_file_mtime *cfmtime;
02868 
02869    switch (cmd) {
02870    case CLI_INIT:
02871       e->command = "config list";
02872       e->usage =
02873          "Usage: config list\n"
02874          "   Show all modules that have loaded a configuration file\n";
02875       return NULL;
02876    case CLI_GENERATE:
02877       return NULL;
02878    }
02879 
02880    AST_LIST_LOCK(&cfmtime_head);
02881    AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
02882       ast_cli(a->fd, "%-20.20s %-50s\n", S_OR(cfmtime->who_asked, "core"), cfmtime->filename);
02883    }
02884    AST_LIST_UNLOCK(&cfmtime_head);
02885 
02886    return CLI_SUCCESS;
02887 }

static char* handle_cli_config_reload ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2803 of file config.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli_command, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, cache_file_mtime::filename, cache_file_mtime::list, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, cache_file_mtime::who_asked, and ast_cli_args::word.

02804 {
02805    struct cache_file_mtime *cfmtime;
02806    char *prev = "", *completion_value = NULL;
02807    int wordlen, which = 0;
02808 
02809    switch (cmd) {
02810    case CLI_INIT:
02811       e->command = "config reload";
02812       e->usage =
02813          "Usage: config reload <filename.conf>\n"
02814          "   Reloads all modules that reference <filename.conf>\n";
02815       return NULL;
02816    case CLI_GENERATE:
02817       if (a->pos > 2) {
02818          return NULL;
02819       }
02820 
02821       wordlen = strlen(a->word);
02822 
02823       AST_LIST_LOCK(&cfmtime_head);
02824       AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
02825          /* Skip duplicates - this only works because the list is sorted by filename */
02826          if (strcmp(cfmtime->filename, prev) == 0) {
02827             continue;
02828          }
02829 
02830          /* Core configs cannot be reloaded */
02831          if (ast_strlen_zero(cfmtime->who_asked)) {
02832             continue;
02833          }
02834 
02835          if (++which > a->n && strncmp(cfmtime->filename, a->word, wordlen) == 0) {
02836             completion_value = ast_strdup(cfmtime->filename);
02837             break;
02838          }
02839 
02840          /* Otherwise save that we've seen this filename */
02841          prev = cfmtime->filename;
02842       }
02843       AST_LIST_UNLOCK(&cfmtime_head);
02844 
02845       return completion_value;
02846    }
02847 
02848    if (a->argc != 3) {
02849       return CLI_SHOWUSAGE;
02850    }
02851 
02852    AST_LIST_LOCK(&cfmtime_head);
02853    AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
02854       if (!strcmp(cfmtime->filename, a->argv[2])) {
02855          char *buf = alloca(strlen("module reload ") + strlen(cfmtime->who_asked) + 1);
02856          sprintf(buf, "module reload %s", cfmtime->who_asked);
02857          ast_cli_command(a->fd, buf);
02858       }
02859    }
02860    AST_LIST_UNLOCK(&cfmtime_head);
02861 
02862    return CLI_SUCCESS;
02863 }

static char* handle_cli_core_show_config_mappings ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2766 of file config.c.

References ast_cli(), ast_mutex_lock, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, config_engine_list, config_lock, config_maps, ast_cli_args::fd, map, ast_config_engine::name, ast_config_engine::next, and ast_cli_entry::usage.

02767 {
02768    struct ast_config_engine *eng;
02769    struct ast_config_map *map;
02770 
02771    switch (cmd) {
02772    case CLI_INIT:
02773       e->command = "core show config mappings";
02774       e->usage =
02775          "Usage: core show config mappings\n"
02776          "  Shows the filenames to config engines.\n";
02777       return NULL;
02778    case CLI_GENERATE:
02779       return NULL;
02780    }
02781    
02782    ast_mutex_lock(&config_lock);
02783 
02784    if (!config_engine_list) {
02785       ast_cli(a->fd, "No config mappings found.\n");
02786    } else {
02787       for (eng = config_engine_list; eng; eng = eng->next) {
02788          ast_cli(a->fd, "Config Engine: %s\n", eng->name);
02789          for (map = config_maps; map; map = map->next) {
02790             if (!strcasecmp(map->driver, eng->name)) {
02791                ast_cli(a->fd, "===> %s (db=%s, table=%s)\n", map->name, map->database,
02792                      map->table ? map->table : map->name);
02793             }
02794          }
02795       }
02796    }
02797    
02798    ast_mutex_unlock(&config_lock);
02799 
02800    return CLI_SUCCESS;
02801 }

static int hash_string ( const void *  obj,
const int  flags 
) [static]

Definition at line 150 of file config.c.

References str, and total.

Referenced by ast_config_text_file_save().

00151 {
00152    char *str = ((struct inclfile *) obj)->fname;
00153    int total;
00154 
00155    for (total = 0; *str; str++) {
00156       unsigned int tmp = total;
00157       total <<= 1; /* multiply by 2 */
00158       total += tmp; /* multiply by 3 */
00159       total <<= 2; /* multiply by 12 */
00160       total += tmp; /* multiply by 13 */
00161 
00162       total += ((unsigned int) (*str));
00163    }
00164    if (total < 0) {
00165       total = -total;
00166    }
00167    return total;
00168 }

static int hashtab_compare_strings ( void *  a,
void *  b,
int  flags 
) [static]

Definition at line 170 of file config.c.

References CMP_MATCH, CMP_STOP, and inclfile::fname.

Referenced by ast_config_text_file_save().

00171 {
00172    const struct inclfile *ae = a, *be = b;
00173    return !strcmp(ae->fname, be->fname) ? CMP_MATCH | CMP_STOP : 0;
00174 }

static void inclfile_destroy ( void *  obj  )  [static]

Definition at line 1691 of file config.c.

References ast_free, and inclfile::fname.

Referenced by set_fn().

01692 {
01693    const struct inclfile *o = obj;
01694 
01695    ast_free(o->fname);
01696 }

static void inherit_category ( struct ast_category new,
const struct ast_category base 
) [static]

Definition at line 828 of file config.c.

References ast_calloc, AST_LIST_INSERT_TAIL, ast_variable_append(), ast_category::name, ast_category_template_instance::next, ast_category::root, ast_category::template_instances, var, and variable_clone().

Referenced by process_text_line().

00829 {
00830    struct ast_variable *var;
00831    struct ast_category_template_instance *x;
00832 
00833    x = ast_calloc(1, sizeof(*x));
00834    if (!x) {
00835       return;
00836    }
00837    strcpy(x->name, base->name);
00838    x->inst = base;
00839    AST_LIST_INSERT_TAIL(&new->template_instances, x, next);
00840    for (var = base->root; var; var = var->next)
00841       ast_variable_append(new, variable_clone(var));
00842 }

static int init_appendbuf ( void *  data  )  [static]

Definition at line 96 of file config.c.

References ast_str_create(), and str.

00097 {
00098    struct ast_str **str = data;
00099    *str = ast_str_create(16);
00100    return *str ? 0 : -1;
00101 }

static void insert_leading_blank_lines ( FILE *  fp,
struct inclfile fi,
struct ast_comment precomments,
int  lineno 
) [static]

Definition at line 1762 of file config.c.

References count_linefeeds_in_comments(), and inclfile::lineno.

Referenced by ast_config_text_file_save().

01763 {
01764    int precomment_lines;
01765    int i;
01766 
01767    if (!fi) {
01768       /* No file scratch pad object so insert no blank lines. */
01769       return;
01770    }
01771 
01772    precomment_lines = count_linefeeds_in_comments(precomments);
01773 
01774    /* I don't have to worry about those ;! comments, they are
01775       stored in the precomments, but not printed back out.
01776       I did have to make sure that comments following
01777       the ;! header comments were not also deleted in the process */
01778    if (lineno - precomment_lines - fi->lineno < 0) { /* insertions can mess up the line numbering and produce negative numbers that mess things up */
01779       return;
01780    } else if (lineno == 0) {
01781       /* Line replacements also mess things up */
01782       return;
01783    } else if (lineno - precomment_lines - fi->lineno < 5) {
01784       /* Only insert less than 5 blank lines; if anything more occurs,
01785        * it's probably due to context deletion. */
01786       for (i = fi->lineno; i < lineno - precomment_lines; i++) {
01787          fprintf(fp, "\n");
01788       }
01789    } else {
01790       /* Deletion occurred - insert a single blank line, for separation of
01791        * contexts. */
01792       fprintf(fp, "\n");
01793    }
01794  
01795    fi->lineno = lineno + 1; /* Advance the file lineno */
01796 }

static void move_variables ( struct ast_category old,
struct ast_category new 
) [static]

Definition at line 624 of file config.c.

References ast_variable_append(), ast_category::root, and var.

Referenced by process_text_line().

00625 {
00626    struct ast_variable *var = old->root;
00627 
00628    old->root = NULL;
00629    /* we can just move the entire list in a single op */
00630    ast_variable_append(new, var);
00631 }

static struct ast_category* next_available_category ( struct ast_category cat  )  [static]

Definition at line 744 of file config.c.

References ast_category::ignored, and ast_category::next.

Referenced by ast_category_browse().

00745 {
00746    for (; cat && cat->ignored; cat = cat->next);
00747 
00748    return cat;
00749 }

static int process_text_line ( struct ast_config cfg,
struct ast_category **  cat,
char *  buf,
int  lineno,
const char *  configfile,
struct ast_flags  flags,
struct ast_str comment_buffer,
struct ast_str lline_buffer,
const char *  suggested_include_file,
struct ast_category **  last_cat,
struct ast_variable **  last_var,
const char *  who_asked 
) [static]

parse one line in the configuration.

 * We can have a category header	[foo](...)
 * a directive				#include / #exec
 * or a regular line			name = value
 * 

Definition at line 1112 of file config.c.

References ALLOC_COMMENT(), appendbuf, ast_category_append(), ast_category_destroy(), ast_category_first(), ast_category_new(), ast_config_internal_load(), ast_include_new(), ast_log(), ast_opt_exec_includes, ast_safe_system(), ast_skip_blanks(), ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_trim_blanks(), ast_strip(), ast_strlen_zero(), ast_test_flag, ast_threadstorage_get(), ast_tvnow(), ast_variable_append(), ast_variable_new(), ast_variable_update(), ATTRIBUTE_EXEC, ATTRIBUTE_INCLUDE, ast_variable::blanklines, category_get(), CB_RESET(), config_cache_attribute(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, ast_config::include_level, inherit_category(), ast_variable::lineno, LOG_ERROR, LOG_WARNING, move_variables(), ast_variable::object, ast_variable::precomments, ast_category::precomments, replace(), S_OR, ast_variable::sameline, ast_category::sameline, str, strsep(), and var.

Referenced by config_text_file_load().

01118 {
01119    char *c;
01120    char *cur = buf;
01121    struct ast_variable *v;
01122    char cmd[512], exec_file[512];
01123 
01124    /* Actually parse the entry */
01125    if (cur[0] == '[') { /* A category header */
01126       /* format is one of the following:
01127        * [foo] define a new category named 'foo'
01128        * [foo](!) define a new template category named 'foo'
01129        * [foo](+) append to category 'foo', error if foo does not exist.
01130        * [foo](a) define a new category and inherit from template a.
01131        *    You can put a comma-separated list of templates and '!' and '+'
01132        *    between parentheses, with obvious meaning.
01133        */
01134       struct ast_category *newcat = NULL;
01135       char *catname;
01136 
01137       c = strchr(cur, ']');
01138       if (!c) {
01139          ast_log(LOG_WARNING, "parse error: no closing ']', line %d of %s\n", lineno, configfile);
01140          return -1;
01141       }
01142       *c++ = '\0';
01143       cur++;
01144       if (*c++ != '(')
01145          c = NULL;
01146       catname = cur;
01147       if (!(*cat = newcat = ast_category_new(catname,
01148             S_OR(suggested_include_file, cfg->include_level == 1 ? "" : configfile),
01149             lineno))) {
01150          return -1;
01151       }
01152       (*cat)->lineno = lineno;
01153       *last_var = 0;
01154       *last_cat = newcat;
01155       
01156       /* add comments */
01157       if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01158          newcat->precomments = ALLOC_COMMENT(comment_buffer);
01159       if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01160          newcat->sameline = ALLOC_COMMENT(lline_buffer);
01161       if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01162          CB_RESET(comment_buffer, lline_buffer);
01163       
01164       /* If there are options or categories to inherit from, process them now */
01165       if (c) {
01166          if (!(cur = strchr(c, ')'))) {
01167             ast_log(LOG_WARNING, "parse error: no closing ')', line %d of %s\n", lineno, configfile);
01168             return -1;
01169          }
01170          *cur = '\0';
01171          while ((cur = strsep(&c, ","))) {
01172             if (!strcasecmp(cur, "!")) {
01173                (*cat)->ignored = 1;
01174             } else if (!strcasecmp(cur, "+")) {
01175                *cat = category_get(cfg, catname, 1);
01176                if (!(*cat)) {
01177                   if (newcat)
01178                      ast_category_destroy(newcat);
01179                   ast_log(LOG_WARNING, "Category addition requested, but category '%s' does not exist, line %d of %s\n", catname, lineno, configfile);
01180                   return -1;
01181                }
01182                if (newcat) {
01183                   move_variables(newcat, *cat);
01184                   ast_category_destroy(newcat);
01185                   newcat = NULL;
01186                }
01187             } else {
01188                struct ast_category *base;
01189             
01190                base = category_get(cfg, cur, 1);
01191                if (!base) {
01192                   ast_log(LOG_WARNING, "Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur, lineno, configfile);
01193                   return -1;
01194                }
01195                inherit_category(*cat, base);
01196             }
01197          }
01198       }
01199       if (newcat)
01200          ast_category_append(cfg, *cat);
01201    } else if (cur[0] == '#') { /* A directive - #include or #exec */
01202       char *cur2;
01203       char real_inclusion_name[256];
01204       int do_include = 0;  /* otherwise, it is exec */
01205 
01206       cur++;
01207       c = cur;
01208       while (*c && (*c > 32)) {
01209          c++;
01210       }
01211 
01212       if (*c) {
01213          *c = '\0';
01214          /* Find real argument */
01215          c = ast_strip(c + 1);
01216          if (!(*c)) {
01217             c = NULL;
01218          }
01219       } else {
01220          c = NULL;
01221       }
01222       if (!strcasecmp(cur, "include")) {
01223          do_include = 1;
01224       } else if (!strcasecmp(cur, "exec")) {
01225          if (!ast_opt_exec_includes) {
01226             ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
01227             return 0;   /* XXX is this correct ? or we should return -1 ? */
01228          }
01229       } else {
01230          ast_log(LOG_WARNING, "Unknown directive '#%s' at line %d of %s\n", cur, lineno, configfile);
01231          return 0;   /* XXX is this correct ? or we should return -1 ? */
01232       }
01233 
01234       if (c == NULL) {
01235          ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n", 
01236                do_include ? "include" : "exec",
01237                do_include ? "filename" : "/path/to/executable",
01238                lineno,
01239                configfile);
01240          return 0;   /* XXX is this correct ? or we should return -1 ? */
01241       }
01242 
01243       cur = c;
01244       /* Strip off leading and trailing "'s and <>'s */
01245       /* Dequote */
01246       if ((*c == '"') || (*c == '<')) {
01247          char quote_char = *c;
01248          if (quote_char == '<') {
01249             quote_char = '>';
01250          }
01251 
01252          if (*(c + strlen(c) - 1) == quote_char) {
01253             cur++;
01254             *(c + strlen(c) - 1) = '\0';
01255          }
01256       }
01257       cur2 = cur;
01258 
01259       /* #exec </path/to/executable>
01260          We create a tmp file, then we #include it, then we delete it. */
01261       if (!do_include) {
01262          struct timeval now = ast_tvnow();
01263          if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
01264             config_cache_attribute(configfile, ATTRIBUTE_EXEC, NULL, who_asked);
01265          snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d%d.%ld", (int)now.tv_sec, (int)now.tv_usec, (long)pthread_self());
01266          snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file);
01267          ast_safe_system(cmd);
01268          cur = exec_file;
01269       } else {
01270          if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
01271             config_cache_attribute(configfile, ATTRIBUTE_INCLUDE, cur, who_asked);
01272          exec_file[0] = '\0';
01273       }
01274       /* A #include */
01275       /* record this inclusion */
01276       ast_include_new(cfg, cfg->include_level == 1 ? "" : configfile, cur, !do_include, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name));
01277 
01278       do_include = ast_config_internal_load(cur, cfg, flags, real_inclusion_name, who_asked) ? 1 : 0;
01279       if (!ast_strlen_zero(exec_file))
01280          unlink(exec_file);
01281       if (!do_include) {
01282          ast_log(LOG_ERROR, "The file '%s' was listed as a #include but it does not exist.\n", cur);
01283          return -1;
01284       }
01285       /* XXX otherwise what ? the default return is 0 anyways */
01286 
01287    } else {
01288       /* Just a line (variable = value) */
01289       int object = 0;
01290       if (!(*cat)) {
01291          ast_log(LOG_WARNING,
01292             "parse error: No category context for line %d of %s\n", lineno, configfile);
01293          return -1;
01294       }
01295       c = strchr(cur, '=');
01296 
01297       if (c && c > cur && (*(c - 1) == '+')) {
01298          struct ast_variable *var, *replace = NULL;
01299          struct ast_str **str = ast_threadstorage_get(&appendbuf, sizeof(*str));
01300 
01301          if (!str || !*str) {
01302             return -1;
01303          }
01304 
01305          *(c - 1) = '\0';
01306          c++;
01307          cur = ast_strip(cur);
01308 
01309          /* Must iterate through category until we find last variable of same name (since there could be multiple) */
01310          for (var = ast_category_first(*cat); var; var = var->next) {
01311             if (!strcmp(var->name, cur)) {
01312                replace = var;
01313             }
01314          }
01315 
01316          if (!replace) {
01317             /* Nothing to replace; just set a variable normally. */
01318             goto set_new_variable;
01319          }
01320 
01321          ast_str_set(str, 0, "%s", replace->value);
01322          ast_str_append(str, 0, "%s", c);
01323          ast_str_trim_blanks(*str);
01324          ast_variable_update(*cat, replace->name, ast_skip_blanks(ast_str_buffer(*str)), replace->value, object);
01325       } else if (c) {
01326          *c = 0;
01327          c++;
01328          /* Ignore > in => */
01329          if (*c== '>') {
01330             object = 1;
01331             c++;
01332          }
01333 set_new_variable:
01334          if ((v = ast_variable_new(ast_strip(cur), ast_strip(c), S_OR(suggested_include_file, cfg->include_level == 1 ? "" : configfile)))) {
01335             v->lineno = lineno;
01336             v->object = object;
01337             *last_cat = 0;
01338             *last_var = v;
01339             /* Put and reset comments */
01340             v->blanklines = 0;
01341             ast_variable_append(*cat, v);
01342             /* add comments */
01343             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01344                v->precomments = ALLOC_COMMENT(comment_buffer);
01345             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01346                v->sameline = ALLOC_COMMENT(lline_buffer);
01347             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01348                CB_RESET(comment_buffer, lline_buffer);
01349             
01350          } else {
01351             return -1;
01352          }
01353       } else {
01354          ast_log(LOG_WARNING, "No '=' (equal sign) in line %d of %s\n", lineno, configfile);
01355       }
01356    }
01357    return 0;
01358 }

int read_config_maps ( void   ) 

Exposed re-initialization method for core process.

This method is intended for use only with the core re-initialization and is not designed to be called from any user applications.

Definition at line 2108 of file config.c.

References append_mapping(), ast_config_destroy(), ast_config_internal_load(), ast_config_new(), ast_copy_string(), ast_log(), ast_variable_browse(), clear_config_maps(), config, CONFIG_FLAG_NOREALTIME, CONFIG_STATUS_FILEINVALID, ast_flags::flags, LOG_WARNING, ast_config::max_include_level, ast_variable::name, ast_variable::next, strsep(), table, and ast_variable::value.

Referenced by main().

02109 {
02110    struct ast_config *config, *configtmp;
02111    struct ast_variable *v;
02112    char *driver, *table, *database, *textpri, *stringp, *tmp;
02113    struct ast_flags flags = { CONFIG_FLAG_NOREALTIME };
02114    int pri;
02115 
02116    clear_config_maps();
02117 
02118    configtmp = ast_config_new();
02119    configtmp->max_include_level = 1;
02120    config = ast_config_internal_load(extconfig_conf, configtmp, flags, "", "extconfig");
02121    if (config == CONFIG_STATUS_FILEINVALID) {
02122       return -1;
02123    } else if (!config) {
02124       ast_config_destroy(configtmp);
02125       return 0;
02126    }
02127 
02128    for (v = ast_variable_browse(config, "settings"); v; v = v->next) {
02129       char buf[512];
02130       ast_copy_string(buf, v->value, sizeof(buf));
02131       stringp = buf;
02132       driver = strsep(&stringp, ",");
02133 
02134       if ((tmp = strchr(stringp, '\"')))
02135          stringp = tmp;
02136 
02137       /* check if the database text starts with a double quote */
02138       if (*stringp == '"') {
02139          stringp++;
02140          database = strsep(&stringp, "\"");
02141          strsep(&stringp, ",");
02142       } else {
02143          /* apparently this text has no quotes */
02144          database = strsep(&stringp, ",");
02145       }
02146 
02147       table = strsep(&stringp, ",");
02148       textpri = strsep(&stringp, ",");
02149       if (!textpri || !(pri = atoi(textpri))) {
02150          pri = 1;
02151       }
02152 
02153       if (!strcmp(v->name, extconfig_conf)) {
02154          ast_log(LOG_WARNING, "Cannot bind '%s'!\n", extconfig_conf);
02155          continue;
02156       }
02157 
02158       if (!strcmp(v->name, "asterisk.conf")) {
02159          ast_log(LOG_WARNING, "Cannot bind 'asterisk.conf'!\n");
02160          continue;
02161       }
02162 
02163       if (!strcmp(v->name, "logger.conf")) {
02164          ast_log(LOG_WARNING, "Cannot bind 'logger.conf'!\n");
02165          continue;
02166       }
02167 
02168       if (!driver || !database)
02169          continue;
02170       if (!strcasecmp(v->name, "sipfriends")) {
02171          ast_log(LOG_WARNING, "The 'sipfriends' table is obsolete, update your config to use sippeers instead.\n");
02172          append_mapping("sippeers", driver, database, table ? table : "sipfriends", pri);
02173       } else if (!strcasecmp(v->name, "iaxfriends")) {
02174          ast_log(LOG_WARNING, "The 'iaxfriends' table is obsolete, update your config to use iaxusers and iaxpeers, though they can point to the same table.\n");
02175          append_mapping("iaxusers", driver, database, table ? table : "iaxfriends", pri);
02176          append_mapping("iaxpeers", driver, database, table ? table : "iaxfriends", pri);
02177       } else 
02178          append_mapping(v->name, driver, database, table, pri);
02179    }
02180       
02181    ast_config_destroy(config);
02182    return 0;
02183 }

int register_config_cli ( void   ) 

Exposed initialization method for core process.

This method is intended for use only with the core initialization and is not designed to be called from any user applications.

Definition at line 2895 of file config.c.

References ARRAY_LEN, ast_cli_register_multiple(), and cli_config.

Referenced by main().

02896 {
02897    ast_cli_register_multiple(cli_config, ARRAY_LEN(cli_config));
02898    return 0;
02899 }

static struct inclfile* set_fn ( char *  fn,
int  fn_size,
const char *  file,
const char *  configfile,
struct ao2_container fileset 
) [static]

Definition at line 1699 of file config.c.

References ao2_alloc, ao2_find, ao2_link, ao2_ref, ast_config_AST_CONFIG_DIR, ast_copy_string(), ast_strdup, ast_strlen_zero(), inclfile::fname, inclfile_destroy(), inclfile::lineno, and OBJ_POINTER.

Referenced by ast_config_text_file_save().

01700 {
01701    struct inclfile lookup;
01702    struct inclfile *fi;
01703 
01704    if (ast_strlen_zero(file)) {
01705       if (configfile[0] == '/')
01706          ast_copy_string(fn, configfile, fn_size);
01707       else
01708          snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, configfile);
01709    } else if (file[0] == '/')
01710       ast_copy_string(fn, file, fn_size);
01711    else
01712       snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, file);
01713    lookup.fname = fn;
01714    fi = ao2_find(fileset, &lookup, OBJ_POINTER);
01715    if (fi) {
01716       /* Found existing include file scratch pad. */
01717       return fi;
01718    }
01719 
01720    /* set up a file scratch pad */
01721    fi = ao2_alloc(sizeof(struct inclfile), inclfile_destroy);
01722    if (!fi) {
01723       /* Scratch pad creation failed. */
01724       return NULL;
01725    }
01726    fi->fname = ast_strdup(fn);
01727    if (!fi->fname) {
01728       /* Scratch pad creation failed. */
01729       ao2_ref(fi, -1);
01730       return NULL;
01731    }
01732    fi->lineno = 1;
01733 
01734    ao2_link(fileset, fi);
01735 
01736    return fi;
01737 }

static struct ast_variable* variable_clone ( const struct ast_variable old  )  [static]

Definition at line 610 of file config.c.

References ast_variable_new(), ast_variable::blanklines, ast_variable::file, ast_variable::lineno, ast_variable::name, ast_variable::object, and ast_variable::value.

Referenced by inherit_category().

00611 {
00612    struct ast_variable *new = ast_variable_new(old->name, old->value, old->file);
00613 
00614    if (new) {
00615       new->lineno = old->lineno;
00616       new->object = old->object;
00617       new->blanklines = old->blanklines;
00618       /* TODO: clone comments? */
00619    }
00620 
00621    return new;
00622 }


Variable Documentation

struct ast_threadstorage appendbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_appendbuf , .custom_init = init_appendbuf , } [static]

Definition at line 103 of file config.c.

Referenced by process_text_line().

struct ast_cli_entry cli_config[] [static]

Initial value:

 {
   { .handler =  handle_cli_core_show_config_mappings , .summary =  "Display config mappings (file names to config engines)" ,__VA_ARGS__ },
   { .handler =  handle_cli_config_reload , .summary =  "Force a reload on modules using a particular configuration file" ,__VA_ARGS__ },
   { .handler =  handle_cli_config_list , .summary =  "Show all files that have loaded a configuration file" ,__VA_ARGS__ },
}

Definition at line 2889 of file config.c.

Referenced by register_config_cli().

struct ast_config_engine* config_engine_list [static]

Definition at line 192 of file config.c.

Referenced by ast_config_engine_deregister(), ast_config_engine_register(), ast_config_internal_load(), and handle_cli_core_show_config_mappings().

ast_mutex_t config_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 191 of file config.c.

Referenced by ast_calendar_config_release(), ast_config_engine_deregister(), ast_config_engine_register(), clear_config_maps(), find_engine(), handle_cli_core_show_config_mappings(), load_config(), and load_tech_calendars().

struct ast_config_map * config_maps [static]

Referenced by append_mapping(), ast_realtime_enabled(), clear_config_maps(), find_engine(), and handle_cli_core_show_config_mappings().

char* extconfig_conf = "extconfig.conf" [static]

Definition at line 65 of file config.c.

struct ast_config_engine text_file_engine [static]

Initial value:

 {
   .name = "text",
   .load_func = config_text_file_load,
}

Definition at line 2261 of file config.c.

Referenced by ast_config_internal_load().


Generated on Mon Mar 19 11:30:46 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7