Wed Oct 28 11:52:14 2009

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 dependency graph for config.c:

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

Enumerations

enum  config_cache_attribute_enum { ATTRIBUTE_INCLUDE = 0, ATTRIBUTE_EXEC = 1 }

Functions

static void __init_appendbuf (void)
static struct ast_commentALLOC_COMMENT (const struct ast_str *buffer)
static int append_mapping (const char *name, const char *driver, const char *database, const char *table)
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)
struct 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.
struct ast_variableast_category_first (struct ast_category *cat)
 given a pointer to a category, return the root variable. This is equivalent to ast_variable_browse(), but more efficient if we already have the struct ast_category * (e.g. from ast_category_get())
struct 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.
struct 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)
struct 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.
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.
struct ast_categoryast_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.
struct 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)
struct ast_configast_config_load2 (const char *filename, const char *who_asked, struct ast_flags flags)
 Load a config file.
struct 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. 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.
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.
static void ast_destroy_comments (struct ast_category *cat)
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)
struct ast_config_includeast_include_find (struct ast_config *conf, const char *included_file)
struct 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)
struct ast_variableast_load_realtime (const char *family,...)
 Retrieve realtime configuration.
struct ast_variableast_load_realtime_all (const char *family,...)
static struct ast_variableast_load_realtime_helper (const char *family, va_list ap)
struct 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,...)
 Helper function to parse arguments See documentation in config.h.
int ast_realtime_enabled ()
 Check if there's any realtime engines loaded.
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_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)
struct ast_variableast_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.
int ast_variable_delete (struct ast_category *category, const char *variable, const char *match, const char *line)
void ast_variable_insert (struct ast_category *category, struct ast_variable *variable, const char *line)
struct 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.
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 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, 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 This method is intended for use only with the core re-initialization and is not designed to be called from any user applications.
int register_config_cli ()
 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.
static void set_fn (char *fn, int fn_size, const char *file, const char *configfile, struct ao2_container *fileset, struct inclfile **fi)
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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
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 doc/realtime.txt and doc/extconfig.txt

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 93 of file config.c.

Referenced by config_text_file_load().

#define COMMENT_END   "--;"

Definition at line 53 of file config.c.

#define COMMENT_META   ';'

Definition at line 54 of file config.c.

Referenced by config_text_file_load().

#define COMMENT_START   ";--"

Definition at line 52 of file config.c.

#define COMMENT_TAG   '-'

Definition at line 55 of file config.c.

Referenced by config_text_file_load().

#define MAX_INCLUDE_LEVEL   10

Definition at line 170 of file config.c.

Referenced by ast_config_new().

#define MAX_NESTED_COMMENTS   128

Definition at line 51 of file config.c.

Referenced by config_text_file_load().


Enumeration Type Documentation

Enumerator:
ATTRIBUTE_INCLUDE 
ATTRIBUTE_EXEC 

Definition at line 855 of file config.c.

00855                                  {
00856    ATTRIBUTE_INCLUDE = 0,
00857    ATTRIBUTE_EXEC = 1,
00858 };


Function Documentation

static void __init_appendbuf ( void   )  [static]

Definition at line 90 of file config.c.

00096 {

static struct ast_comment* ALLOC_COMMENT ( const struct ast_str buffer  )  [static, read]

Definition at line 115 of file config.c.

References ast_calloc, ast_comment::cmt, ast_str::str, and ast_str::used.

Referenced by config_text_file_load(), and process_text_line().

00116 { 
00117    struct ast_comment *x = NULL;
00118    if (buffer && buffer->used)
00119       x = ast_calloc(1, sizeof(*x) + buffer->used + 1);
00120    if (x)
00121       strcpy(x->cmt, buffer->str);
00122    return x;
00123 }

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

Definition at line 1845 of file config.c.

References ast_calloc, ast_verb, config_maps, ast_config_map::database, ast_config_map::driver, map, ast_config_map::name, ast_config_map::next, ast_config_map::stuff, and ast_config_map::table.

Referenced by read_config_maps().

01846 {
01847    struct ast_config_map *map;
01848    int length;
01849 
01850    length = sizeof(*map);
01851    length += strlen(name) + 1;
01852    length += strlen(driver) + 1;
01853    length += strlen(database) + 1;
01854    if (table)
01855       length += strlen(table) + 1;
01856 
01857    if (!(map = ast_calloc(1, length)))
01858       return -1;
01859 
01860    map->name = map->stuff;
01861    strcpy(map->name, name);
01862    map->driver = map->name + strlen(map->name) + 1;
01863    strcpy(map->driver, driver);
01864    map->database = map->driver + strlen(map->driver) + 1;
01865    strcpy(map->database, database);
01866    if (table) {
01867       map->table = map->database + strlen(map->database) + 1;
01868       strcpy(map->table, table);
01869    }
01870    map->next = config_maps;
01871 
01872    ast_verb(2, "Binding %s to %s/%s/%s\n", map->name, map->driver, map->database, map->table ? map->table : map->name);
01873 
01874    config_maps = map;
01875    return 0;
01876 }

void ast_category_append ( struct ast_config config,
struct ast_category category 
)

Definition at line 494 of file config.c.

References ast_config::current, ast_config::include_level, ast_category::include_level, ast_config::last, ast_category::next, and ast_config::root.

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(), and realtime_multi_pgsql().

00495 {
00496    if (config->last)
00497       config->last->next = category;
00498    else
00499       config->root = category;
00500    category->include_level = config->include_level;
00501    config->last = category;
00502    config->current = category;
00503 }

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 604 of file config.c.

References ast_config::last_browse, ast_category::name, ast_category::next, next_available_category(), and ast_config::root.

Referenced by __init_manager(), __queues_show(), action_getconfig(), action_getconfigjson(), action_listcategories(), aji_load_config(), complete_sipnotify(), find_queue_by_name_rt(), get_insecure_variable_from_config(), gtalk_load_config(), iax_provision_reload(), ind_load_module(), jingle_load_config(), load_config(), load_module(), load_moh_classes(), load_odbc_config(), misdn_cfg_init(), osp_load(), parse_config(), pbx_load_config(), pbx_load_users(), read_agent_config(), realtime_directory(), realtime_switch_common(), reload(), reload_config(), reload_followme(), reload_queue_rules(), reload_queues(), rpt_master(), search_directory(), set_config(), setup_dahdi(), show_users_realtime(), sla_load_config(), update_realtime_members(), and vm_change_password().

00605 {  
00606    struct ast_category *cat = NULL;
00607 
00608    if (prev && config->last_browse && (config->last_browse->name == prev))
00609       cat = config->last_browse->next;
00610    else if (!prev && config->root)
00611       cat = config->root;
00612    else if (prev) {
00613       for (cat = config->root; cat; cat = cat->next) {
00614          if (cat->name == prev) {
00615             cat = cat->next;
00616             break;
00617          }
00618       }
00619       if (!cat) {
00620          for (cat = config->root; cat; cat = cat->next) {
00621             if (!strcasecmp(cat->name, prev)) {
00622                cat = cat->next;
00623                break;
00624             }
00625          }
00626       }
00627    }
00628    
00629    if (cat)
00630       cat = next_available_category(cat);
00631 
00632    config->last_browse = cat;
00633    return (cat) ? cat->name : NULL;
00634 }

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

Definition at line 765 of file config.c.

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

Referenced by handle_updates().

00766 {
00767    struct ast_category *prev=NULL, *cat;
00768 
00769    cat = cfg->root;
00770    while (cat) {
00771       if (cat->name == category) {
00772          if (prev) {
00773             prev->next = cat->next;
00774             if (cat == cfg->last)
00775                cfg->last = prev;
00776          } else {
00777             cfg->root = cat->next;
00778             if (cat == cfg->last)
00779                cfg->last = NULL;
00780          }
00781          ast_category_destroy(cat);
00782          return 0;
00783       }
00784       prev = cat;
00785       cat = cat->next;
00786    }
00787 
00788    prev = NULL;
00789    cat = cfg->root;
00790    while (cat) {
00791       if (!strcasecmp(cat->name, category)) {
00792          if (prev) {
00793             prev->next = cat->next;
00794             if (cat == cfg->last)
00795                cfg->last = prev;
00796          } else {
00797             cfg->root = cat->next;
00798             if (cat == cfg->last)
00799                cfg->last = NULL;
00800          }
00801          ast_category_destroy(cat);
00802          return 0;
00803       }
00804       prev = cat;
00805       cat = cat->next;
00806    }
00807    return -1;
00808 }

void ast_category_destroy ( struct ast_category cat  ) 

Definition at line 554 of file config.c.

References ast_destroy_comments(), ast_destroy_template_list(), ast_free, ast_variables_destroy(), ast_category::file, free, and ast_category::root.

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

00555 {
00556    ast_variables_destroy(cat->root);
00557    if (cat->file) {
00558       free(cat->file);
00559       cat->file = 0;
00560    }
00561    ast_destroy_comments(cat);
00562    ast_destroy_template_list(cat);
00563    ast_free(cat);
00564 }

struct ast_variable* ast_category_detach_variables ( struct ast_category cat  )  [read]

Definition at line 636 of file config.c.

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

Referenced by realtime_switch_common().

00637 {
00638    struct ast_variable *v;
00639 
00640    v = cat->root;
00641    cat->root = NULL;
00642    cat->last = NULL;
00643 
00644    return v;
00645 }

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 810 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().

00811 {
00812    struct ast_category *cat;
00813 
00814    for (cat = cfg->root; cat; cat = cat->next) {
00815       if (!strcasecmp(cat->name, category))
00816          continue;
00817       ast_variables_destroy(cat->root);
00818       cat->root = NULL;
00819       cat->last = NULL;
00820       return 0;
00821    }
00822 
00823    return -1;
00824 }

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 489 of file config.c.

References ast_category_get().

00490 {
00491    return !!ast_category_get(config, category_name);
00492 }

struct ast_variable* ast_category_first ( struct ast_category cat  )  [read]

given a pointer to a category, return the root variable. This is equivalent to ast_variable_browse(), but more efficient if we already have the struct ast_category * (e.g. from ast_category_get())

return the first var of a category

Definition at line 590 of file config.c.

References ast_category::root.

Referenced by process_text_line().

00591 {
00592    return (cat) ? cat->root : NULL;
00593 }

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

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 484 of file config.c.

References category_get().

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

00485 {
00486    return category_get(config, category_name, 0);
00487 }

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 505 of file config.c.

References ast_category::name, ast_category::next, and ast_config::root.

Referenced by handle_updates().

00506 {
00507    struct ast_category *cur_category;
00508 
00509    if (!cat || !match)
00510       return;
00511    if (!strcasecmp(config->root->name, match)) {
00512       cat->next = config->root;
00513       config->root = cat;
00514       return;
00515    } 
00516    for (cur_category = config->root; cur_category; cur_category = cur_category->next) {
00517       if (!strcasecmp(cur_category->next->name, match)) {
00518          cat->next = cur_category->next;
00519          cur_category->next = cat;
00520          break;
00521       }
00522    }
00523 }

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

Create a category structure.

Definition at line 455 of file config.c.

References ast_calloc, ast_copy_string(), ast_category::file, ast_category::lineno, ast_category::name, and 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(), and realtime_multi_pgsql().

00456 {
00457    struct ast_category *category;
00458 
00459    if ((category = ast_calloc(1, sizeof(*category))))
00460       ast_copy_string(category->name, name, sizeof(category->name));
00461    category->file = strdup(in_file);
00462    category->lineno = lineno; /* if you don't know the lineno, set it to 999999 or something real big */
00463    return category;
00464 }

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

Definition at line 647 of file config.c.

References ast_copy_string(), and ast_category::name.

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

00648 {
00649    ast_copy_string(cat->name, name, sizeof(cat->name));
00650 }

struct ast_variable* ast_category_root ( struct ast_config config,
char *  cat 
) [read]

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 595 of file config.c.

References ast_category_get(), and ast_category::root.

Referenced by get_insecure_variable_from_config().

00596 {
00597    struct ast_category *category = ast_category_get(config, cat);
00598 
00599    if (category)
00600       return category->root;
00601    return NULL;
00602 }

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 2142 of file config.c.

References find_engine().

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

02143 {
02144    struct ast_config_engine *eng;
02145 
02146    eng = find_engine(family, NULL, 0, NULL, 0);
02147    if (eng)
02148       return 1;
02149    return 0;
02150 }

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 826 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_load(), __ast_http_post_load(), __ast_rtp_reload(), __ast_udptl_reload(), __init_manager(), __queues_show(), _dsp_init(), action_getconfig(), action_getconfigjson(), action_listcategories(), action_updateconfig(), adsi_load(), advanced_options(), aji_load_config(), ast_config_load2(), ast_readconfig(), conf_exec(), config_function_read(), config_module(), directory_exec(), do_reload(), festival_exec(), find_conf(), handle_cli_dialplan_save(), iax_provision_reload(), ind_load_module(), init_logger_chain(), load_config(), load_config_meetme(), load_module(), load_modules(), load_moh_classes(), load_odbc_config(), load_realtime_queue(), load_rpt_vars(), make_email_file(), misdn_cfg_init(), node_lookup(), odbc_load_module(), osp_load(), parse_config(), pbx_load_config(), pbx_load_users(), play_message(), prep_email_sub_vars(), private_enum_init(), read_agent_config(), read_config_maps(), realtime_directory(), realtime_multi_handler(), realtime_peer(), realtime_switch_common(), reload(), reload_config(), reload_followme(), reload_queue_rules(), reload_queues(), rpt_master(), run_startup_commands(), set_config(), setup_dahdi(), show_users_realtime(), sla_load_config(), smdi_load(), store_config(), tds_load_module(), unload_module(), update_realtime_members(), and vm_forwardoptions().

00827 {
00828    struct ast_category *cat, *catn;
00829 
00830    if (!cfg)
00831       return;
00832 
00833    ast_includes_destroy(cfg->includes);
00834 
00835    cat = cfg->root;
00836    while (cat) {
00837       catn = cat;
00838       cat = cat->next;
00839       ast_category_destroy(catn);
00840    }
00841    ast_free(cfg);
00842 }

int ast_config_engine_deregister ( struct ast_config_engine del  ) 

Deregister config engine.

Return values:
0 Always

Definition at line 1968 of file config.c.

References ast_mutex_lock(), ast_mutex_unlock(), config_lock, last, and ast_config_engine::next.

Referenced by unload_module().

01969 {
01970    struct ast_config_engine *ptr, *last=NULL;
01971 
01972    ast_mutex_lock(&config_lock);
01973 
01974    for (ptr = config_engine_list; ptr; ptr=ptr->next) {
01975       if (ptr == del) {
01976          if (last)
01977             last->next = ptr->next;
01978          else
01979             config_engine_list = ptr->next;
01980          break;
01981       }
01982       last = ptr;
01983    }
01984 
01985    ast_mutex_unlock(&config_lock);
01986 
01987    return 0;
01988 }

int ast_config_engine_register ( struct ast_config_engine newconfig  ) 

Register config engine.

Return values:
1 Always

Definition at line 1949 of file config.c.

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

Referenced by load_module().

01950 {
01951    struct ast_config_engine *ptr;
01952 
01953    ast_mutex_lock(&config_lock);
01954 
01955    if (!config_engine_list) {
01956       config_engine_list = new;
01957    } else {
01958       for (ptr = config_engine_list; ptr->next; ptr=ptr->next);
01959       ptr->next = new;
01960    }
01961 
01962    ast_mutex_unlock(&config_lock);
01963    ast_log(LOG_NOTICE,"Registered Config Engine %s\n", new->name);
01964 
01965    return 1;
01966 }

struct ast_category* ast_config_get_current_category ( const struct ast_config cfg  )  [read]

Retrieve the current category name being built. API for backend configuration engines while building a configuration set.

Definition at line 844 of file config.c.

References ast_config::current.

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

00845 {
00846    return cfg->current;
00847 }

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 
) [read]

