|
|
|
@ -64,13 +64,28 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|
|
|
|
static char *extconfig_conf = "extconfig.conf";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief Structure to keep comments for rewriting configuration files */
|
|
|
|
|
/*! \brief Structure to keep comments for rewriting configuration files */
|
|
|
|
|
struct ast_comment {
|
|
|
|
|
struct ast_comment *next;
|
|
|
|
|
char cmt[0];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*! \brief Hold the mtime for config files, so if we don't need to reread our config, don't. */
|
|
|
|
|
struct cache_file_include {
|
|
|
|
|
AST_LIST_ENTRY(cache_file_include) list;
|
|
|
|
|
char include[0];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct cache_file_mtime {
|
|
|
|
|
AST_LIST_ENTRY(cache_file_mtime) list;
|
|
|
|
|
AST_LIST_HEAD(includes, cache_file_include) includes;
|
|
|
|
|
unsigned int has_exec:1;
|
|
|
|
|
time_t mtime;
|
|
|
|
|
char filename[0];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static AST_LIST_HEAD_STATIC(cfmtime_head, cache_file_mtime);
|
|
|
|
|
|
|
|
|
|
#define CB_INCR 250
|
|
|
|
|
|
|
|
|
|
static void CB_INIT(char **comment_buffer, int *comment_buffer_size, char **lline_buffer, int *lline_buffer_size)
|
|
|
|
@ -590,7 +605,58 @@ void ast_config_set_current_category(struct ast_config *cfg, const struct ast_ca
|
|
|
|
|
cfg->current = (struct ast_category *) cat;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, int withcomments,
|
|
|
|
|
enum config_cache_attribute_enum {
|
|
|
|
|
ATTRIBUTE_INCLUDE = 0,
|
|
|
|
|
ATTRIBUTE_EXEC = 1,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void config_cache_attribute(const char *configfile, enum config_cache_attribute_enum attrtype, const char *filename)
|
|
|
|
|
{
|
|
|
|
|
struct cache_file_mtime *cfmtime;
|
|
|
|
|
struct cache_file_include *cfinclude;
|
|
|
|
|
struct stat statbuf = { 0, };
|
|
|
|
|
|
|
|
|
|
/* Find our cached entry for this configuration file */
|
|
|
|
|
AST_LIST_LOCK(&cfmtime_head);
|
|
|
|
|
AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
|
|
|
|
|
if (!strcmp(cfmtime->filename, configfile))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!cfmtime) {
|
|
|
|
|
cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(configfile) + 1);
|
|
|
|
|
if (!cfmtime) {
|
|
|
|
|
AST_LIST_UNLOCK(&cfmtime_head);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
AST_LIST_HEAD_INIT(&cfmtime->includes);
|
|
|
|
|
strcpy(cfmtime->filename, configfile);
|
|
|
|
|
/* Note that the file mtime is initialized to 0, i.e. 1970 */
|
|
|
|
|
AST_LIST_INSERT_TAIL(&cfmtime_head, cfmtime, list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!stat(configfile, &statbuf))
|
|
|
|
|
cfmtime->mtime = 0;
|
|
|
|
|
else
|
|
|
|
|
cfmtime->mtime = statbuf.st_mtime;
|
|
|
|
|
|
|
|
|
|
switch (attrtype) {
|
|
|
|
|
case ATTRIBUTE_INCLUDE:
|
|
|
|
|
cfinclude = ast_calloc(1, sizeof(*cfinclude) + strlen(filename) + 1);
|
|
|
|
|
if (!cfinclude) {
|
|
|
|
|
AST_LIST_UNLOCK(&cfmtime_head);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
strcpy(cfinclude->include, filename);
|
|
|
|
|
AST_LIST_INSERT_TAIL(&cfmtime->includes, cfinclude, list);
|
|
|
|
|
break;
|
|
|
|
|
case ATTRIBUTE_EXEC:
|
|
|
|
|
cfmtime->has_exec = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
AST_LIST_UNLOCK(&cfmtime_head);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int process_text_line(struct ast_config *cfg, struct ast_category **cat, char *buf, int lineno, const char *configfile, struct ast_flags flags,
|
|
|
|
|
char **comment_buffer, int *comment_buffer_size, char **lline_buffer, int *lline_buffer_size)
|
|
|
|
|
{
|
|
|
|
|
char *c;
|
|
|
|
@ -619,13 +685,13 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
/* add comments */
|
|
|
|
|
if (withcomments && *comment_buffer && (*comment_buffer)[0] ) {
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && *comment_buffer && (*comment_buffer)[0] ) {
|
|
|
|
|
newcat->precomments = ALLOC_COMMENT(*comment_buffer);
|
|
|
|
|
}
|
|
|
|
|
if (withcomments && *lline_buffer && (*lline_buffer)[0] ) {
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && *lline_buffer && (*lline_buffer)[0] ) {
|
|
|
|
|
newcat->sameline = ALLOC_COMMENT(*lline_buffer);
|
|
|
|
|
}
|
|
|
|
|
if ( withcomments )
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
|
|
|
|
|
CB_RESET(comment_buffer, lline_buffer);
|
|
|
|
|
|
|
|
|
|
/* If there are options or categories to inherit from, process them now */
|
|
|
|
@ -702,15 +768,20 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
|
|
|
|
|
}
|
|
|
|
|
/* #exec </path/to/executable>
|
|
|
|
|
We create a tmp file, then we #include it, then we delete it. */
|
|
|
|
|
if (do_exec) {
|
|
|
|
|
if (do_exec) {
|
|
|
|
|
if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
|
|
|
|
|
config_cache_attribute(configfile, ATTRIBUTE_EXEC, NULL);
|
|
|
|
|
snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self());
|
|
|
|
|
snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file);
|
|
|
|
|
ast_safe_system(cmd);
|
|
|
|
|
cur = exec_file;
|
|
|
|
|
} else
|
|
|
|
|
} else {
|
|
|
|
|
if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
|
|
|
|
|
config_cache_attribute(configfile, ATTRIBUTE_INCLUDE, cur);
|
|
|
|
|
exec_file[0] = '\0';
|
|
|
|
|
}
|
|
|
|
|
/* A #include */
|
|
|
|
|
do_include = ast_config_internal_load(cur, cfg, withcomments) ? 1 : 0;
|
|
|
|
|
do_include = ast_config_internal_load(cur, cfg, flags) ? 1 : 0;
|
|
|
|
|
if (!ast_strlen_zero(exec_file))
|
|
|
|
|
unlink(exec_file);
|
|
|
|
|
if (!do_include)
|
|
|
|
@ -750,13 +821,13 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
|
|
|
|
|
v->blanklines = 0;
|
|
|
|
|
ast_variable_append(*cat, v);
|
|
|
|
|
/* add comments */
|
|
|
|
|
if (withcomments && *comment_buffer && (*comment_buffer)[0] ) {
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && *comment_buffer && (*comment_buffer)[0] ) {
|
|
|
|
|
v->precomments = ALLOC_COMMENT(*comment_buffer);
|
|
|
|
|
}
|
|
|
|
|
if (withcomments && *lline_buffer && (*lline_buffer)[0] ) {
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && *lline_buffer && (*lline_buffer)[0] ) {
|
|
|
|
|
v->sameline = ALLOC_COMMENT(*lline_buffer);
|
|
|
|
|
}
|
|
|
|
|
if ( withcomments )
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS))
|
|
|
|
|
CB_RESET(comment_buffer, lline_buffer);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
@ -769,7 +840,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, int withcomments)
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
char fn[256];
|
|
|
|
|
char buf[8192];
|
|
|
|
@ -780,6 +851,8 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
struct ast_category *cat = NULL;
|
|
|
|
|
int count = 0;
|
|
|
|
|
struct stat statbuf;
|
|
|
|
|
struct cache_file_mtime *cfmtime = NULL;
|
|
|
|
|
struct cache_file_include *cfinclude;
|
|
|
|
|
/*! Growable string buffer */
|
|
|
|
|
char *comment_buffer=0; /*!< this will be a comment collector.*/
|
|
|
|
|
int comment_buffer_size=0; /*!< the amount of storage so far alloc'd for the comment_buffer */
|
|
|
|
@ -787,8 +860,8 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
char *lline_buffer=0; /*!< A buffer for stuff behind the ; */
|
|
|
|
|
int lline_buffer_size=0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cat = ast_config_get_current_category(cfg);
|
|
|
|
|
if (cfg)
|
|
|
|
|
cat = ast_config_get_current_category(cfg);
|
|
|
|
|
|
|
|
|
|
if (filename[0] == '/') {
|
|
|
|
|
ast_copy_string(fn, filename, sizeof(fn));
|
|
|
|
@ -796,7 +869,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, filename);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (withcomments) {
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
|
|
|
|
|
CB_INIT(&comment_buffer, &comment_buffer_size, &lline_buffer, &lline_buffer_size);
|
|
|
|
|
if (!lline_buffer || !comment_buffer) {
|
|
|
|
|
ast_log(LOG_ERROR, "Failed to initialize the comment buffer!\n");
|
|
|
|
@ -833,6 +906,77 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
ast_log(LOG_WARNING, "'%s' is not a regular file, ignoring\n", fn);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) {
|
|
|
|
|
/* Find our cached entry for this configuration file */
|
|
|
|
|
AST_LIST_LOCK(&cfmtime_head);
|
|
|
|
|
AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
|
|
|
|
|
if (!strcmp(cfmtime->filename, fn))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!cfmtime) {
|
|
|
|
|
cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(fn) + 1);
|
|
|
|
|
if (!cfmtime)
|
|
|
|
|
continue;
|
|
|
|
|
AST_LIST_HEAD_INIT(&cfmtime->includes);
|
|
|
|
|
strcpy(cfmtime->filename, fn);
|
|
|
|
|
/* Note that the file mtime is initialized to 0, i.e. 1970 */
|
|
|
|
|
AST_LIST_INSERT_TAIL(&cfmtime_head, cfmtime, list);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cfmtime && (!cfmtime->has_exec) && (cfmtime->mtime == statbuf.st_mtime) && ast_test_flag(&flags, CONFIG_FLAG_FILEUNCHANGED)) {
|
|
|
|
|
/* File is unchanged, what about the (cached) includes (if any)? */
|
|
|
|
|
int unchanged = 1;
|
|
|
|
|
AST_LIST_TRAVERSE(&cfmtime->includes, cfinclude, list) {
|
|
|
|
|
/* We must glob here, because if we did not, then adding a file to globbed directory would
|
|
|
|
|
* incorrectly cause no reload to be necessary. */
|
|
|
|
|
char fn2[256];
|
|
|
|
|
#ifdef AST_INCLUDE_GLOB
|
|
|
|
|
int glob_ret;
|
|
|
|
|
glob_t globbuf = { .gl_offs = 0 };
|
|
|
|
|
#ifdef SOLARIS
|
|
|
|
|
glob_ret = glob(cfinclude->include, GLOB_NOCHECK, NULL, &globbuf);
|
|
|
|
|
#else
|
|
|
|
|
glob_ret = glob(cfinclude->include, GLOB_NOMAGIC|GLOB_BRACE, NULL, &globbuf);
|
|
|
|
|
#endif
|
|
|
|
|
/* On error, we reparse */
|
|
|
|
|
if (glob_ret == GLOB_NOSPACE || glob_ret == GLOB_ABORTED)
|
|
|
|
|
unchanged = 0;
|
|
|
|
|
else {
|
|
|
|
|
/* loop over expanded files */
|
|
|
|
|
int j;
|
|
|
|
|
for (j = 0; j < globbuf.gl_pathc; j++) {
|
|
|
|
|
ast_copy_string(fn2, globbuf.gl_pathv[j], sizeof(fn2));
|
|
|
|
|
#else
|
|
|
|
|
ast_copy_string(fn2, cfinclude->include);
|
|
|
|
|
#endif
|
|
|
|
|
if (config_text_file_load(NULL, NULL, fn2, NULL, flags) == NULL) {
|
|
|
|
|
unchanged = 0;
|
|
|
|
|
/* One change is enough to short-circuit and reload the whole shebang */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
#ifdef AST_INCLUDE_GLOB
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (unchanged) {
|
|
|
|
|
AST_LIST_UNLOCK(&cfmtime_head);
|
|
|
|
|
return CONFIG_STATUS_FILEUNCHANGED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (cfmtime)
|
|
|
|
|
AST_LIST_UNLOCK(&cfmtime_head);
|
|
|
|
|
|
|
|
|
|
/* If cfg is NULL, then we just want an answer */
|
|
|
|
|
if (cfg == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (cfmtime)
|
|
|
|
|
cfmtime->mtime = statbuf.st_mtime;
|
|
|
|
|
|
|
|
|
|
ast_verb(2, "Parsing '%s': ", fn);
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
if (!(f = fopen(fn, "r"))) {
|
|
|
|
@ -846,7 +990,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
while (!feof(f)) {
|
|
|
|
|
lineno++;
|
|
|
|
|
if (fgets(buf, sizeof(buf), f)) {
|
|
|
|
|
if ( withcomments ) {
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
|
|
|
|
|
CB_ADD(&comment_buffer, &comment_buffer_size, lline_buffer); /* add the current lline buffer to the comment buffer */
|
|
|
|
|
lline_buffer[0] = 0; /* erase the lline buffer */
|
|
|
|
|
}
|
|
|
|
@ -883,7 +1027,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
/* Actually have to move what's left over the top, then continue */
|
|
|
|
|
char *oldptr;
|
|
|
|
|
oldptr = process_buf + strlen(process_buf);
|
|
|
|
|
if ( withcomments ) {
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
|
|
|
|
|
CB_ADD(&comment_buffer, &comment_buffer_size, ";");
|
|
|
|
|
CB_ADD_LEN(&comment_buffer, &comment_buffer_size, oldptr+1, new_buf-oldptr-1);
|
|
|
|
|
}
|
|
|
|
@ -897,7 +1041,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
if (!comment) {
|
|
|
|
|
/* If ; is found, and we are not nested in a comment,
|
|
|
|
|
we immediately stop all comment processing */
|
|
|
|
|
if ( withcomments ) {
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS)) {
|
|
|
|
|
LLB_ADD(&lline_buffer, &lline_buffer_size, comment_p);
|
|
|
|
|
}
|
|
|
|
|
*comment_p = '\0';
|
|
|
|
@ -906,7 +1050,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
new_buf = comment_p + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( withcomments && comment && !process_buf )
|
|
|
|
|
if (ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment && !process_buf )
|
|
|
|
|
{
|
|
|
|
|
CB_ADD(&comment_buffer, &comment_buffer_size, buf); /* the whole line is a comment, store it */
|
|
|
|
|
}
|
|
|
|
@ -914,7 +1058,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
if (process_buf) {
|
|
|
|
|
char *buf = ast_strip(process_buf);
|
|
|
|
|
if (!ast_strlen_zero(buf)) {
|
|
|
|
|
if (process_text_line(cfg, &cat, buf, lineno, fn, withcomments, &comment_buffer, &comment_buffer_size, &lline_buffer, &lline_buffer_size)) {
|
|
|
|
|
if (process_text_line(cfg, &cat, buf, lineno, fn, flags, &comment_buffer, &comment_buffer_size, &lline_buffer, &lline_buffer_size)) {
|
|
|
|
|
cfg = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -928,7 +1072,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
ast_log(LOG_WARNING,"Unterminated comment detected beginning on line %d\n", nest[comment - 1]);
|
|
|
|
|
}
|
|
|
|
|
#ifdef AST_INCLUDE_GLOB
|
|
|
|
|
if (!cfg)
|
|
|
|
|
if (cfg == NULL || cfg == CONFIG_STATUS_FILEUNCHANGED)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
globfree(&globbuf);
|
|
|
|
@ -936,7 +1080,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (cfg && cfg->include_level == 1 && withcomments && comment_buffer) {
|
|
|
|
|
if (cfg && cfg != CONFIG_STATUS_FILEUNCHANGED && cfg->include_level == 1 && ast_test_flag(&flags, CONFIG_FLAG_WITHCOMMENTS) && comment_buffer) {
|
|
|
|
|
ast_free(comment_buffer);
|
|
|
|
|
ast_free(lline_buffer);
|
|
|
|
|
comment_buffer = NULL;
|
|
|
|
@ -1090,12 +1234,13 @@ int read_config_maps(void)
|
|
|
|
|
struct ast_config *config, *configtmp;
|
|
|
|
|
struct ast_variable *v;
|
|
|
|
|
char *driver, *table, *database, *stringp, *tmp;
|
|
|
|
|
struct ast_flags flags = { 0 };
|
|
|
|
|
|
|
|
|
|
clear_config_maps();
|
|
|
|
|
|
|
|
|
|
configtmp = ast_config_new();
|
|
|
|
|
configtmp->max_include_level = 1;
|
|
|
|
|
config = ast_config_internal_load(extconfig_conf, configtmp, 0);
|
|
|
|
|
config = ast_config_internal_load(extconfig_conf, configtmp, flags);
|
|
|
|
|
if (!config) {
|
|
|
|
|
ast_config_destroy(configtmp);
|
|
|
|
|
return 0;
|
|
|
|
@ -1234,7 +1379,7 @@ static struct ast_config_engine text_file_engine = {
|
|
|
|
|
.load_func = config_text_file_load,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, int withcomments)
|
|
|
|
|
struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, struct ast_flags flags)
|
|
|
|
|
{
|
|
|
|
|
char db[256];
|
|
|
|
|
char table[256];
|
|
|
|
@ -1263,9 +1408,9 @@ struct ast_config *ast_config_internal_load(const char *filename, struct ast_con
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = loader->load_func(db, table, filename, cfg, withcomments);
|
|
|
|
|
result = loader->load_func(db, table, filename, cfg, flags);
|
|
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
|
if (result && result != CONFIG_STATUS_FILEUNCHANGED)
|
|
|
|
|
result->include_level--;
|
|
|
|
|
else
|
|
|
|
|
cfg->include_level--;
|
|
|
|
@ -1273,23 +1418,7 @@ struct ast_config *ast_config_internal_load(const char *filename, struct ast_con
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ast_config *ast_config_load(const char *filename)
|
|
|
|
|
{
|
|
|
|
|
struct ast_config *cfg;
|
|
|
|
|
struct ast_config *result;
|
|
|
|
|
|
|
|
|
|
cfg = ast_config_new();
|
|
|
|
|
if (!cfg)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
result = ast_config_internal_load(filename, cfg, 0);
|
|
|
|
|
if (!result)
|
|
|
|
|
ast_config_destroy(cfg);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ast_config *ast_config_load_with_comments(const char *filename)
|
|
|
|
|
struct ast_config *ast_config_load(const char *filename, struct ast_flags flags)
|
|
|
|
|
{
|
|
|
|
|
struct ast_config *cfg;
|
|
|
|
|
struct ast_config *result;
|
|
|
|
@ -1298,8 +1427,8 @@ struct ast_config *ast_config_load_with_comments(const char *filename)
|
|
|
|
|
if (!cfg)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
result = ast_config_internal_load(filename, cfg, 1);
|
|
|
|
|
if (!result)
|
|
|
|
|
result = ast_config_internal_load(filename, cfg, flags);
|
|
|
|
|
if (!result || result == CONFIG_STATUS_FILEUNCHANGED)
|
|
|
|
|
ast_config_destroy(cfg);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|