diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-01-25 06:10:20 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-01-25 06:10:20 +0000 |
commit | 2207b9a515214bf72785eabf75bd587bd7df23e8 (patch) | |
tree | 5e740f79246c281ef1bc43bcffc87fd21f676005 /config.c | |
parent | c7f2030d7977ded782c6430a33e57bbbb69cd6df (diff) |
Merge config updates (bug #3406)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@4889 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'config.c')
-rwxr-xr-x | config.c | 989 |
1 files changed, 514 insertions, 475 deletions
@@ -25,7 +25,6 @@ # include <glob.h> #endif #include <asterisk/config.h> -#include <asterisk/config_pvt.h> #include <asterisk/cli.h> #include <asterisk/lock.h> #include <asterisk/options.h> @@ -40,8 +39,7 @@ #define COMMENT_META ';' #define COMMENT_TAG '-' -static int ast_cust_config=0; -static config_static_func *global_load_func; +static char *extconfig_conf = "extconfig.conf"; static struct ast_config_map { struct ast_config_map *next; @@ -50,44 +48,33 @@ static struct ast_config_map { char *database; char *table; char stuff[0]; -} *maps = NULL; - -AST_MUTEX_DEFINE_STATIC(ast_cust_config_lock); -static struct ast_config_reg *ast_cust_config_list; -static char *config_conf_file = "extconfig.conf"; - -void ast_destroy_realtime(struct ast_variable *v) -{ - struct ast_variable *vn; - while(v) { - vn = v; - v = v->next; - free(vn); - } -} - -void ast_category_destroy(struct ast_category *cat) -{ - ast_destroy_realtime(cat->root); - free(cat); -} - -void ast_destroy(struct ast_config *ast) -{ - struct ast_category *cat, *catn; - - if (!ast) - return; - - cat = ast->root; - while(cat) { - ast_destroy_realtime(cat->root); - catn = cat; - cat = cat->next; - free(catn); - } - free(ast); -} +} *config_maps = NULL; + +AST_MUTEX_DEFINE_STATIC(config_lock); +static struct ast_config_engine *config_engine_list; + +#define MAX_INCLUDE_LEVEL 10 + +struct ast_comment { + struct ast_comment *next; + char cmt[0]; +}; + +struct ast_category { + char name[80]; + struct ast_variable *root; + struct ast_variable *last; + struct ast_category *next; +}; + +struct ast_config { + struct ast_category *root; + struct ast_category *last; + struct ast_category *current; + struct ast_category *last_browse; /* used to cache the last category supplied via category_browse */ + int include_level; + int max_include_level; +}; int ast_true(const char *s) { @@ -96,11 +83,11 @@ int ast_true(const char *s) /* Determine if this is a true value */ if (!strcasecmp(s, "yes") || !strcasecmp(s, "true") || - !strcasecmp(s, "y") || - !strcasecmp(s, "t") || - !strcasecmp(s, "1") || - !strcasecmp(s, "on")) - return -1; + !strcasecmp(s, "y") || + !strcasecmp(s, "t") || + !strcasecmp(s, "1") || + !strcasecmp(s, "on")) + return -1; return 0; } @@ -111,150 +98,232 @@ int ast_false(const char *s) /* Determine if this is a false value */ if (!strcasecmp(s, "no") || !strcasecmp(s, "false") || - !strcasecmp(s, "n") || - !strcasecmp(s, "f") || - !strcasecmp(s, "0") || - !strcasecmp(s, "off")) - return -1; + !strcasecmp(s, "n") || + !strcasecmp(s, "f") || + !strcasecmp(s, "0") || + !strcasecmp(s, "off")) + return -1; return 0; } -struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category) +struct ast_variable *ast_variable_new(const char *name, const char *value) { - struct ast_category *cat; - cat = config->root; - while(cat) { - if (cat->name == category) - return cat->root; - cat = cat->next; + struct ast_variable *variable; + + int length = strlen(name) + strlen(value) + 2 + sizeof(struct ast_variable); + variable = malloc(length); + if (variable) { + memset(variable, 0, length); + variable->name = variable->stuff; + variable->value = variable->stuff + strlen(name) + 1; + strcpy(variable->name,name); + strcpy(variable->value,value); } - cat = config->root; - while(cat) { - if (!strcasecmp(cat->name, category)) - return cat->root; - cat = cat->next; + + return variable; +} + +void ast_variable_append(struct ast_category *category, struct ast_variable *variable) +{ + if (category->last) + category->last->next = variable; + else + category->root = variable; + category->last = variable; +} + +void ast_variables_destroy(struct ast_variable *v) +{ + struct ast_variable *vn; + + while(v) { + vn = v; + v = v->next; + free(vn); } - return NULL; } -char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *value) +struct ast_variable *ast_variable_browse(const struct ast_config *config, const char *category) +{ + struct ast_category *cat = NULL; + + if (category && config->last_browse && (config->last_browse->name == category)) + cat = config->last_browse; + else + cat = ast_category_get(config, category); + + if (cat) + return cat->root; + else + return NULL; +} + +char *ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable) { struct ast_variable *v; + if (category) { - v = ast_variable_browse(config, category); - while (v) { - if (value == v->name) + for (v = ast_variable_browse(config, category); v; v = v->next) + if (variable == v->name) return v->value; - v=v->next; - } - v = ast_variable_browse(config, category); - while (v) { - if (!strcasecmp(value, v->name)) + for (v = ast_variable_browse(config, category); v; v = v->next) + if (!strcasecmp(variable, v->name)) return v->value; - v=v->next; - } } else { struct ast_category *cat; - cat = config->root; - while(cat) { - v = cat->root; - while (v) { - if (!strcasecmp(value, v->name)) + + for (cat = config->root; cat; cat = cat->next) + for (v = cat->root; v; v = v->next) + if (!strcasecmp(variable, v->name)) return v->value; - v=v->next; - } - cat = cat->next; - } } + return NULL; } +struct ast_category *ast_category_new(const char *name) +{ + struct ast_category *category; + + category = malloc(sizeof(struct ast_category)); + if (category) { + memset(category, 0, sizeof(struct ast_category)); + strncpy(category->name, name, sizeof(category->name) - 1); + } + + return category; +} + struct ast_category *ast_category_get(const struct ast_config *config, const char *category_name) { - struct ast_category *category = config->root; + struct ast_category *cat; - while(category) { - if (!strcasecmp(category->name, category_name)) - return category; - category = category->next; + for (cat = config->root; cat; cat = cat->next) { + if (cat->name == category_name) + return cat; + } + + for (cat = config->root; cat; cat = cat->next) { + if (!strcasecmp(cat->name, category_name)) + return cat; } return NULL; } -int ast_category_exist(struct ast_config *config, char *category_name) +int ast_category_exist(const struct ast_config *config, const char *category_name) { return !!ast_category_get(config, category_name); } +void ast_category_append(struct ast_config *config, struct ast_category *category) +{ + if (config->last) + config->last->next = category; + else + config->root = category; + config->last = category; + config->current = category; +} -static struct ast_config_reg *get_ast_cust_config_keyword(const char *name, char *database, int dbsiz, char *table, int tabsiz) +void ast_category_destroy(struct ast_category *cat) { - struct ast_config_reg *reg,*ret=NULL; - struct ast_config_map *map; + ast_variables_destroy(cat->root); + free(cat); +} - ast_mutex_lock(&ast_cust_config_lock); - map = maps; - while(map) { - if (!strcasecmp(name, map->name)) { - strncpy(database, map->database, dbsiz - 1); - if (map->table) - strncpy(table, map->table, tabsiz - 1); - else - strncpy(table, name, tabsiz - 1); - break; +char *ast_category_browse(struct ast_config *config, const char *prev) +{ + struct ast_category *cat = NULL; + + if (prev && config->last_browse && (config->last_browse->name == prev)) + cat = config->last_browse->next; + else if (!prev && config->root) + cat = config->root; + else if (prev) { + for (cat = config->root; cat; cat = cat->next) { + if (cat->name == prev) { + cat = cat->next; + break; + } } - map = map->next; - } - if (map) { - for (reg=ast_cust_config_list;reg && !ret;reg=reg->next) { - if (!strcmp(reg->name,map->driver)) - ret=reg; + if (!cat) { + for (cat = config->root; cat; cat = cat->next) { + if (!strcasecmp(cat->name, prev)) { + cat = cat->next; + break; + } + } } } - ast_mutex_unlock(&ast_cust_config_lock); - return ret; + + config->last_browse = cat; + if (cat) + return cat->name; + else + return NULL; } -void ast_config_destroy_all(void) +struct ast_variable *ast_category_detach_variables(struct ast_category *cat) { - struct ast_config_reg *key; - ast_mutex_lock(&ast_cust_config_lock); - for (key=ast_cust_config_list;key;key=key->next) { - ast_config_deregister(key); + struct ast_variable *v; + + v = cat->root; + cat->root = NULL; + + return v; +} + +void ast_category_rename(struct ast_category *cat, const char *name) +{ + strncpy(cat->name, name, sizeof(cat->name) - 1); +} + +struct ast_config *ast_config_new(void) +{ + struct ast_config *config; + + config = malloc(sizeof(*config)); + if (config) { + memset(config, 0, sizeof(*config)); + config->max_include_level = MAX_INCLUDE_LEVEL; } - ast_cust_config_list = NULL; - ast_mutex_unlock(&ast_cust_config_lock); + + return config; } -static struct ast_config_reg *get_config_registrations(void) +void ast_config_destroy(struct ast_config *cfg) { - return ast_cust_config_list; + struct ast_category *cat, *catn; + + if (!cfg) + return; + + cat = cfg->root; + while(cat) { + ast_variables_destroy(cat->root); + catn = cat; + cat = cat->next; + free(catn); + } + free(cfg); } -void ast_category_append(struct ast_config *config, struct ast_category *category) +struct ast_category *ast_config_get_current_category(const struct ast_config *cfg) { - if (config->last) - config->last->next = category; - else - config->root = category; - config->last = category; + return cfg->current; } -static void variable_append(struct ast_category *category, struct ast_variable *variable) +void ast_config_set_current_category(struct ast_config *cfg, const struct ast_category *cat) { - if (category->last) - category->last->next = variable; - else - category->root = variable; - category->last = variable; + /* cast below is just to silence compiler warning about dropping "const" */ + cfg->current = (struct ast_category *) cat; } -static int cfg_process(struct ast_config *tmp, struct ast_category **cat, char *buf, int lineno, const char *configfile, int includelevel) +static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile) { char *c; char *cur; - char *arg=NULL; struct ast_variable *v; int object; @@ -267,19 +336,17 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **cat, char * /* A category header */ c = strchr(cur, ']'); if (!c) { - ast_destroy(tmp); ast_log(LOG_WARNING, "parse error: no closing ']', line %d of %s\n", lineno, configfile); return -1; } *c = '\0'; cur++; - *cat = ast_new_category(cur); + *cat = ast_category_new(cur); if (!*cat) { - ast_destroy(tmp); ast_log(LOG_WARNING, "Out of memory, line %d of %s\n", lineno, configfile); return -1; } - ast_category_append(tmp, *cat); + ast_category_append(cfg, *cat); } else if (cur[0] == '#') { /* A directive */ cur++; @@ -309,21 +376,8 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **cat, char * break; } - if((c = strchr(cur,':'))) { - *c = '\0'; - c++; - arg = c; - } - - if (includelevel < MAX_INCLUDE_LEVEL) { - if(arg && cur) { - ast_log(LOG_WARNING, "Including files with explicit config engine no longer permitted. Please use extconfig.conf to specify all mappings\n"); - } else { - if (!ast_internal_load(cur, tmp, cat, includelevel + 1)) - return -1; - } - } else - ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", includelevel); + if (!ast_config_internal_load(cur, cfg)) + return -1; } else ast_log(LOG_WARNING, "Directive '#include' needs an argument (filename) at line %d of %s\n", lineno, configfile); } @@ -334,7 +388,6 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **cat, char * if (!*cat) { ast_log(LOG_WARNING, "parse error: No category context for line %d of %s\n", lineno, configfile); - ast_destroy(tmp); return -1; } c = strchr(cur, '='); @@ -347,15 +400,14 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **cat, char * c++; } else object = 0; - v = ast_new_variable(ast_strip(cur), ast_strip(c)); + v = ast_variable_new(ast_strip(cur), ast_strip(c)); if (v) { v->lineno = lineno; v->object = object; /* Put and reset comments */ v->blanklines = 0; - variable_append(*cat, v); + ast_variable_append(*cat, v); } else { - ast_destroy(tmp); ast_log(LOG_WARNING, "Out of memory, line %d\n", lineno); return -1; } @@ -367,154 +419,24 @@ static int cfg_process(struct ast_config *tmp, struct ast_category **cat, char * return 0; } -int ast_save(char *configfile, struct ast_config *cfg, char *generator) -{ - FILE *f; - char fn[256]; - char date[256]=""; - time_t t; - struct ast_variable *var; - struct ast_category *cat; - int blanklines = 0; - if (configfile[0] == '/') { - strncpy(fn, configfile, sizeof(fn)-1); - } else { - snprintf(fn, sizeof(fn), "%s/%s", AST_CONFIG_DIR, configfile); - } - time(&t); - strncpy(date, ctime(&t), sizeof(date) - 1); - if ((f = fopen(fn, "w"))) { - if ((option_verbose > 1) && !option_debug) - ast_verbose( VERBOSE_PREFIX_2 "Saving '%s': ", fn); - fprintf(f, ";!\n"); - fprintf(f, ";! Automatically generated configuration file\n"); - fprintf(f, ";! Filename: %s (%s)\n", configfile, fn); - fprintf(f, ";! Generator: %s\n", generator); - fprintf(f, ";! Creation Date: %s", date); - fprintf(f, ";!\n"); - cat = cfg->root; - while(cat) { - /* Dump section with any appropriate comment */ - fprintf(f, "[%s]\n", cat->name); - var = cat->root; - while(var) { - if (var->sameline) - fprintf(f, "%s %s %s ; %s\n", var->name, (var->object ? "=>" : "="), var->value, var->sameline->cmt); - else - fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value); - if (var->blanklines) { - blanklines = var->blanklines; - while (blanklines) { - fprintf(f, "\n"); - blanklines--; - } - } - - var = var->next; - } -#if 0 - /* Put an empty line */ - fprintf(f, "\n"); -#endif - cat = cat->next; - } - } else { - if (option_debug) - printf("Unable to open for writing: %s\n", fn); - else if (option_verbose > 1) - printf( "Unable to write (%s)", strerror(errno)); - return -1; - } - fclose(f); - return 0; -} - -struct ast_variable *ast_load_realtime(const char *family, ...) -{ - struct ast_config_reg *reg; - char db[256]=""; - char table[256]=""; - struct ast_variable *res=NULL; - va_list ap; - va_start(ap, family); - reg = get_ast_cust_config_keyword(family, db, sizeof(db), table, sizeof(table)); - if (reg && reg->realtime_func) - res = reg->realtime_func(db, table, ap); - va_end(ap); - return res; -} - -struct ast_config *ast_load_realtime_multientry(const char *family, ...) -{ - struct ast_config_reg *reg; - char db[256]=""; - char table[256]=""; - struct ast_config *res=NULL; - va_list ap; - va_start(ap, family); - reg = get_ast_cust_config_keyword(family, db, sizeof(db), table, sizeof(table)); - if (reg && reg->realtime_multi_func) - res = reg->realtime_multi_func(db, table, ap); - va_end(ap); - return res; -} - -int ast_update_realtime(const char *family, const char *keyfield, const char *lookup, ...) -{ - struct ast_config_reg *reg; - int res = -1; - char db[256]=""; - char table[256]=""; - va_list ap; - va_start(ap, lookup); - reg = get_ast_cust_config_keyword(family, db, sizeof(db), table, sizeof(table)); - if (reg && reg->update_func) - res = reg->update_func(db, table, keyfield, lookup, ap); - va_end(ap); - return res; -} - -struct ast_config *ast_internal_load(const char *configfile, struct ast_config *tmp, struct ast_category **cat, int includelevel) +static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg) { char fn[256]; char buf[8192]; - char db[256]; - char table[256]; + char *new_buf, *comment_p, *process_buf; FILE *f; int lineno=0; int comment = 0, nest[MAX_NESTED_COMMENTS]; + struct ast_category *cat = NULL; - struct ast_config_reg *reg=NULL; - config_static_func *load_func; - char *comment_p, *process_buf, *new_buf=NULL; - - load_func=NULL; - if (strcmp(configfile,config_conf_file) && strcmp(configfile,"asterisk.conf") && ast_cust_config_list) { - if (global_load_func) { - load_func = global_load_func; - } else { - reg = get_ast_cust_config_keyword(configfile, db, sizeof(db), table, sizeof(table)); - if (reg && reg->static_func) { - load_func = reg->static_func; - } else { - reg = get_ast_cust_config_keyword(configfile, db, sizeof(db), table, sizeof(table)); - if (reg && reg->static_func) - global_load_func = load_func = reg->static_func; - } - } + cat = ast_config_get_current_category(cfg); - if (load_func) { - ast_log(LOG_NOTICE,"Loading Config %s via %s engine\n",configfile,reg && reg->name ? reg->name : "global"); - if((tmp = load_func(db, table, configfile, tmp, cat, includelevel))) - return tmp; - } - } - - if (configfile[0] == '/') { - strncpy(fn, configfile, sizeof(fn)-1); + if (filename[0] == '/') { + strncpy(fn, filename, sizeof(fn)-1); } else { - snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, configfile); + snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, filename); } + #ifdef AST_INCLUDE_GLOB { int glob_ret; @@ -546,13 +468,6 @@ struct ast_config *ast_internal_load(const char *configfile, struct ast_config * ast_log(LOG_DEBUG, "Parsing %s\n", fn); else if (option_verbose > 2) ast_verbose("Found\n"); - if (!tmp) - tmp = ast_new_config(); - if (!tmp) { - ast_log(LOG_WARNING, "Out of memory\n"); - fclose(f); - return tmp; - } while(!feof(f)) { lineno++; if (fgets(buf, sizeof(buf), f)) { @@ -603,8 +518,8 @@ struct ast_config *ast_internal_load(const char *configfile, struct ast_config * new_buf = comment_p + 1; } } - if (process_buf && cfg_process(tmp, cat, process_buf, lineno, configfile, includelevel)) { - tmp = NULL; + if (process_buf && process_text_line(cfg, &cat, process_buf, lineno, filename)) { + cfg = NULL; break; } } @@ -620,7 +535,7 @@ struct ast_config *ast_internal_load(const char *configfile, struct ast_config * ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment]); } #ifdef AST_INCLUDE_GLOB - if (!tmp) + if (!cfg) break; } globfree(&globbuf); @@ -628,233 +543,357 @@ struct ast_config *ast_internal_load(const char *configfile, struct ast_config * } #endif - return tmp; + return cfg; } -int ast_config_register(struct ast_config_reg *new) +int config_text_file_save(const char *configfile, const struct ast_config *cfg, const char *generator) { - struct ast_config_reg *ptr; - ast_mutex_lock(&ast_cust_config_lock); - if (!ast_cust_config_list) { - ast_cust_config_list = new; + FILE *f; + char fn[256]; + char date[256]=""; + time_t t; + struct ast_variable *var; + struct ast_category *cat; + int blanklines = 0; + + if (configfile[0] == '/') { + strncpy(fn, configfile, sizeof(fn)-1); } else { - for(ptr=ast_cust_config_list;ptr->next;ptr=ptr->next); - ptr->next = new; + snprintf(fn, sizeof(fn), "%s/%s", AST_CONFIG_DIR, configfile); } - ast_mutex_unlock(&ast_cust_config_lock); - ast_log(LOG_NOTICE,"Registered Config Engine %s\n",new->name); + time(&t); + strncpy(date, ctime(&t), sizeof(date) - 1); + if ((f = fopen(fn, "w"))) { + if ((option_verbose > 1) && !option_debug) + ast_verbose( VERBOSE_PREFIX_2 "Saving '%s': ", fn); + fprintf(f, ";!\n"); + fprintf(f, ";! Automatically generated configuration file\n"); + fprintf(f, ";! Filename: %s (%s)\n", configfile, fn); + fprintf(f, ";! Generator: %s\n", generator); + fprintf(f, ";! Creation Date: %s", date); + fprintf(f, ";!\n"); + cat = cfg->root; + while(cat) { + /* Dump section with any appropriate comment */ + fprintf(f, "[%s]\n", cat->name); + var = cat->root; + while(var) { + if (var->sameline) + fprintf(f, "%s %s %s ; %s\n", var->name, (var->object ? "=>" : "="), var->value, var->sameline->cmt); + else + fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value); + if (var->blanklines) { + blanklines = var->blanklines; + while (blanklines--) + fprintf(f, "\n"); + } + + var = var->next; + } +#if 0 + /* Put an empty line */ + fprintf(f, "\n"); +#endif + cat = cat->next; + } + } else { + if (option_debug) + printf("Unable to open for writing: %s\n", fn); + else if (option_verbose > 1) + printf( "Unable to write (%s)", strerror(errno)); + return -1; + } + fclose(f); + return 0; +} + +static void clear_config_maps(void) +{ + struct ast_config_map *map; + + ast_mutex_lock(&config_lock); + + while (config_maps) { + map = config_maps; + config_maps = config_maps->next; + free(map); + } + + ast_mutex_unlock(&config_lock); +} + +void read_config_maps(void) +{ + struct ast_config *config; + struct ast_variable *v; + struct ast_config_map *map; + int length; + char *driver, *table, *database, *stringp; + + clear_config_maps(); + + config = ast_config_new(); + config->max_include_level = 1; + config = ast_config_internal_load(extconfig_conf, config); + if (!config) + return; + + for (v = ast_variable_browse(config, "settings"); v; v = v->next) { + stringp = v->value; + driver = strsep(&stringp, ","); + database = strsep(&stringp, ","); + table = strsep(&stringp, ","); + + if (!strcmp(v->name, extconfig_conf) || !strcmp(v->name, "asterisk.conf")) { + ast_log(LOG_WARNING, "Cannot bind asterisk.conf or extconfig.conf!\n"); + continue; + } + + if (!driver || !database) + continue; + + length = sizeof(*map); + length += strlen(v->name) + 1; + length += strlen(driver) + 1; + length += strlen(database) + 1; + if (table) + length += strlen(table) + 1; + map = malloc(length); + + if (!map) + continue; + + memset(map, 0, length); + map->name = map->stuff; + strcpy(map->name, v->name); + map->driver = map->name + strlen(map->name) + 1; + strcpy(map->driver, driver); + map->database = map->driver + strlen(map->driver) + 1; + strcpy(map->database, database); + if (table) { + map->table = map->database + strlen(map->database) + 1; + strcpy(map->table, table); + } + map->next = config_maps; + + if (option_verbose > 1) + ast_verbose(VERBOSE_PREFIX_2 "Binding %s to %s/%s/%s\n", + map->name, map->driver, map->database, map->table ? map->table : map->name); + + config_maps = map; + } + + ast_config_destroy(config); +} + +int ast_config_engine_register(struct ast_config_engine *new) +{ + struct ast_config_engine *ptr; + + ast_mutex_lock(&config_lock); + + if (!config_engine_list) { + config_engine_list = new; + } else { + for (ptr = config_engine_list; ptr->next; ptr=ptr->next); + ptr->next = new; + } + + ast_mutex_unlock(&config_lock); + ast_log(LOG_NOTICE,"Registered Config Engine %s\n", new->name); + return 1; } -int ast_config_deregister(struct ast_config_reg *del) +int ast_config_engine_deregister(struct ast_config_engine *del) { - struct ast_config_reg *ptr=NULL,*last=NULL; - ast_mutex_lock(&ast_cust_config_lock); - for (ptr=ast_cust_config_list;ptr;ptr=ptr->next) { + struct ast_config_engine *ptr, *last=NULL; + + ast_mutex_lock(&config_lock); + + for (ptr = config_engine_list; ptr; ptr=ptr->next) { if (ptr == del) { - if (last && ptr->next) { + if (last) last->next = ptr->next; - } else if (last && ! ptr->next) { - last->next = NULL; - } else if (!last && ptr->next) { - ast_cust_config_list = ptr->next; - } else if (!last && !ptr->next) { - ast_cust_config_list = NULL; - } + else + config_engine_list = ptr->next; + break; } last = ptr; } - ast_mutex_unlock(&ast_cust_config_lock); - return 0; -} -int ast_cust_config_active(void) { - return (ast_cust_config >0) ? 1 : 0; + ast_mutex_unlock(&config_lock); + + return 0; } -struct ast_config *ast_load(char *configfile) +static struct ast_config_engine *find_engine(const char *filename, char *database, int dbsiz, char *table, int tabsiz) { - struct ast_category *category = NULL; + struct ast_config_engine *eng, *ret=NULL; + struct ast_config_map *map; - return ast_internal_load(configfile, NULL, &category, 0); -} + ast_mutex_lock(&config_lock); -char *ast_category_browse(struct ast_config *config, char *prev) -{ - struct ast_category *cat; - if (!prev) { - if (config->root) - return config->root->name; - else - return NULL; - } - cat = config->root; - while(cat) { - if (cat->name == prev) { - if (cat->next) - return cat->next->name; + map = config_maps; + while (map) { + if (!strcasecmp(filename, map->name)) { + strncpy(database, map->database, dbsiz-1); + if (map->table) + strncpy(table, map->table, tabsiz-1); else - return NULL; + strncpy(table, filename, tabsiz-1); + break; } - cat = cat->next; + map = map->next; } - cat = config->root; - while(cat) { - if (!strcasecmp(cat->name, prev)) { - if (cat->next) - return cat->next->name; - else - return NULL; + if (map) { + for (eng = config_engine_list; eng; eng = eng->next) { + if (!strcmp(eng->name, map->driver)) { + ret = eng; + break; + } } - cat = cat->next; } - return NULL; + ast_mutex_unlock(&config_lock); + + return ret; } +static struct ast_config_engine text_file_engine = { + .name = "text", + .load_func = config_text_file_load, +}; -struct ast_config *ast_new_config(void) +struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg) { - struct ast_config *config; - config = malloc(sizeof(struct ast_config)); - memset(config,0,sizeof(struct ast_config)); - return config; -} + char db[256]; + char table[256]; + struct ast_config_engine *loader = &text_file_engine; + struct ast_config *result; -struct ast_category *ast_new_category(char *name) -{ - struct ast_category *category; - category = malloc(sizeof(struct ast_category)); - if (category) { - memset(category, 0, sizeof(struct ast_category)); - strncpy(category->name, name, sizeof(category->name) - 1); + if (cfg->include_level == cfg->max_include_level) { + ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", cfg->max_include_level); + return NULL; } - return category; + + cfg->include_level++; + + if (strcmp(filename, extconfig_conf) && strcmp(filename, "asterisk.conf") && config_engine_list) { + struct ast_config_engine *eng; + + eng = find_engine(filename, db, sizeof(db), table, sizeof(table)); + if (eng && eng->load_func) { + loader = eng; + } else { + eng = find_engine("global", db, sizeof(db), table, sizeof(table)); + if (eng && eng->load_func) + loader = eng; + } + } + + result = loader->load_func(db, table, filename, cfg); + if (result) + result->include_level--; + + return result; } -struct ast_variable *ast_new_variable(char *name, char *value) +struct ast_config *ast_config_load(const char *filename) { - struct ast_variable *variable; - int length = strlen(name) + strlen(value) + 2 + sizeof(struct ast_variable); - variable = malloc(length); - if (variable) { - memset(variable, 0, length); - variable->name = variable->stuff; - variable->value = variable->stuff + strlen(name) + 1; - strcpy(variable->name,name); - strcpy(variable->value,value); - } - return variable; + struct ast_config *cfg; + struct ast_config *result; + + cfg = ast_config_new(); + if (!cfg) + return NULL; + + result = ast_config_internal_load(filename, cfg); + if (!result) + ast_config_destroy(cfg); + + return result; } -int ast_cust_config_register(struct ast_config_reg *new) +struct ast_variable *ast_load_realtime(const char *family, ...) { - ast_config_register(new); - read_ast_cust_config(); - return 1; + struct ast_config_engine *eng; + char db[256]=""; + char table[256]=""; + struct ast_variable *res=NULL; + va_list ap; + + va_start(ap, family); + eng = find_engine(family, db, sizeof(db), table, sizeof(table)); + if (eng && eng->realtime_func) + res = eng->realtime_func(db, table, ap); + va_end(ap); + + return res; } -int ast_cust_config_deregister(struct ast_config_reg *new) + +struct ast_config *ast_load_realtime_multientry(const char *family, ...) { - ast_config_deregister(new); - read_ast_cust_config(); - return 1; + struct ast_config_engine *eng; + char db[256]=""; + char table[256]=""; + struct ast_config *res=NULL; + va_list ap; + + va_start(ap, family); + eng = find_engine(family, db, sizeof(db), table, sizeof(table)); + if (eng && eng->realtime_multi_func) + res = eng->realtime_multi_func(db, table, ap); + va_end(ap); + + return res; } -static void clear_cust_keywords(void) +int ast_update_realtime(const char *family, const char *keyfield, const char *lookup, ...) { - struct ast_config_map *map, *prev; - ast_mutex_lock(&ast_cust_config_lock); - map = maps; - while(map) { - prev = map; - map = map->next; - free(prev); - } - maps = NULL; - ast_mutex_unlock(&ast_cust_config_lock); + struct ast_config_engine *eng; + int res = -1; + char db[256]=""; + char table[256]=""; + va_list ap; + + va_start(ap, lookup); + eng = find_engine(family, db, sizeof(db), table, sizeof(table)); + if (eng && eng->update_func) + res = eng->update_func(db, table, keyfield, lookup, ap); + va_end(ap); + + return res; } static int config_command(int fd, int argc, char **argv) { - struct ast_config_reg *key; + struct ast_config_engine *eng; struct ast_config_map *map; - ast_cli(fd,"\n\n"); - ast_mutex_lock(&ast_cust_config_lock); - for (key=get_config_registrations();key;key=key->next) { - ast_cli(fd,"\nConfig Engine: %s\n",key->name); - map = maps; - while(map) { - if (!strcasecmp(map->driver, key->name)) - ast_cli(fd,"===> %s (db=%s, table=%s)\n",map->name, map->database, map->table ? map->table : map->name); - map = map->next; - } + ast_mutex_lock(&config_lock); + + ast_cli(fd, "\n\n"); + for (eng = config_engine_list; eng; eng = eng->next) { + ast_cli(fd, "\nConfig Engine: %s\n", eng->name); + for (map = config_maps; map; map = map->next) + if (!strcasecmp(map->driver, eng->name)) { + ast_cli(fd, "===> %s (db=%s, table=%s)\n", map->name, map->database, + map->table ? map->table : map->name); + break; + } } - ast_mutex_unlock(&ast_cust_config_lock); ast_cli(fd,"\n\n"); + ast_mutex_unlock(&config_lock); + return 0; } static struct ast_cli_entry config_command_struct = { - { "show","config","handles", NULL }, config_command, - "Show Config Handles", NULL }; + { "show", "config", "mappings" }, config_command, "Show Config mappings (file names to config engines)" +}; int register_config_cli() { return ast_cli_register(&config_command_struct); } - -int read_ast_cust_config(void) -{ - char *cfg = config_conf_file; - struct ast_config *config; - struct ast_variable *v; - struct ast_config_map *map; - int length; - char *driver, *table, *database, *stringp; - - clear_cust_keywords(); - config = ast_load(cfg); - if (config) { - for (v = ast_variable_browse(config,"settings");v;v=v->next) { - stringp = v->value; - driver = strsep(&stringp, ","); - database = strsep(&stringp, ","); - table = strsep(&stringp, ","); - - if (!strcmp(v->name,config_conf_file) || !strcmp(v->name,"asterisk.conf")) { - ast_log(LOG_WARNING, "Cannot bind asterisk.conf or extconfig.conf!\n"); - } else if (driver && database) { - length = sizeof(struct ast_config_map); - length += strlen(v->name) + 1; - length += strlen(driver) + 1; - length += strlen(database) + 1; - if (table) - length += strlen(table) + 1; - map = malloc(length); - if (map) { - memset(map, 0, length); - map->name = map->stuff; - strcpy(map->name, v->name); - map->driver = map->name + strlen(map->name) + 1; - strcpy(map->driver, driver); - map->database = map->driver + strlen(map->driver) + 1; - strcpy(map->database, database); - if (table) { - map->table = map->database + strlen(map->database) + 1; - strcpy(map->table, table); - } else - map->table = NULL; - map->next = maps; - if (option_verbose > 1) - ast_verbose(VERBOSE_PREFIX_2 "Binding %s to %s/%s/%s\n",map->name,map->driver, map->database, map->table ? map->table : map->name); - maps = map; - } - } - } - - ast_destroy(config); - } - - return 0; -} |