Definition at line 2030 of file config.c.

References ast_log(), CONFIG_STATUS_FILEUNCHANGED, db, find_engine(), ast_config::include_level, ast_config_engine::load_func, LOG_WARNING, ast_config::max_include_level, and table.

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

02031 {
02032    char db[256];
02033    char table[256];
02034    struct ast_config_engine *loader = &text_file_engine;
02035    struct ast_config *result; 
02036 
02037    /* The config file itself bumps include_level by 1 */
02038    if (cfg->max_include_level > 0 && cfg->include_level == cfg->max_include_level + 1) {
02039       ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level);
02040       return NULL;
02041    }
02042 
02043    cfg->include_level++;
02044 
02045    if (strcmp(filename, extconfig_conf) && strcmp(filename, "asterisk.conf") && config_engine_list) {
02046       struct ast_config_engine *eng;
02047 
02048       eng = find_engine(filename, db, sizeof(db), table, sizeof(table));
02049 
02050 
02051       if (eng && eng->load_func) {
02052          loader = eng;
02053       } else {
02054          eng = find_engine("global", db, sizeof(db), table, sizeof(table));
02055          if (eng && eng->load_func)
02056             loader = eng;
02057       }
02058    }
02059 
02060    result = loader->load_func(db, table, filename, cfg, flags, suggested_include_file, who_asked);
02061 
02062    if (result && result != CONFIG_STATUS_FILEUNCHANGED)
02063       result->include_level--;
02064    else
02065       cfg->include_level--;
02066 
02067    return result;
02068 }

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

Load a config file.

Parameters:
filename path of file to open. If no preceding '/' character, path is considered relative to AST_CONFIG_DIR Create a config structure from a given configuration file.
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).
Returns:
an ast_config data structure on success
Return values:
NULL on error

Definition at line 2070 of file config.c.

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

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

02071 {
02072    struct ast_config *cfg;
02073    struct ast_config *result;
02074 
02075    cfg = ast_config_new();
02076    if (!cfg)
02077       return NULL;
02078 
02079    result = ast_config_internal_load(filename, cfg, flags, "", who_asked);
02080    if (!result || result == CONFIG_STATUS_FILEUNCHANGED)
02081       ast_config_destroy(cfg);
02082 
02083    return result;
02084 }

struct ast_config* ast_config_new ( void   )  [read]

Create a new base configuration structure.

Definition at line 664 of file config.c.

References ast_calloc, config, MAX_INCLUDE_LEVEL, and ast_config::max_include_level.

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

00665 {
00666    struct ast_config *config;
00667 
00668    if ((config = ast_calloc(1, sizeof(*config))))
00669       config->max_include_level = MAX_INCLUDE_LEVEL;
00670    return config;
00671 }

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 401 of file config.c.

References ast_variable_retrieve().

Referenced by load_config(), pbx_load_users(), and search_directory().

00402 {
00403    const char *tmp;
00404    tmp = ast_variable_retrieve(cfg, cat, var);
00405    if (!tmp)
00406       tmp = ast_variable_retrieve(cfg, "general", var);
00407    return tmp;
00408 }

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 849 of file config.c.

References ast_config::current.

00850 {
00851    /* cast below is just to silence compiler warning about dropping "const" */
00852    cfg->current = (struct ast_category *) cat;
00853 }

static void ast_destroy_comments ( struct ast_category cat  )  [static]

Definition at line 525 of file config.c.

References free, ast_comment::next, ast_category::precomments, ast_category::sameline, and ast_category::trailing.

Referenced by ast_category_destroy().

00526 {
00527    struct ast_comment *n, *p;
00528 
00529    for (p=cat->precomments; p; p=n) {
00530       n = p->next;
00531       free(p);
00532    }
00533    for (p=cat->sameline; p; p=n) {
00534       n = p->next;
00535       free(p);
00536    }
00537    for (p=cat->trailing; p; p=n) {
00538       n = p->next;
00539       free(p);
00540    }
00541    cat->precomments = NULL;
00542    cat->sameline = NULL;
00543    cat->trailing = NULL;
00544 }

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.

Definition at line 2241 of file config.c.

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

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

02242 {
02243    struct ast_config_engine *eng;
02244    int res = -1;
02245    char db[256]="";
02246    char table[256]="";
02247    va_list ap;
02248 
02249    va_start(ap, lookup);
02250    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
02251    if (eng && eng->destroy_func) 
02252       res = eng->destroy_func(db, table, keyfield, lookup, ap);
02253    va_end(ap);
02254 
02255    return res;
02256 }

static void ast_destroy_template_list ( struct ast_category cat  )  [static]

Definition at line 546 of file config.c.

References AST_LIST_REMOVE_HEAD, free, and ast_category::template_instances.

Referenced by ast_category_destroy().

00547 {
00548    struct ast_category_template_instance *x;
00549 
00550    while ((x = AST_LIST_REMOVE_HEAD(&cat->template_instances, next)))
00551       free(x);
00552 }

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

Definition at line 332 of file config.c.

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

Referenced by ast_include_new().

00333 {
00334    struct ast_config_include *x;
00335    for (x=conf->includes;x;x=x->next) {
00336       if (strcmp(x->included_file,included_file) == 0)
00337          return x;
00338    }
00339    return 0;
00340 }

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 
) [read]

Definition at line 241 of file config.c.

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

Referenced by process_text_line().

00242 {
00243    /* a file should be included ONCE. Otherwise, if one of the instances is changed,
00244     * then all be changed. -- how do we know to include it? -- Handling modified 
00245     * instances is possible, I'd have
00246     * to create a new master for each instance. */
00247    struct ast_config_include *inc;
00248    struct stat statbuf;
00249    
00250    inc = ast_include_find(conf, included_file);
00251    if (inc) {
00252       do {
00253          inc->inclusion_count++;
00254          snprintf(real_included_file_name, real_included_file_name_size, "%s~~%d", included_file, inc->inclusion_count);
00255       } while (stat(real_included_file_name, &statbuf) == 0);
00256       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);
00257    } else
00258       *real_included_file_name = 0;
00259    
00260    inc = ast_calloc(1,sizeof(struct ast_config_include));
00261    inc->include_location_file = ast_strdup(from_file);
00262    inc->include_location_lineno = from_lineno;
00263    if (!ast_strlen_zero(real_included_file_name))
00264       inc->included_file = ast_strdup(real_included_file_name);
00265    else
00266       inc->included_file = ast_strdup(included_file);
00267    
00268    inc->exec = is_exec;
00269    if (is_exec)
00270       inc->exec_file = ast_strdup(exec_file);
00271    
00272    /* attach this new struct to the conf struct */
00273    inc->next = conf->includes;
00274    conf->includes = inc;
00275    
00276    return inc;
00277 }

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

Definition at line 279 of file config.c.

References ast_variable::file, ast_category::file, free, ast_config_include::include_location_file, ast_config::includes, ast_variable::next, ast_category::next, ast_config_include::next, ast_category::root, ast_config::root, and strdup.

Referenced by action_updateconfig().

00280 {
00281    struct ast_config_include *incl;
00282    struct ast_category *cat;
00283    struct ast_variable *v;
00284    
00285    int from_len = strlen(from_file);
00286    int to_len = strlen(to_file);
00287    
00288    if (strcmp(from_file, to_file) == 0) /* no use wasting time if the name is the same */
00289       return;
00290    
00291    /* the manager code allows you to read in one config file, then
00292     * write it back out under a different name. But, the new arrangement
00293     * ties output lines to the file name. So, before you try to write
00294     * the config file to disk, better riffle thru the data and make sure
00295     * the file names are changed.
00296     */
00297    /* file names are on categories, includes (of course), and on variables. So,
00298     * traverse all this and swap names */
00299 
00300    for (incl = conf->includes; incl; incl=incl->next) {
00301       if (strcmp(incl->include_location_file,from_file) == 0) {
00302          if (from_len >= to_len)
00303             strcpy(incl->include_location_file, to_file);
00304          else {
00305             free(incl->include_location_file);
00306             incl->include_location_file = strdup(to_file);
00307          }
00308       }
00309    }
00310    for (cat = conf->root; cat; cat = cat->next) {
00311       if (strcmp(cat->file,from_file) == 0) {
00312          if (from_len >= to_len)
00313             strcpy(cat->file, to_file);
00314          else {
00315             free(cat->file);
00316             cat->file = strdup(to_file);
00317          }
00318       }
00319       for (v = cat->root; v; v = v->next) {
00320          if (strcmp(v->file,from_file) == 0) {
00321             if (from_len >= to_len)
00322                strcpy(v->file, to_file);
00323             else {
00324                free(v->file);
00325                v->file = strdup(to_file);
00326             }
00327          }
00328       }
00329    }
00330 }

static void ast_includes_destroy ( struct ast_config_include incls  )  [static]

Definition at line 566 of file config.c.

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

Referenced by ast_config_destroy().

00567 {
00568    struct ast_config_include *incl,*inclnext;
00569    
00570    for (incl=incls; incl; incl = inclnext) {
00571       inclnext = incl->next;
00572       if (incl->include_location_file)
00573          free(incl->include_location_file);
00574       if (incl->exec_file)
00575          free(incl->exec_file);
00576       if (incl->included_file)
00577          free(incl->included_file);
00578       free(incl);
00579    }
00580 }

struct ast_variable* ast_load_realtime ( const char *  family,
  ... 
) [read]

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 that 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.

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

Definition at line 2112 of file config.c.

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

Referenced by copy_plain_file(), find_conf_realtime(), find_user_realtime(), leave_queue(), load_realtime_queue(), local_ast_moh_start(), queue_function_queuewaitingcount(), realtime_alias(), realtime_peer(), realtime_switch_common(), and realtime_user().

02113 {
02114    struct ast_variable *res, *cur, *prev = NULL, *freeme = NULL;
02115    va_list ap;
02116 
02117    va_start(ap, family);
02118    res = ast_load_realtime_helper(family, ap);
02119    va_end(ap);
02120 
02121    /* Eliminate blank entries */
02122    for (cur = res; cur; cur = cur->next) {
02123       if (freeme) {
02124          ast_free(freeme);
02125          freeme = NULL;
02126       }
02127 
02128       if (ast_strlen_zero(cur->value)) {
02129          if (prev)
02130             prev->next = cur->next;
02131          else
02132             res = cur->next;
02133          freeme = cur;
02134       } else {
02135          prev = cur;
02136       }
02137    }
02138    return res;
02139 }

struct ast_variable* ast_load_realtime_all ( const char *  family,
  ... 
) [read]

Definition at line 2100 of file config.c.

References ast_load_realtime_helper().

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

02101 {
02102    struct ast_variable *res;
02103    va_list ap;
02104 
02105    va_start(ap, family);
02106    res = ast_load_realtime_helper(family, ap);
02107    va_end(ap);
02108 
02109    return res;
02110 }

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

Definition at line 2086 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().

02087 {
02088    struct ast_config_engine *eng;
02089    char db[256]="";
02090    char table[256]="";
02091    struct ast_variable *res=NULL;
02092 
02093    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
02094    if (eng && eng->realtime_func) 
02095       res = eng->realtime_func(db, table, ap);
02096 
02097    return res;
02098 }

struct ast_config* ast_load_realtime_multientry ( const char *  family,
  ... 
) [read]

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.

Definition at line 2190 of file config.c.

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

Referenced by __queues_show(), load_realtime_queue(), realtime_directory(), realtime_peer(), realtime_switch_common(), show_users_realtime(), and update_realtime_members().

02191 {
02192    struct ast_config_engine *eng;
02193    char db[256]="";
02194    char table[256]="";
02195    struct ast_config *res=NULL;
02196    va_list ap;
02197 
02198    va_start(ap, family);
02199    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
02200    if (eng && eng->realtime_multi_func) 
02201       res = eng->realtime_multi_func(db, table, ap);
02202    va_end(ap);
02203 
02204    return res;
02205 }

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

Helper function to parse arguments See documentation in config.h.

The argument parsing routine.

Definition at line 2261 of file config.c.

References ast_debug, ast_gethostbyname(), ast_inet_ntoa(), ast_strdupa, buf, hp, 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_sip_ouraddrfor(), check_via_response(), and reload_config().

02263 {
02264    va_list ap;
02265    int error = 0;
02266 
02267    va_start(ap, p_result);
02268    switch (flags & PARSE_TYPE) {
02269    case PARSE_INT32:
02270        {
02271       int32_t *result = p_result;
02272       int32_t x, def = result ? *result : 0,
02273          high = (int32_t)0x7fffffff,
02274          low  = (int32_t)0x80000000;
02275       /* optional argument: first default value, then range */
02276       if (flags & PARSE_DEFAULT)
02277          def = va_arg(ap, int32_t);
02278       if (flags & (PARSE_IN_RANGE|PARSE_OUT_RANGE)) {
02279          /* range requested, update bounds */
02280          low = va_arg(ap, int32_t);
02281          high = va_arg(ap, int32_t);
02282       }
02283       x = strtol(arg, NULL, 0);
02284       error = (x < low) || (x > high);
02285       if (flags & PARSE_OUT_RANGE)
02286          error = !error;
02287       if (result)
02288          *result  = error ? def : x;
02289       ast_debug(3,
02290          "extract int from [%s] in [%d, %d] gives [%d](%d)\n",
02291          arg, low, high,
02292          result ? *result : x, error);
02293       break;
02294        }
02295 
02296    case PARSE_UINT32:
02297        {
02298       uint32_t *result = p_result;
02299       uint32_t x, def = result ? *result : 0,
02300          low = 0, high = (uint32_t)~0;
02301       /* optional argument: first default value, then range */
02302       if (flags & PARSE_DEFAULT)
02303          def = va_arg(ap, uint32_t);
02304       if (flags & (PARSE_IN_RANGE|PARSE_OUT_RANGE)) {
02305          /* range requested, update bounds */
02306          low = va_arg(ap, uint32_t);
02307          high = va_arg(ap, uint32_t);
02308       }
02309       x = strtoul(arg, NULL, 0);
02310       error = (x < low) || (x > high);
02311       if (flags & PARSE_OUT_RANGE)
02312          error = !error;
02313       if (result)
02314          *result  = error ? def : x;
02315       ast_debug(3,
02316          "extract uint from [%s] in [%u, %u] gives [%u](%d)\n",
02317          arg, low, high,
02318          result ? *result : x, error);
02319       break;
02320        }
02321 
02322    case PARSE_DOUBLE:
02323        {
02324       double *result = p_result;
02325       double x, def = result ? *result : 0,
02326          low = -HUGE_VAL, high = HUGE_VAL;
02327 
02328       /* optional argument: first default value, then range */
02329       if (flags & PARSE_DEFAULT)
02330          def = va_arg(ap, double);
02331       if (flags & (PARSE_IN_RANGE|PARSE_OUT_RANGE)) {
02332          /* range requested, update bounds */
02333          low = va_arg(ap, double);
02334          high = va_arg(ap, double);
02335       }
02336       x = strtod(arg, NULL);
02337       error = (x < low) || (x > high);
02338       if (flags & PARSE_OUT_RANGE)
02339          error = !error;
02340       if (result)
02341          *result  = error ? def : x;
02342       ast_debug(3,
02343          "extract double from [%s] in [%f, %f] gives [%f](%d)\n",
02344          arg, low, high,
02345          result ? *result : x, error);
02346       break;
02347        }
02348    case PARSE_INADDR:
02349        {
02350       char *port, *buf;
02351       struct sockaddr_in _sa_buf;   /* buffer for the result */
02352       struct sockaddr_in *sa = p_result ?
02353          (struct sockaddr_in *)p_result : &_sa_buf;
02354       /* default is either the supplied value or the result itself */
02355       struct sockaddr_in *def = (flags & PARSE_DEFAULT) ?
02356          va_arg(ap, struct sockaddr_in *) : sa;
02357       struct hostent *hp;
02358       struct ast_hostent ahp;
02359 
02360       memset(&_sa_buf, '\0', sizeof(_sa_buf)); /* clear buffer */
02361       /* duplicate the string to strip away the :port */
02362       port = ast_strdupa(arg);
02363       buf = strsep(&port, ":");
02364       sa->sin_family = AF_INET;  /* assign family */
02365       /*
02366        * honor the ports flag setting, assign default value
02367        * in case of errors or field unset.
02368        */
02369       flags &= PARSE_PORT_MASK; /* the only flags left to process */
02370       if (port) {
02371          if (flags == PARSE_PORT_FORBID) {
02372             error = 1;  /* port was forbidden */
02373             sa->sin_port = def->sin_port;
02374          } else if (flags == PARSE_PORT_IGNORE)
02375             sa->sin_port = def->sin_port;
02376          else /* accept or require */
02377             sa->sin_port = htons(strtol(port, NULL, 0));
02378       } else {
02379          sa->sin_port = def->sin_port;
02380          if (flags == PARSE_PORT_REQUIRE)
02381             error = 1;
02382       }
02383       /* Now deal with host part, even if we have errors before. */
02384       hp = ast_gethostbyname(buf, &ahp);
02385       if (hp)  /* resolved successfully */
02386          memcpy(&sa->sin_addr, hp->h_addr, sizeof(sa->sin_addr));
02387       else {
02388          error = 1;
02389          sa->sin_addr = def->sin_addr;
02390       }
02391       ast_debug(3,
02392          "extract inaddr from [%s] gives [%s:%d](%d)\n",
02393          arg, ast_inet_ntoa(sa->sin_addr),
02394          ntohs(sa->sin_port), error);
02395          break;
02396        }
02397    }
02398    va_end(ap);
02399    return error;
02400 }

int ast_realtime_enabled ( void   ) 

Check if there's any realtime engines loaded.

Definition at line 2153 of file config.c.

References config_maps.

Referenced by action_coresettings(), and handle_show_settings().

02154 {
02155    return config_maps ? 1 : 0;
02156 }

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

Inform realtime what fields that may be stored.

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 that you should use the constant SENTINEL to terminate arguments, in order to preserve cross-platform compatibility.

Since:
1.6.1

Definition at line 2158 of file config.c.

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

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

02159 {
02160    struct ast_config_engine *eng;
02161    char db[256] = "";
02162    char table[256] = "";
02163    va_list ap;
02164    int res = -1;
02165 
02166    va_start(ap, family);
02167    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
02168    if (eng && eng->require_func) {
02169       res = eng->require_func(db, table, ap);
02170    }
02171    va_end(ap);
02172 
02173    return res;
02174 }

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. 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.

Definition at line 2224 of file config.c.

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

Referenced by ast_queue_log(), copy_plain_file(), function_realtime_store(), and leave_voicemail().

02225 {
02226    struct ast_config_engine *eng;
02227    int res = -1;
02228    char db[256]="";
02229    char table[256]="";
02230    va_list ap;
02231 
02232    va_start(ap, family);
02233    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
02234    if (eng && eng->store_func) 
02235       res = eng->store_func(db, table, ap);
02236    va_end(ap);
02237 
02238    return res;
02239 }

int ast_unload_realtime ( const char *  family  ) 

Release any resources cached for a realtime family.

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
Since:
1.6.1

Definition at line 2176 of file config.c.

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

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

02177 {
02178    struct ast_config_engine *eng;
02179    char db[256] = "";
02180    char table[256] = "";
02181    int res = -1;
02182 
02183    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
02184    if (eng && eng->unload_func) {
02185       res = eng->unload_func(db, table);
02186    }
02187    return res;
02188 }

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.

Definition at line 2207 of file config.c.

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

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

02208 {
02209    struct ast_config_engine *eng;
02210    int res = -1;
02211    char db[256]="";
02212    char table[256]="";
02213    va_list ap;
02214 
02215    va_start(ap, lookup);
02216    eng = find_engine(family, db, sizeof(db), table, sizeof(table));
02217    if (eng && eng->update_func) 
02218       res = eng->update_func(db, table, keyfield, lookup, ap);
02219    va_end(ap);
02220 
02221    return res;
02222 }

void ast_variable_append ( struct ast_category category,
struct ast_variable variable 
)

Definition at line 343 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(), and vm_change_password().

00344 {
00345    if (!variable)
00346       return;
00347    if (category->last)
00348       category->last->next = variable;
00349    else
00350       category->root = variable;
00351    category->last = variable;
00352    while (category->last->next)
00353       category->last = category->last->next;
00354 }

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

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 389 of file config.c.

References ast_category_get(), ast_config::last_browse, ast_category::name, and ast_category::root.

Referenced by __ast_http_load(), __ast_http_post_load(), __init_manager(), action_getconfig(), action_getconfigjson(), adsi_load(), aji_load_config(), ast_readconfig(), ast_variable_retrieve(), build_device(), check_tx_freq(), collect_function_digits(), conf_exec(), config_module(), do_say(), do_scheduler(), find_conf(), gtalk_load_config(), handle_cli_dialplan_save(), iax_template_parse(), ind_load_module(), init_logger_chain(), jingle_load_config(), load_config(), load_module(), load_modules(), load_moh_classes(), load_odbc_config(), load_rpt_vars(), misdn_cfg_init(), node_lookup(), odbc_load_module(), osp_create_provider(), parse_config(), pbx_load_config(), read_agent_config(), read_config_maps(), reload(), reload_config(), reload_followme(), reload_queue_rules(), reload_queues(), run_startup_commands(), search_directory(), set_config(), setup_dahdi(), show_users_realtime(), sip_cli_notify(), sla_build_station(), sla_build_trunk(), smdi_load(), store_config(), and tds_load_module().

00390 {
00391    struct ast_category *cat = NULL;
00392 
00393    if (category && config->last_browse && (config->last_browse->name == category))
00394       cat = config->last_browse;
00395    else
00396       cat = ast_category_get(config, category);
00397 
00398    return (cat) ? cat->root : NULL;
00399 }

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

Definition at line 673 of file config.c.

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

Referenced by handle_updates().

00674 {
00675    struct ast_variable *cur, *prev=NULL, *curn;
00676    int res = -1;
00677    int lineno = 0;
00678 
00679    cur = category->root;
00680    while (cur) {
00681       if (cur->name == variable) {
00682          if (prev) {
00683             prev->next = cur->next;
00684             if (cur == category->last)
00685                category->last = prev;
00686          } else {
00687             category->root = cur->next;
00688             if (cur == category->last)
00689                category->last = NULL;
00690          }
00691          cur->next = NULL;
00692          ast_variables_destroy(cur);
00693          return 0;
00694       }
00695       prev = cur;
00696       cur = cur->next;
00697    }
00698 
00699    prev = NULL;
00700    cur = category->root;
00701    while (cur) {
00702       curn = cur->next;
00703       if ((!ast_strlen_zero(line) && lineno == atoi(line)) || (ast_strlen_zero(line) && !strcasecmp(cur->name, variable) && (ast_strlen_zero(match) || !strcasecmp(cur->value, match)))) {
00704          if (prev) {
00705             prev->next = cur->next;
00706             if (cur == category->last)
00707                category->last = prev;
00708          } else {
00709             category->root = cur->next;
00710             if (cur == category->last)
00711                category->last = NULL;
00712          }
00713          cur->next = NULL;
00714          ast_variables_destroy(cur);
00715          res = 0;
00716       } else
00717          prev = cur;
00718 
00719       cur = curn;
00720       lineno++;
00721    }
00722    return res;
00723 }

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

Definition at line 356 of file config.c.

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

Referenced by handle_updates().

00357 {
00358    struct ast_variable *cur = category->root;
00359    int lineno;
00360    int insertline;
00361 
00362    if (!variable || sscanf(line, "%30d", &insertline) != 1)
00363       return;
00364    if (!insertline) {
00365       variable->next = category->root;
00366       category->root = variable;
00367    } else {
00368       for (lineno = 1; lineno < insertline; lineno++) {
00369          cur = cur->next;
00370          if (!cur->next)
00371             break;
00372       }
00373       variable->next = cur->next;
00374       cur->next = variable;
00375    }
00376 }

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

Definition at line 218 of file config.c.

References __ast_calloc(), ast_calloc, ast_variable::file, ast_variable::name, ast_variable::stuff, and ast_variable::value.

Referenced by add_cfg_entry(), add_rt_cfg_entry(), add_rt_multi_cfg_entry(), add_var(), apply_outgoing(), ast_channeltype_list(), ast_variable_update(), astman_get_variables(), build_user(), check_access(), config_curl(), config_ldap(), config_odbc(), config_pgsql(), copy_vars(), create_vmaccount(), handle_updates(), handle_uri(), httpd_helper_thread(), iax_parse_ies(), ldap_table_config_add_attribute(), mkintf(), parkandannounce_exec(), parse_cookies(), process_dahdi(), 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(), transmit_notify_custom(), variable_clone(), and vm_change_password().

00220 {
00221    struct ast_variable *variable;
00222    int name_len = strlen(name) + 1; 
00223    int val_len = strlen(value) + 1; 
00224    int fn_len = strlen(filename) + 1;  
00225 
00226 #ifdef MALLOC_DEBUG
00227    if ((variable = __ast_calloc(1, name_len + val_len + fn_len + sizeof(*variable), file, lineno, func))) {
00228 #else
00229    if ((variable = ast_calloc(1, name_len + val_len + fn_len + sizeof(*variable)))) {
00230 #endif
00231       char *dst = variable->stuff;  /* writable space starts here */
00232       variable->name = strcpy(dst, name);
00233       dst += name_len;
00234       variable->value = strcpy(dst, value);
00235       dst += val_len;
00236       variable->file = strcpy(dst, filename);
00237    }
00238    return variable;
00239 }

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 411 of file config.c.

References ast_variable_browse(), ast_variable::name, ast_category::next, ast_variable::next, ast_category::root, ast_config::root, and ast_variable::value.

Referenced by __ast_rtp_reload(), __ast_udptl_reload(), __init_manager(), _dsp_init(), advanced_options(), aji_load_config(), ast_config_option(), build_extension(), config_function_read(), config_module(), directory_exec(), do_reload(), do_scheduler(), festival_exec(), find_queue_by_name_rt(), function_macro(), get_insecure_variable_from_config(), get_wait_interval(), gtalk_load_config(), iax_template_parse(), ind_load_module(), init_acf_query(), init_logger_chain(), jingle_load_config(), load_config(), load_config_meetme(), load_module(), load_modules(), load_rpt_vars(), 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(), read_agent_config(), realtime_directory(), reload_config(), reload_followme(), reload_queues(), retreive_memory(), retrieve_astcfgint(), rpt(), rpt_master(), rpt_tele_thread(), rpt_telemetry(), saynode(), search_directory(), set_config(), setup_dahdi(), sla_build_station(), sla_build_trunk(), sla_load_config(), tds_load_module(), telem_lookup(), update_realtime_members(), vm_change_password(), and vm_forwardoptions().

00412 {
00413    struct ast_variable *v;
00414 
00415    if (category) {
00416       for (v = ast_variable_browse(config, category); v; v = v->next) {
00417          if (!strcasecmp(variable, v->name))
00418             return v->value;
00419       }
00420    } else {
00421       struct ast_category *cat;
00422 
00423       for (cat = config->root; cat; cat = cat->next)
00424          for (v = cat->root; v; v = v->next)
00425             if (!strcasecmp(variable, v->name))
00426                return v->value;
00427    }
00428 
00429    return NULL;
00430 }

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 725 of file config.c.

References ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), ast_variable::blanklines, ast_variable::file, ast_category::last, ast_variable::lineno, ast_variable::name, ast_variable::next, ast_variable::object, ast_variable::precomments, ast_category::root, ast_variable::sameline, ast_variable::trailing, and ast_variable::value.

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

00727 {
00728    struct ast_variable *cur, *prev=NULL, *newer=NULL;
00729 
00730    for (cur = category->root; cur; prev = cur, cur = cur->next) {
00731       if (strcasecmp(cur->name, variable) ||
00732          (!ast_strlen_zero(match) && strcasecmp(cur->value, match)))
00733          continue;
00734 
00735       if (!(newer = ast_variable_new(variable, value, cur->file)))
00736          return -1;
00737    
00738       newer->next = cur->next;
00739       newer->object = cur->object || object;
00740 
00741       /* Preserve everything */
00742       newer->lineno = cur->lineno;
00743       newer->blanklines = cur->blanklines;
00744       newer->precomments = cur->precomments; cur->precomments = NULL;
00745       newer->sameline = cur->sameline; cur->sameline = NULL;
00746       newer->trailing = cur->trailing; cur->trailing = NULL;
00747 
00748       if (prev)
00749          prev->next = newer;
00750       else
00751          category->root = newer;
00752       if (category->last == cur)
00753          category->last = newer;
00754 
00755       cur->next = NULL;
00756       ast_variables_destroy(cur);
00757 
00758       return 0;
00759    }
00760 
00761    /* Could not find variable to update */
00762    return -1;
00763 }

void ast_variables_destroy ( struct ast_variable var  ) 

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

Definition at line 466 of file config.c.

References ast_category::ignored, ast_category::name, ast_category::next, and ast_config::root.

Referenced by ast_category_get(), and process_text_line().

00467 {
00468    struct ast_category *cat;
00469 
00470    /* try exact match first, then case-insensitive match */
00471    for (cat = config->root; cat; cat = cat->next) {
00472       if (cat->name == category_name && (ignored || !cat->ignored))
00473          return cat;
00474    }
00475 
00476    for (cat = config->root; cat; cat = cat->next) {
00477       if (!strcasecmp(cat->name, category_name) && (ignored || !cat->ignored))
00478          return cat;
00479    }
00480 
00481    return NULL;
00482 }

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

Definition at line 95 of file config.c.

References ast_str_append().

Referenced by config_text_file_load().

00096 {
00097    ast_str_append(cb, 0, "%s", str);
00098 }

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

Definition at line 100 of file config.c.

References ast_copy_string(), ast_str_append(), and s.

Referenced by config_text_file_load().

00101 {
00102    char *s = alloca(len + 1);
00103    ast_copy_string(s, str, len);
00104    ast_str_append(cb, 0, "%s", str);
00105 }

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

Definition at line 107 of file config.c.

References ast_str::used.

Referenced by config_text_file_load(), and process_text_line().

00108 { 
00109    if (cb)
00110       cb->used = 0;
00111    if (llb)
00112       llb->used = 0;
00113 }

static void clear_config_maps ( void   )  [static]

Definition at line 1830 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().

01831 {
01832    struct ast_config_map *map;
01833 
01834    ast_mutex_lock(&config_lock);
01835 
01836    while (config_maps) {
01837       map = config_maps;
01838       config_maps = config_maps->next;
01839       ast_free(map);
01840    }
01841       
01842    ast_mutex_unlock(&config_lock);
01843 }

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 860 of file config.c.

References ast_calloc, AST_LIST_HEAD_INIT, AST_LIST_INSERT_SORTALPHA, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ATTRIBUTE_EXEC, ATTRIBUTE_INCLUDE, 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().

00861 {
00862    struct cache_file_mtime *cfmtime;
00863    struct cache_file_include *cfinclude;
00864    struct stat statbuf = { 0, };
00865 
00866    /* Find our cached entry for this configuration file */
00867    AST_LIST_LOCK(&cfmtime_head);
00868    AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
00869       if (!strcmp(cfmtime->filename, configfile) && !strcmp(cfmtime->who_asked, who_asked))
00870          break;
00871    }
00872    if (!cfmtime) {
00873       cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(configfile) + 1 + strlen(who_asked) + 1);
00874       if (!cfmtime) {
00875          AST_LIST_UNLOCK(&cfmtime_head);
00876          return;
00877       }
00878       AST_LIST_HEAD_INIT(&cfmtime->includes);
00879       strcpy(cfmtime->filename, configfile);
00880       cfmtime->who_asked = cfmtime->filename + strlen(configfile) + 1;
00881       strcpy(cfmtime->who_asked, who_asked);
00882       /* Note that the file mtime is initialized to 0, i.e. 1970 */
00883       AST_LIST_INSERT_SORTALPHA(&cfmtime_head, cfmtime, list, filename);
00884    }
00885 
00886    if (!stat(configfile, &statbuf))
00887       cfmtime->mtime = 0;
00888    else
00889       cfmtime->mtime = statbuf.st_mtime;
00890 
00891    switch (attrtype) {
00892    case ATTRIBUTE_INCLUDE:
00893       AST_LIST_TRAVERSE(&cfmtime->includes, cfinclude, list) {
00894          if (!strcmp(cfinclude->include, filename)) {
00895             AST_LIST_UNLOCK(&cfmtime_head);
00896             return;
00897          }
00898       }
00899       cfinclude = ast_calloc(1, sizeof(*cfinclude) + strlen(filename) + 1);
00900       if (!cfinclude) {
00901          AST_LIST_UNLOCK(&cfmtime_head);
00902          return;
00903       }
00904       strcpy(cfinclude->include, filename);
00905       AST_LIST_INSERT_TAIL(&cfmtime->includes, cfinclude, list);
00906       break;
00907    case ATTRIBUTE_EXEC:
00908       cfmtime->has_exec = 1;
00909       break;
00910    }
00911    AST_LIST_UNLOCK(&cfmtime_head);
00912 }

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, read]

Growable string buffer

< this will be a comment collector.

< A buffer for stuff behind the ;

Definition at line 1170 of file config.c.

References ALLOC_COMMENT(), ast_calloc, ast_clear_flag, ast_config_AST_CONFIG_DIR, ast_config_get_current_category(), ast_copy_string(), ast_debug, ast_free, AST_LIST_HEAD_INIT, AST_LIST_INSERT_SORTALPHA, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_str_create(), ast_strip(), ast_strlen_zero(), ast_test_flag, ast_verb, buf, CB_ADD(), CB_ADD_LEN(), CB_RESET(), CB_SIZE, COMMENT_META, COMMENT_TAG, CONFIG_FLAG_FILEUNCHANGED, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEUNCHANGED, errno, f, cache_file_mtime::filename, cache_file_mtime::has_exec, cache_file_include::include, ast_config::include_level, cache_file_mtime::includes, LOG_ERROR, LOG_WARNING, MAX_NESTED_COMMENTS, cache_file_mtime::mtime, MY_GLOB_FLAGS, process_text_line(), ast_str::str, ast_variable::trailing, ast_category::trailing, ast_str::used, and cache_file_mtime::who_asked.

01171 {
01172    char fn[256];
01173 #if defined(LOW_MEMORY)
01174    char buf[512];
01175 #else
01176    char buf[8192];
01177 #endif
01178    char *new_buf, *comment_p, *process_buf;
01179    FILE *f;
01180    int lineno=0;
01181    int comment = 0, nest[MAX_NESTED_COMMENTS];
01182    struct ast_category *cat = NULL;
01183    int count = 0;
01184    struct stat statbuf;
01185    struct cache_file_mtime *cfmtime = NULL;
01186    struct cache_file_include *cfinclude;
01187    struct ast_variable *last_var = 0;
01188    struct ast_category *last_cat = 0;
01189    /*! Growable string buffer */
01190    struct ast_str *comment_buffer = NULL; /*!< this will be a comment collector.*/
01191    struct ast_str *lline_buffer = NULL;   /*!< A buffer for stuff behind the ; */
01192 
01193    if (cfg)
01194       cat = ast_config_get_current_category(cfg);
01195 
01196    if (filename[0] == '/') {
01197       ast_copy_string(fn, filename, sizeof(fn));
01198    } else {
01199       snprintf(fn, sizeof(fn), "%s/%s", ast_config_AST_CONFIG_DIR, filename);
01200    }
01201 
01202    if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
01203       comment_buffer = ast_str_create(CB_SIZE);
01204       if (comment_buffer)
01205          lline_buffer = ast_str_create(CB_SIZE);
01206       if (!lline_buffer) {
01207          if (comment_buffer)
01208             ast_free(comment_buffer);
01209          ast_log(LOG_ERROR, "Failed to initialize the comment buffer!\n");
01210          return NULL;
01211       }
01212    }
01213 #ifdef AST_INCLUDE_GLOB
01214    {
01215       int glob_ret;
01216       glob_t globbuf;
01217       globbuf.gl_offs = 0; /* initialize it to silence gcc */
01218       glob_ret = glob(fn, MY_GLOB_FLAGS, NULL, &globbuf);
01219       if (glob_ret == GLOB_NOSPACE)
01220          ast_log(LOG_WARNING,
01221             "Glob Expansion of pattern '%s' failed: Not enough memory\n", fn);
01222       else if (glob_ret  == GLOB_ABORTED)
01223          ast_log(LOG_WARNING,
01224             "Glob Expansion of pattern '%s' failed: Read error\n", fn);
01225       else  {
01226          /* loop over expanded files */
01227          int i;
01228          for (i=0; i<globbuf.gl_pathc; i++) {
01229             ast_copy_string(fn, globbuf.gl_pathv[i], sizeof(fn));
01230 #endif
01231    /*
01232     * The following is not a loop, but just a convenient way to define a block
01233     * (using do { } while(0) ), and be able to exit from it with 'continue'
01234     * or 'break' in case of errors. Nice trick.
01235     */
01236    do {
01237       if (stat(fn, &statbuf))
01238          continue;
01239 
01240       if (!S_ISREG(statbuf.st_mode)) {
01241          ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn);
01242          continue;
01243       }
01244 
01245       if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) {
01246          /* Find our cached entry for this configuration file */
01247          AST_LIST_LOCK(&cfmtime_head);
01248          AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
01249             if (!strcmp(cfmtime->filename, fn) && !strcmp(cfmtime->who_asked, who_asked))
01250                break;
01251          }
01252          if (!cfmtime) {
01253             cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(fn) + 1 + strlen(who_asked) + 1);
01254             if (!cfmtime)
01255                continue;
01256             AST_LIST_HEAD_INIT(&cfmtime->includes);
01257             strcpy(cfmtime->filename, fn);
01258             cfmtime->who_asked = cfmtime->filename + strlen(fn) + 1;
01259             strcpy(cfmtime->who_asked, who_asked);
01260             /* Note that the file mtime is initialized to 0, i.e. 1970 */
01261             AST_LIST_INSERT_SORTALPHA(&cfmtime_head, cfmtime, list, filename);
01262          }
01263       }
01264 
01265       if (cfmtime && (!cfmtime->has_exec) && (cfmtime->mtime == statbuf.st_mtime) && ast_test_flag(&flags, CONFIG_FLAG_FILEUNCHANGED)) {
01266          /* File is unchanged, what about the (cached) includes (if any)? */
01267          int unchanged = 1;
01268          AST_LIST_TRAVERSE(&cfmtime->includes, cfinclude, list) {
01269             /* We must glob here, because if we did not, then adding a file to globbed directory would
01270              * incorrectly cause no reload to be necessary. */
01271             char fn2[256];
01272 #ifdef AST_INCLUDE_GLOB
01273             int glob_return;
01274             glob_t glob_buf = { .gl_offs = 0 };
01275             glob_return = glob(cfinclude->include, MY_GLOB_FLAGS, NULL, &glob_buf);
01276             /* On error, we reparse */
01277             if (glob_return == GLOB_NOSPACE || glob_return  == GLOB_ABORTED)
01278                unchanged = 0;
01279             else  {
01280                /* loop over expanded files */
01281                int j;
01282                for (j = 0; j < glob_buf.gl_pathc; j++) {
01283                   ast_copy_string(fn2, glob_buf.gl_pathv[j], sizeof(fn2));
01284 #else
01285                   ast_copy_string(fn2, cfinclude->include);
01286 #endif
01287                   if (config_text_file_load(NULL, NULL, fn2, NULL, flags, "", who_asked) == NULL) {
01288                      /* that second-to-last field needs to be looked at in this case... TODO */
01289                      unchanged = 0;
01290                      /* One change is enough to short-circuit and reload the whole shebang */
01291                      break;
01292                   }
01293 #ifdef AST_INCLUDE_GLOB
01294                }
01295             }
01296 #endif
01297          }
01298 
01299          if (unchanged) {
01300             AST_LIST_UNLOCK(&cfmtime_head);
01301             return CONFIG_STATUS_FILEUNCHANGED;
01302          }
01303       }
01304       if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
01305          AST_LIST_UNLOCK(&cfmtime_head);
01306 
01307       /* If cfg is NULL, then we just want an answer */
01308       if (cfg == NULL)
01309          return NULL;
01310 
01311       if (cfmtime)
01312          cfmtime->mtime = statbuf.st_mtime;
01313 
01314       ast_verb(2, "Parsing '%s': ", fn);
01315          fflush(stdout);
01316       if (!(f = fopen(fn, "r"))) {
01317          ast_debug(1, "No file to parse: %s\n", fn);
01318          ast_verb(2, "Not found (%s)\n", strerror(errno));
01319          continue;
01320       }
01321       count++;
01322       /* If we get to this point, then we're loading regardless */
01323       ast_clear_flag(&flags, CONFIG_FLAG_FILEUNCHANGED);
01324       ast_debug(1, "Parsing %s\n", fn);
01325       ast_verb(2, "Found\n");
01326       while (!feof(f)) {
01327          lineno++;
01328          if (fgets(buf, sizeof(buf), f)) {
01329             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && lline_buffer && lline_buffer->used) {
01330                CB_ADD(&comment_buffer, lline_buffer->str);       /* add the current lline buffer to the comment buffer */
01331                lline_buffer->used = 0;        /* erase the lline buffer */
01332             }
01333             
01334             new_buf = buf;
01335             if (comment) 
01336                process_buf = NULL;
01337             else
01338                process_buf = buf;
01339             
01340             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used && (ast_strlen_zero(buf) || strlen(buf) == strspn(buf," \t\n\r"))) {
01341                /* blank line? really? Can we add it to an existing comment and maybe preserve inter- and post- comment spacing? */
01342                CB_ADD(&comment_buffer, "\n");       /* add a newline to the comment buffer */
01343                continue; /* go get a new line, then */
01344             }
01345             
01346             while ((comment_p = strchr(new_buf, COMMENT_META))) {
01347                if ((comment_p > new_buf) && (*(comment_p-1) == '\\')) {
01348                   /* Escaped semicolons aren't comments. */
01349                   new_buf = comment_p + 1;
01350                } else if (comment_p[1] == COMMENT_TAG && comment_p[2] == COMMENT_TAG && (comment_p[3] != '-')) {
01351                   /* Meta-Comment start detected ";--" */
01352                   if (comment < MAX_NESTED_COMMENTS) {
01353                      *comment_p = '\0';
01354                      new_buf = comment_p + 3;
01355                      comment++;
01356                      nest[comment-1] = lineno;
01357                   } else {
01358                      ast_log(LOG_ERROR, "Maximum nest limit of %d reached.\n", MAX_NESTED_COMMENTS);
01359                   }
01360                } else if ((comment_p >= new_buf + 2) &&
01361                      (*(comment_p - 1) == COMMENT_TAG) &&
01362                      (*(comment_p - 2) == COMMENT_TAG)) {
01363                   /* Meta-Comment end detected */
01364                   comment--;
01365                   new_buf = comment_p + 1;
01366                   if (!comment) {
01367                      /* Back to non-comment now */
01368                      if (process_buf) {
01369                         /* Actually have to move what's left over the top, then continue */
01370                         char *oldptr;
01371                         oldptr = process_buf + strlen(process_buf);
01372                         if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
01373                            CB_ADD(&comment_buffer, ";");
01374                            CB_ADD_LEN(&comment_buffer, oldptr+1, new_buf-oldptr-1);
01375                         }
01376                         
01377                         memmove(oldptr, new_buf, strlen(new_buf) + 1);
01378                         new_buf = oldptr;
01379                      } else
01380                         process_buf = new_buf;
01381                   }
01382                } else {
01383                   if (!comment) {
01384                      /* If ; is found, and we are not nested in a comment, 
01385                         we immediately stop all comment processing */
01386                      if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
01387                         CB_ADD(&lline_buffer, comment_p);
01388                      }
01389                      *comment_p = '\0'; 
01390                      new_buf = comment_p;
01391                   } else
01392                      new_buf = comment_p + 1;
01393                }
01394             }
01395             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment && !process_buf ) {
01396                CB_ADD(&comment_buffer, buf);  /* the whole line is a comment, store it */
01397             }
01398             
01399             if (process_buf) {
01400                char *buffer = ast_strip(process_buf);
01401                if (!ast_strlen_zero(buffer)) {
01402                   if (process_text_line(cfg, &cat, buffer, lineno, fn, flags, comment_buffer, lline_buffer, suggested_include_file, &last_cat, &last_var, who_asked)) {
01403                      cfg = NULL;
01404                      break;
01405                   }
01406                }
01407             }
01408          }
01409       }
01410       /* end of file-- anything in a comment buffer? */
01411       if (last_cat) {
01412          if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used ) {
01413             if (lline_buffer && lline_buffer->used) {
01414                CB_ADD(&comment_buffer, lline_buffer->str);       /* add the current lline buffer to the comment buffer */
01415                lline_buffer->used = 0;        /* erase the lline buffer */
01416             }
01417             last_cat->trailing = ALLOC_COMMENT(comment_buffer);
01418          }
01419       } else if (last_var) {
01420          if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used ) {
01421             if (lline_buffer && lline_buffer->used) {
01422                CB_ADD(&comment_buffer, lline_buffer->str);       /* add the current lline buffer to the comment buffer */
01423                lline_buffer->used = 0;        /* erase the lline buffer */
01424             }
01425             last_var->trailing = ALLOC_COMMENT(comment_buffer);
01426          }
01427       } else {
01428          if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer && comment_buffer->used) {
01429             ast_debug(1, "Nothing to attach comments to, discarded: %s\n", comment_buffer->str);
01430          }
01431       }
01432       if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01433          CB_RESET(comment_buffer, lline_buffer);
01434 
01435       fclose(f);     
01436    } while (0);
01437    if (comment) {
01438       ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment - 1]);
01439    }
01440 #ifdef AST_INCLUDE_GLOB
01441                if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED)
01442                   break;
01443             }
01444             globfree(&globbuf);
01445          }
01446       }
01447 #endif
01448 
01449    if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg->include_level == 1 && ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
01450       if (comment_buffer)
01451          ast_free(comment_buffer);
01452       if (lline_buffer)
01453          ast_free(lline_buffer);
01454       comment_buffer = NULL;
01455       lline_buffer = NULL;
01456    }
01457    
01458    if (count == 0)
01459       return NULL;
01460 
01461    return cfg;
01462 }

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

Definition at line 1590 of file config.c.

References ao2_container_alloc, ao2_ref, ast_debug, AST_LIST_EMPTY, AST_LIST_LAST, AST_LIST_TRAVERSE, ast_verb, ast_variable::blanklines, ast_comment::cmt, errno, ast_config_include::exec, ast_config_include::exec_file, f, ast_variable::file, 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_variable::lineno, ast_category::lineno, ast_variable::name, ast_category_template_instance::name, ast_category::name, ast_category::next, ast_variable::next, ast_comment::next, ast_config_include::next, ast_variable::object, option_debug, ast_config_include::output, ast_variable::precomments, ast_category::precomments, ast_category::root, ast_config::root, ast_variable::sameline, ast_category::sameline, set_fn(), ast_category::template_instances, ast_variable::trailing, ast_category::trailing, ast_variable::value, and var.

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

01591 {
01592    FILE *f;
01593    char fn[256];
01594    struct ast_variable *var;
01595    struct ast_category *cat;
01596    struct ast_comment *cmt;
01597    struct ast_config_include *incl;
01598    int blanklines = 0;
01599    struct ao2_container *fileset = ao2_container_alloc(180000, hash_string, hashtab_compare_strings);
01600    struct inclfile *fi = 0;
01601 
01602    /* reset all the output flags, in case this isn't our first time saving this data */
01603 
01604    for (incl=cfg->includes; incl; incl = incl->next)
01605       incl->output = 0;
01606 
01607    /* go thru all the inclusions and make sure all the files involved (configfile plus all its inclusions)
01608       are all truncated to zero bytes and have that nice header*/
01609 
01610    for (incl=cfg->includes; incl; incl = incl->next)
01611    {
01612       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*/
01613          FILE *f1;
01614 
01615          set_fn(fn, sizeof(fn), incl->included_file, configfile, fileset, &fi); /* normally, fn is just set to incl->included_file, prepended with config dir if relative */
01616          f1 = fopen(fn,"w");
01617          if (f1) {
01618             gen_header(f1, configfile, fn, generator);
01619             fclose(f1); /* this should zero out the file */
01620          } else {
01621             ast_debug(1, "Unable to open for writing: %s\n", fn);
01622             ast_verb(2, "Unable to write %s (%s)", fn, strerror(errno));
01623          }
01624          ao2_ref(fi,-1); /* we are giving up this reference to the object ptd to by fi */
01625          fi = 0;
01626       }
01627    }
01628 
01629    set_fn(fn, sizeof(fn), 0, configfile, fileset, &fi); /* just set fn to absolute ver of configfile */
01630 #ifdef __CYGWIN__ 
01631    if ((f = fopen(fn, "w+"))) {
01632 #else
01633    if ((f = fopen(fn, "w"))) {
01634 #endif       
01635       ast_verb(2, "Saving '%s': ", fn);
01636       gen_header(f, configfile, fn, generator);
01637       cat = cfg->root;
01638       fclose(f);
01639       ao2_ref(fi,-1); /* we are giving up this reference to the object ptd to by fi */
01640       
01641       /* from here out, we open each involved file and concat the stuff we need to add to the end and immediately close... */
01642       /* since each var, cat, and associated comments can come from any file, we have to be 
01643          mobile, and open each file, print, and close it on an entry-by-entry basis */
01644 
01645       while (cat) {
01646          set_fn(fn, sizeof(fn), cat->file, configfile, fileset, &fi);
01647          f = fopen(fn, "a");
01648          if (!f)
01649          {
01650             ast_debug(1, "Unable to open for writing: %s\n", fn);
01651             ast_verb(2, "Unable to write %s (%s)", fn, strerror(errno));
01652             ao2_ref(fileset, -1);
01653             return -1;
01654          }
01655 
01656          /* dump any includes that happen before this category header */
01657          for (incl=cfg->includes; incl; incl = incl->next) {
01658             if (strcmp(incl->include_location_file, cat->file) == 0){
01659                if (cat->lineno > incl->include_location_lineno && !incl->output) {
01660                   if (incl->exec)
01661                      fprintf(f,"#exec \"%s\"\n", incl->exec_file);
01662                   else
01663                      fprintf(f,"#include \"%s\"\n", incl->included_file);
01664                   incl->output = 1;
01665                }
01666             }
01667          }
01668 
01669          insert_leading_blank_lines(f, fi, cat->precomments, cat->lineno);
01670          /* Dump section with any appropriate comment */
01671          for (cmt = cat->precomments; cmt; cmt=cmt->next) {
01672             char *cmtp = cmt->cmt;
01673             while (*cmtp == ';' && *(cmtp+1) == '!') {
01674                char *cmtp2 = strchr(cmtp+1, '\n');
01675                if (cmtp2)
01676                   cmtp = cmtp2+1;
01677                else cmtp = 0;
01678             }
01679             if (cmtp)
01680                fprintf(f,"%s", cmtp);
01681          }
01682          fprintf(f, "[%s]", cat->name);
01683          if (cat->ignored || !AST_LIST_EMPTY(&cat->template_instances)) {
01684             fprintf(f, "(");
01685             if (cat->ignored) {
01686                fprintf(f, "!");
01687             }
01688             if (cat->ignored && !AST_LIST_EMPTY(&cat->template_instances)) {
01689                fprintf(f, ",");
01690             }
01691             if (!AST_LIST_EMPTY(&cat->template_instances)) {
01692                struct ast_category_template_instance *x;
01693                AST_LIST_TRAVERSE(&cat->template_instances, x, next) {
01694                   fprintf(f,"%s",x->name);
01695                   if (x != AST_LIST_LAST(&cat->template_instances))
01696                      fprintf(f,",");
01697                }
01698             }
01699             fprintf(f, ")");
01700          }
01701          for(cmt = cat->sameline; cmt; cmt=cmt->next)
01702          {
01703             fprintf(f,"%s", cmt->cmt);
01704          }
01705          if (!cat->sameline)
01706             fprintf(f,"\n");
01707          for (cmt = cat->trailing; cmt; cmt=cmt->next) {
01708             if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
01709                fprintf(f,"%s", cmt->cmt);
01710          }
01711          fclose(f);
01712          ao2_ref(fi,-1); /* we are giving up this reference to the object ptd to by fi */
01713          fi = 0;
01714          
01715          var = cat->root;
01716          while (var) {
01717             struct ast_category_template_instance *x;
01718             int found = 0;
01719             AST_LIST_TRAVERSE(&cat->template_instances, x, next) {
01720                struct ast_variable *v;
01721                for (v = x->inst->root; v; v = v->next) {
01722                   if (!strcasecmp(var->name, v->name) && !strcmp(var->value, v->value)) {
01723                      found = 1;
01724                      break;
01725                   }
01726                }
01727                if (found)
01728                   break;
01729             }
01730             if (found) {
01731                var = var->next;
01732                continue;
01733             }
01734             set_fn(fn, sizeof(fn), var->file, configfile, fileset, &fi);
01735             f = fopen(fn, "a");
01736             if (!f)
01737             {
01738                ast_debug(1, "Unable to open for writing: %s\n", fn);
01739                ast_verb(2, "Unable to write %s (%s)", fn, strerror(errno));
01740                ao2_ref(fi,-1); /* we are giving up this reference to the object ptd to by fi */
01741                fi = 0;
01742                ao2_ref(fileset, -1);
01743                return -1;
01744             }
01745             
01746             /* dump any includes that happen before this category header */
01747             for (incl=cfg->includes; incl; incl = incl->next) {
01748                if (strcmp(incl->include_location_file, var->file) == 0){
01749                   if (var->lineno > incl->include_location_lineno && !incl->output) {
01750                      if (incl->exec)
01751                         fprintf(f,"#exec \"%s\"\n", incl->exec_file);
01752                      else
01753                         fprintf(f,"#include \"%s\"\n", incl->included_file);
01754                      incl->output = 1;
01755                   }
01756                }
01757             }
01758             
01759             insert_leading_blank_lines(f, fi, var->precomments, var->lineno);
01760             for (cmt = var->precomments; cmt; cmt=cmt->next) {
01761                if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
01762                   fprintf(f,"%s", cmt->cmt);
01763             }
01764             if (var->sameline) 
01765                fprintf(f, "%s %s %s  %s", var->name, (var->object ? "=>" : "="), var->value, var->sameline->cmt);
01766             else  
01767                fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value);
01768             for (cmt = var->trailing; cmt; cmt=cmt->next) {
01769                if (cmt->cmt[0] != ';' || cmt->cmt[1] != '!')
01770                   fprintf(f,"%s", cmt->cmt);
01771             }
01772             if (var->blanklines) {
01773                blanklines = var->blanklines;
01774                while (blanklines--)
01775                   fprintf(f, "\n");
01776             }
01777             
01778             fclose(f);
01779             ao2_ref(fi,-1); /* we are giving up this reference to the object ptd to by fi */
01780             fi = 0;
01781             
01782             var = var->next;
01783          }
01784          cat = cat->next;
01785       }
01786       if (!option_debug)
01787          ast_verb(2, "Saved\n");
01788    } else {
01789       ast_debug(1, "Unable to open for writing: %s\n", fn);
01790       ast_verb(2, "Unable to write (%s)", strerror(errno));
01791       ao2_ref(fi,-1); /* we are giving up this reference to the object ptd to by fi */
01792       ao2_ref(fileset, -1);
01793       return -1;
01794    }
01795 
01796    /* Now, for files with trailing #include/#exec statements,
01797       we have to make sure every entry is output */
01798 
01799    for (incl=cfg->includes; incl; incl = incl->next) {
01800       if (!incl->output) {
01801          /* open the respective file */
01802          set_fn(fn, sizeof(fn), incl->include_location_file, configfile, fileset, &fi);
01803          f = fopen(fn, "a");
01804          if (!f)
01805          {
01806             ast_debug(1, "Unable to open for writing: %s\n", fn);
01807             ast_verb(2, "Unable to write %s (%s)", fn, strerror(errno));
01808             ao2_ref(fi,-1); /* we are giving up this reference to the object ptd to by fi */
01809             fi = 0;
01810             ao2_ref(fileset, -1);
01811             return -1;
01812          }
01813          
01814          /* output the respective include */
01815          if (incl->exec)
01816             fprintf(f,"#exec \"%s\"\n", incl->exec_file);
01817          else
01818             fprintf(f,"#include \"%s\"\n", incl->included_file);
01819          fclose(f);
01820          incl->output = 1;
01821          ao2_ref(fi,-1); /* we are giving up this reference to the object ptd to by fi */
01822          fi = 0;
01823       }
01824    }
01825    ao2_ref(fileset, -1); /* this should destroy the hash container */
01826             
01827    return 0;
01828 }

static int count_linefeeds ( char *  str  )  [static]

Definition at line 1538 of file config.c.

Referenced by count_linefeeds_in_comments().

01539 {
01540    int count = 0;
01541 
01542    while (*str) {
01543       if (*str =='\n')
01544          count++;
01545       str++;
01546    }
01547    return count;
01548 }

static int count_linefeeds_in_comments ( struct ast_comment x  )  [static]

Definition at line 1550 of file config.c.

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

Referenced by insert_leading_blank_lines().

01551 {
01552    int count = 0;
01553 
01554    while (x) {
01555       count += count_linefeeds(x->cmt);
01556       x = x->next;
01557    }
01558    return count;
01559 }

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

Find realtime engine for realtime family.

Definition at line 1991 of file config.c.

References ast_copy_string(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), config_lock, config_maps, ast_config_map::database, ast_config_map::driver, LOG_WARNING, map, ast_config_map::name, ast_config_engine::next, ast_config_map::next, and ast_config_map::table.

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(), and ast_update_realtime().

01992 {
01993    struct ast_config_engine *eng, *ret = NULL;
01994    struct ast_config_map *map;
01995 
01996    ast_mutex_lock(&config_lock);
01997 
01998    for (map = config_maps; map; map = map->next) {
01999       if (!strcasecmp(family, map->name)) {
02000          if (database)
02001             ast_copy_string(database, map->database, dbsiz);
02002          if (table)
02003             ast_copy_string(table, map->table ? map->table : family, tabsiz);
02004          break;
02005       }
02006    }
02007 
02008    /* Check if the required driver (engine) exist */
02009    if (map) {
02010       for (eng = config_engine_list; !ret && eng; eng = eng->next) {
02011          if (!strcasecmp(eng->name, map->driver))
02012             ret = eng;
02013       }
02014    }
02015 
02016    ast_mutex_unlock(&config_lock);
02017    
02018    /* if we found a mapping, but the engine is not available, then issue a warning */
02019    if (map && !ret)
02020       ast_log(LOG_WARNING, "Realtime mapping for '%s' found to engine '%s', but the engine is not available\n", map->name, map->driver);
02021 
02022    return ret;
02023 }

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

Definition at line 1485 of file config.c.

References ast_copy_string().

Referenced by config_text_file_save().

01486 {
01487    char date[256]="";
01488    time_t t;
01489 
01490    time(&t);
01491    ast_copy_string(date, ctime(&t), sizeof(date));
01492 
01493    fprintf(f1, ";!\n");
01494    fprintf(f1, ";! Automatically generated configuration file\n");
01495    if (strcmp(configfile, fn))
01496       fprintf(f1, ";! Filename: %s (%s)\n", configfile, fn);
01497    else
01498       fprintf(f1, ";! Filename: %s\n", configfile);
01499    fprintf(f1, ";! Generator: %s\n", generator);
01500    fprintf(f1, ";! Creation Date: %s", date);
01501    fprintf(f1, ";!\n");
01502 }

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

Definition at line 2503 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, S_OR, ast_cli_entry::usage, and cache_file_mtime::who_asked.

02504 {
02505    struct cache_file_mtime *cfmtime;
02506 
02507    switch (cmd) {
02508    case CLI_INIT:
02509       e->command = "config list";
02510       e->usage =
02511          "Usage: config list\n"
02512          "   Show all modules that have loaded a configuration file\n";
02513       return NULL;
02514    case CLI_GENERATE:
02515       return NULL;
02516    }
02517 
02518    AST_LIST_LOCK(&cfmtime_head);
02519    AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
02520       ast_cli(a->fd, "%-20.20s %-50s\n", S_OR(cfmtime->who_asked, "core"), cfmtime->filename);
02521    }
02522    AST_LIST_UNLOCK(&cfmtime_head);
02523 
02524    return CLI_SUCCESS;
02525 }

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

Definition at line 2441 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(), buf, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, cache_file_mtime::filename, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, cache_file_mtime::who_asked, and ast_cli_args::word.

02442 {
02443    struct cache_file_mtime *cfmtime;
02444    char *prev = "", *completion_value = NULL;
02445    int wordlen, which = 0;
02446 
02447    switch (cmd) {
02448    case CLI_INIT:
02449       e->command = "config reload";
02450       e->usage =
02451          "Usage: config reload <filename.conf>\n"
02452          "   Reloads all modules that reference <filename.conf>\n";
02453       return NULL;
02454    case CLI_GENERATE:
02455       if (a->pos > 2) {
02456          return NULL;
02457       }
02458 
02459       wordlen = strlen(a->word);
02460 
02461       AST_LIST_LOCK(&cfmtime_head);
02462       AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
02463          /* Skip duplicates - this only works because the list is sorted by filename */
02464          if (strcmp(cfmtime->filename, prev) == 0) {
02465             continue;
02466          }
02467 
02468          /* Core configs cannot be reloaded */
02469          if (ast_strlen_zero(cfmtime->who_asked)) {
02470             continue;
02471          }
02472 
02473          if (++which > a->n && strncmp(cfmtime->filename, a->word, wordlen) == 0) {
02474             completion_value = ast_strdup(cfmtime->filename);
02475             break;
02476          }
02477 
02478          /* Otherwise save that we've seen this filename */
02479          prev = cfmtime->filename;
02480       }
02481       AST_LIST_UNLOCK(&cfmtime_head);
02482 
02483       return completion_value;
02484    }
02485 
02486    if (a->argc != 3) {
02487       return CLI_SHOWUSAGE;
02488    }
02489 
02490    AST_LIST_LOCK(&cfmtime_head);
02491    AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
02492       if (!strcmp(cfmtime->filename, a->argv[2])) {
02493          char *buf = alloca(strlen("module reload ") + strlen(cfmtime->who_asked) + 1);
02494          sprintf(buf, "module reload %s", cfmtime->who_asked);
02495          ast_cli_command(a->fd, buf);
02496       }
02497    }
02498    AST_LIST_UNLOCK(&cfmtime_head);
02499 
02500    return CLI_SUCCESS;
02501 }

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

Definition at line 2402 of file config.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, config_lock, config_maps, ast_config_map::database, ast_config_map::driver, ast_cli_args::fd, map, ast_config_map::name, ast_config_engine::name, ast_config_map::next, ast_config_engine::next, ast_config_map::table, and ast_cli_entry::usage.

02403 {
02404    struct ast_config_engine *eng;
02405    struct ast_config_map *map;
02406 
02407    switch (cmd) {
02408    case CLI_INIT:
02409       e->command = "core show config mappings";
02410       e->usage =
02411          "Usage: core show config mappings\n"
02412          "  Shows the filenames to config engines.\n";
02413       return NULL;
02414    case CLI_GENERATE:
02415       return NULL;
02416    }
02417    
02418    ast_mutex_lock(&config_lock);
02419 
02420    if (!config_engine_list) {
02421       ast_cli(a->fd, "No config mappings found.\n");
02422    } else {
02423       ast_cli(a->fd, "\n\n");
02424       for (eng = config_engine_list; eng; eng = eng->next) {
02425          ast_cli(a->fd, "\nConfig Engine: %s\n", eng->name);
02426          for (map = config_maps; map; map = map->next) {
02427             if (!strcasecmp(map->driver, eng->name)) {
02428                ast_cli(a->fd, "===> %s (db=%s, table=%s)\n", map->name, map->database,
02429                      map->table ? map->table : map->name);
02430             }
02431          }
02432       }
02433       ast_cli(a->fd,"\n\n");
02434    }
02435    
02436    ast_mutex_unlock(&config_lock);
02437 
02438    return CLI_SUCCESS;
02439 }

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

Definition at line 133 of file config.c.

References str, and total.

Referenced by config_text_file_save().

00134 {
00135    char *str = ((struct inclfile*)obj)->fname;
00136    int total;
00137 
00138    for (total=0; *str; str++) {
00139       unsigned int tmp = total;
00140       total <<= 1; /* multiply by 2 */
00141       total += tmp; /* multiply by 3 */
00142       total <<= 2; /* multiply by 12 */
00143       total += tmp; /* multiply by 13 */
00144 
00145       total += ((unsigned int)(*str));
00146    }
00147    if (total < 0)
00148       total = -total;
00149    return total;
00150 }

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

Definition at line 152 of file config.c.

References CMP_MATCH, CMP_STOP, and inclfile::fname.

Referenced by config_text_file_save().

00153 {
00154    const struct inclfile *ae = a, *be = b;
00155    return !strcmp(ae->fname, be->fname) ? CMP_MATCH | CMP_STOP : 0;
00156 }

static void inclfile_destroy ( void *  obj  )  [static]

Definition at line 1504 of file config.c.

References inclfile::fname, and free.

Referenced by set_fn().

01505 {
01506    const struct inclfile *o = obj;
01507 
01508    if (o->fname)
01509       free(o->fname);
01510 }

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

Definition at line 652 of file config.c.

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

Referenced by process_text_line().

00653 {
00654    struct ast_variable *var;
00655    struct ast_category_template_instance *x = ast_calloc(1,sizeof(struct ast_category_template_instance));
00656 
00657    strcpy(x->name, base->name);
00658    x->inst = base;
00659    AST_LIST_INSERT_TAIL(&new->template_instances, x, next);
00660    for (var = base->root; var; var = var->next)
00661       ast_variable_append(new, variable_clone(var));
00662 }

static int init_appendbuf ( void *  data  )  [static]

Definition at line 83 of file config.c.

References ast_str_create(), and str.

00084 {
00085    struct ast_str **str = data;
00086    *str = ast_str_create(16);
00087    return *str ? 0 : -1;
00088 }

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

Definition at line 1561 of file config.c.

References count_linefeeds_in_comments(), and inclfile::lineno.

Referenced by config_text_file_save().

01562 {
01563    int precomment_lines = count_linefeeds_in_comments(precomments);
01564    int i;
01565 
01566    /* I don't have to worry about those ;! comments, they are
01567       stored in the precomments, but not printed back out.
01568       I did have to make sure that comments following
01569       the ;! header comments were not also deleted in the process */
01570    if (lineno - precomment_lines - fi->lineno < 0) { /* insertions can mess up the line numbering and produce negative numbers that mess things up */
01571       return;
01572    } else if (lineno == 0) {
01573       /* Line replacements also mess things up */
01574       return;
01575    } else if (lineno - precomment_lines - fi->lineno < 5) {
01576       /* Only insert less than 5 blank lines; if anything more occurs,
01577        * it's probably due to context deletion. */
01578       for (i = fi->lineno; i < lineno - precomment_lines; i++) {
01579          fprintf(fp, "\n");
01580       }
01581    } else {
01582       /* Deletion occurred - insert a single blank line, for separation of
01583        * contexts. */
01584       fprintf(fp, "\n");
01585    }
01586  
01587    fi->lineno = lineno + 1; /* Advance the file lineno */
01588 }

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

Definition at line 446 of file config.c.

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

Referenced by process_text_line().

00447 {
00448    struct ast_variable *var = old->root;
00449 
00450    old->root = NULL;
00451    /* we can just move the entire list in a single op */
00452    ast_variable_append(new, var);
00453 }

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

Definition at line 582 of file config.c.

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

Referenced by ast_category_browse().

00583 {
00584    for (; cat && cat->ignored; cat = cat->next);
00585 
00586    return cat;
00587 }

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 921 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_set(), 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::name, ast_variable::next, ast_variable::object, ast_variable::precomments, ast_category::precomments, S_OR, ast_variable::sameline, ast_category::sameline, str, strsep(), ast_variable::value, and var.

Referenced by config_text_file_load().

00927 {
00928    char *c;
00929    char *cur = buf;
00930    struct ast_variable *v;
00931    char cmd[512], exec_file[512];
00932 
00933    /* Actually parse the entry */
00934    if (cur[0] == '[') { /* A category header */
00935       /* format is one of the following:
00936        * [foo] define a new category named 'foo'
00937        * [foo](!) define a new template category named 'foo'
00938        * [foo](+) append to category 'foo', error if foo does not exist.
00939        * [foo](a) define a new category and inherit from template a.
00940        *    You can put a comma-separated list of templates and '!' and '+'
00941        *    between parentheses, with obvious meaning.
00942        */
00943       struct ast_category *newcat = NULL;
00944       char *catname;
00945 
00946       c = strchr(cur, ']');
00947       if (!c) {
00948          ast_log(LOG_WARNING, "parse error: no closing ']', line %d of %s\n", lineno, configfile);
00949          return -1;
00950       }
00951       *c++ = '\0';
00952       cur++;
00953       if (*c++ != '(')
00954          c = NULL;
00955       catname = cur;
00956       if (!(*cat = newcat = ast_category_new(catname,
00957             S_OR(suggested_include_file, cfg->include_level == 1 ? "" : configfile),
00958             lineno))) {
00959          return -1;
00960       }
00961       (*cat)->lineno = lineno;
00962       *last_var = 0;
00963       *last_cat = newcat;
00964       
00965       /* add comments */
00966       if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
00967          newcat->precomments = ALLOC_COMMENT(comment_buffer);
00968       if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
00969          newcat->sameline = ALLOC_COMMENT(lline_buffer);
00970       if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
00971          CB_RESET(comment_buffer, lline_buffer);
00972       
00973       /* If there are options or categories to inherit from, process them now */
00974       if (c) {
00975          if (!(cur = strchr(c, ')'))) {
00976             ast_log(LOG_WARNING, "parse error: no closing ')', line %d of %s\n", lineno, configfile);
00977             return -1;
00978          }
00979          *cur = '\0';
00980          while ((cur = strsep(&c, ","))) {
00981             if (!strcasecmp(cur, "!")) {
00982                (*cat)->ignored = 1;
00983             } else if (!strcasecmp(cur, "+")) {
00984                *cat = category_get(cfg, catname, 1);
00985                if (!(*cat)) {
00986                   if (newcat)
00987                      ast_category_destroy(newcat);
00988                   ast_log(LOG_WARNING, "Category addition requested, but category '%s' does not exist, line %d of %s\n", catname, lineno, configfile);
00989                   return -1;
00990                }
00991                if (newcat) {
00992                   move_variables(newcat, *cat);
00993                   ast_category_destroy(newcat);
00994                   newcat = NULL;
00995                }
00996             } else {
00997                struct ast_category *base;
00998             
00999                base = category_get(cfg, cur, 1);
01000                if (!base) {
01001                   ast_log(LOG_WARNING, "Inheritance requested, but category '%s' does not exist, line %d of %s\n", cur, lineno, configfile);
01002                   return -1;
01003                }
01004                inherit_category(*cat, base);
01005             }
01006          }
01007       }
01008       if (newcat)
01009          ast_category_append(cfg, *cat);
01010    } else if (cur[0] == '#') { /* A directive - #include or #exec */
01011       char *cur2;
01012       char real_inclusion_name[256];
01013       struct ast_config_include *inclu;
01014       int do_include = 0;  /* otherwise, it is exec */
01015 
01016       cur++;
01017       c = cur;
01018       while (*c && (*c > 32)) c++;
01019       if (*c) {
01020          *c = '\0';
01021          /* Find real argument */
01022          c = ast_skip_blanks(c + 1);
01023          if (!(*c))
01024             c = NULL;
01025       } else 
01026          c = NULL;
01027       if (!strcasecmp(cur, "include")) {
01028          do_include = 1;
01029       } else if (!strcasecmp(cur, "exec")) {
01030          if (!ast_opt_exec_includes) {
01031             ast_log(LOG_WARNING, "Cannot perform #exec unless execincludes option is enabled in asterisk.conf (options section)!\n");
01032             return 0;   /* XXX is this correct ? or we should return -1 ? */
01033          }
01034       } else {
01035          ast_log(LOG_WARNING, "Unknown directive '#%s' at line %d of %s\n", cur, lineno, configfile);
01036          return 0;   /* XXX is this correct ? or we should return -1 ? */
01037       }
01038 
01039       if (c == NULL) {
01040          ast_log(LOG_WARNING, "Directive '#%s' needs an argument (%s) at line %d of %s\n", 
01041                do_include ? "include" : "exec",
01042                do_include ? "filename" : "/path/to/executable",
01043                lineno,
01044                configfile);
01045          return 0;   /* XXX is this correct ? or we should return -1 ? */
01046       }
01047 
01048       cur = c;
01049       /* Strip off leading and trailing "'s and <>'s */
01050       if (*c == '"') {
01051          /* Dequote */
01052          while (*c) {
01053             if (*c == '"') {
01054                strcpy(c, c + 1); /* SAFE */
01055                c--;
01056             } else if (*c == '\\') {
01057                strcpy(c, c + 1); /* SAFE */
01058             }
01059             c++;
01060          }
01061       } else if (*c == '<') {
01062          /* C-style include */
01063          if (*(c + strlen(c) - 1) == '>') {
01064             cur++;
01065             *(c + strlen(c) - 1) = '\0';
01066          }
01067       }
01068       cur2 = cur;
01069 
01070       /* #exec </path/to/executable>
01071          We create a tmp file, then we #include it, then we delete it. */
01072       if (!do_include) {
01073          struct timeval now = ast_tvnow();
01074          if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
01075             config_cache_attribute(configfile, ATTRIBUTE_EXEC, NULL, who_asked);
01076          snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d%d.%ld", (int)now.tv_sec, (int)now.tv_usec, (long)pthread_self());
01077          snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file);
01078          ast_safe_system(cmd);
01079          cur = exec_file;
01080       } else {
01081          if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
01082             config_cache_attribute(configfile, ATTRIBUTE_INCLUDE, cur, who_asked);
01083          exec_file[0] = '\0';
01084       }
01085       /* A #include */
01086       /* record this inclusion */
01087       inclu = ast_include_new(cfg, cfg->include_level == 1 ? "" : configfile, cur, !do_include, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name));
01088 
01089       do_include = ast_config_internal_load(cur, cfg, flags, real_inclusion_name, who_asked) ? 1 : 0;
01090       if (!ast_strlen_zero(exec_file))
01091          unlink(exec_file);
01092       if (!do_include) {
01093          ast_log(LOG_ERROR, "The file '%s' was listed as a #include but it does not exist.\n", cur);
01094          return -1;
01095       }
01096       /* XXX otherwise what ? the default return is 0 anyways */
01097 
01098    } else {
01099       /* Just a line (variable = value) */
01100       int object = 0;
01101       if (!(*cat)) {
01102          ast_log(LOG_WARNING,
01103             "parse error: No category context for line %d of %s\n", lineno, configfile);
01104          return -1;
01105       }
01106       c = strchr(cur, '=');
01107 
01108       if (c && c > cur && (*(c - 1) == '+')) {
01109          struct ast_variable *var, *replace = NULL;
01110          struct ast_str **str = ast_threadstorage_get(&appendbuf, sizeof(*str));
01111 
01112          if (!str || !*str) {
01113             return -1;
01114          }
01115 
01116          *(c - 1) = '\0';
01117          c++;
01118          cur = ast_strip(cur);
01119 
01120          /* Must iterate through category until we find last variable of same name (since there could be multiple) */
01121          for (var = ast_category_first(*cat); var; var = var->next) {
01122             if (!strcmp(var->name, cur)) {
01123                replace = var;
01124             }
01125          }
01126 
01127          if (!replace) {
01128             /* Nothing to replace; just set a variable normally. */
01129             goto set_new_variable;
01130          }
01131 
01132          ast_str_set(str, 0, "%s", replace->value);
01133          ast_str_append(str, 0, "%s", c);
01134          ast_variable_update(*cat, replace->name, ast_strip((*str)->str), replace->value, object);
01135       } else if (c) {
01136          *c = 0;
01137          c++;
01138          /* Ignore > in => */
01139          if (*c== '>') {
01140             object = 1;
01141             c++;
01142          }
01143 set_new_variable:
01144          if ((v = ast_variable_new(ast_strip(cur), ast_strip(c), S_OR(suggested_include_file, cfg->include_level == 1 ? "" : configfile)))) {
01145             v->lineno = lineno;
01146             v->object = object;
01147             *last_cat = 0;
01148             *last_var = v;
01149             /* Put and reset comments */
01150             v->blanklines = 0;
01151             ast_variable_append(*cat, v);
01152             /* add comments */
01153             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01154                v->precomments = ALLOC_COMMENT(comment_buffer);
01155             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01156                v->sameline = ALLOC_COMMENT(lline_buffer);
01157             if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
01158                CB_RESET(comment_buffer, lline_buffer);
01159             
01160          } else {
01161             return -1;
01162          }
01163       } else {
01164          ast_log(LOG_WARNING, "No '=' (equal sign) in line %d of %s\n", lineno, configfile);
01165       }
01166    }
01167    return 0;
01168 }

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 1878 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(), buf, clear_config_maps(), config, LOG_WARNING, ast_config::max_include_level, ast_variable::name, ast_variable::next, strsep(), table, and ast_variable::value.

Referenced by main().

01879 {
01880    struct ast_config *config, *configtmp;
01881    struct ast_variable *v;
01882    char *driver, *table, *database, *stringp, *tmp;
01883    struct ast_flags flags = { 0 };
01884 
01885    clear_config_maps();
01886 
01887    configtmp = ast_config_new();
01888    configtmp->max_include_level = 1;
01889    config = ast_config_internal_load(extconfig_conf, configtmp, flags, "", "extconfig");
01890    if (!config) {
01891       ast_config_destroy(configtmp);
01892       return 0;
01893    }
01894 
01895    for (v = ast_variable_browse(config, "settings"); v; v = v->next) {
01896       char buf[512];
01897       ast_copy_string(buf, v->value, sizeof(buf));
01898       stringp = buf;
01899       driver = strsep(&stringp, ",");
01900 
01901       if ((tmp = strchr(stringp, '\"')))
01902          stringp = tmp;
01903 
01904       /* check if the database text starts with a double quote */
01905       if (*stringp == '"') {
01906          stringp++;
01907          database = strsep(&stringp, "\"");
01908          strsep(&stringp, ",");
01909       } else {
01910          /* apparently this text has no quotes */
01911          database = strsep(&stringp, ",");
01912       }
01913 
01914       table = strsep(&stringp, ",");
01915 
01916       if (!strcmp(v->name, extconfig_conf)) {
01917          ast_log(LOG_WARNING, "Cannot bind '%s'!\n", extconfig_conf);
01918          continue;
01919       }
01920 
01921       if (!strcmp(v->name, "asterisk.conf")) {
01922          ast_log(LOG_WARNING, "Cannot bind 'asterisk.conf'!\n");
01923          continue;
01924       }
01925 
01926       if (!strcmp(v->name, "logger.conf")) {
01927          ast_log(LOG_WARNING, "Cannot bind 'logger.conf'!\n");
01928          continue;
01929       }
01930 
01931       if (!driver || !database)
01932          continue;
01933       if (!strcasecmp(v->name, "sipfriends")) {
01934          ast_log(LOG_WARNING, "The 'sipfriends' table is obsolete, update your config to use sipusers and sippeers, though they can point to the same table.\n");
01935          append_mapping("sipusers", driver, database, table ? table : "sipfriends");
01936          append_mapping("sippeers", driver, database, table ? table : "sipfriends");
01937       } else if (!strcasecmp(v->name, "iaxfriends")) {
01938          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");
01939          append_mapping("iaxusers", driver, database, table ? table : "iaxfriends");
01940          append_mapping("iaxpeers", driver, database, table ? table : "iaxfriends");
01941       } else 
01942          append_mapping(v->name, driver, database, table);
01943    }
01944       
01945    ast_config_destroy(config);
01946    return 0;
01947 }

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 2533 of file config.c.

References ast_cli_register_multiple().

Referenced by main().

02534 {
02535    ast_cli_register_multiple(cli_config, sizeof(cli_config) / sizeof(struct ast_cli_entry));
02536    return 0;
02537 }

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

Definition at line 1513 of file config.c.

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

Referenced by config_text_file_save().

01514 {
01515    struct inclfile lookup;
01516    
01517    if (!file || file[0] == 0) {
01518       if (configfile[0] == '/')
01519          ast_copy_string(fn, configfile, fn_size);
01520       else
01521          snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, configfile);
01522    } else if (file[0] == '/') 
01523       ast_copy_string(fn, file, fn_size);
01524    else
01525       snprintf(fn, fn_size, "%s/%s", ast_config_AST_CONFIG_DIR, file);
01526    lookup.fname = fn;
01527    *fi = ao2_find(fileset, &lookup, OBJ_POINTER);
01528    if (!(*fi)) {
01529       /* set up a file scratch pad */
01530       struct inclfile *fx = ao2_alloc(sizeof(struct inclfile), inclfile_destroy);
01531       fx->fname = ast_strdup(fn);
01532       fx->lineno = 1;
01533       *fi = fx;
01534       ao2_link(fileset, fx);
01535    }
01536 }

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

Definition at line 432 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().

00433 {
00434    struct ast_variable *new = ast_variable_new(old->name, old->value, old->file);
00435 
00436    if (new) {
00437       new->lineno = old->lineno;
00438       new->object = old->object;
00439       new->blanklines = old->blanklines;
00440       /* TODO: clone comments? */
00441    }
00442 
00443    return new;
00444 }


Variable Documentation

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

Definition at line 90 of file config.c.

Referenced by process_text_line().

struct ast_cli_entry cli_config[] [static]

Initial value:

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

Definition at line 2527 of file config.c.

Definition at line 168 of file config.c.

ast_mutex_t config_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

struct ast_config_map * config_maps [static]

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

Definition at line 57 of file config.c.

Initial value:

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

Definition at line 2025 of file config.c.


Generated on Wed Oct 28 11:52:14 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6