|
|
|
@ -21,6 +21,8 @@
|
|
|
|
|
#include <asterisk/logger.h>
|
|
|
|
|
#include "asterisk.h"
|
|
|
|
|
|
|
|
|
|
#define MAX_INCLUDE_LEVEL 10
|
|
|
|
|
|
|
|
|
|
struct ast_category {
|
|
|
|
|
char name[80];
|
|
|
|
|
struct ast_variable *root;
|
|
|
|
@ -150,15 +152,119 @@ int ast_category_exist(struct ast_config *config, char *category_name)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ast_config *ast_load(char *configfile)
|
|
|
|
|
static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, int includelevel);
|
|
|
|
|
static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, char *buf, int lineno, char *configfile, int includelevel)
|
|
|
|
|
{
|
|
|
|
|
char *c;
|
|
|
|
|
char *cur;
|
|
|
|
|
struct ast_variable *v;
|
|
|
|
|
/* Strip off lines using ; as comment */
|
|
|
|
|
c = strchr(buf, ';');
|
|
|
|
|
if (c)
|
|
|
|
|
*c = '\0';
|
|
|
|
|
cur = strip(buf);
|
|
|
|
|
if (strlen(cur)) {
|
|
|
|
|
/* Actually parse the entry */
|
|
|
|
|
if (cur[0] == '[') {
|
|
|
|
|
/* A category header */
|
|
|
|
|
c = strchr(cur, ']');
|
|
|
|
|
if (c) {
|
|
|
|
|
*c = 0;
|
|
|
|
|
*_tmpc = malloc(sizeof(struct ast_category));
|
|
|
|
|
if (!*_tmpc) {
|
|
|
|
|
ast_destroy(tmp);
|
|
|
|
|
ast_log(LOG_WARNING,
|
|
|
|
|
"Out of memory, line %d\n", lineno);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
strncpy((*_tmpc)->name, cur+1, sizeof((*_tmpc)->name) - 1);
|
|
|
|
|
(*_tmpc)->root = NULL;
|
|
|
|
|
(*_tmpc)->next = tmp->root;
|
|
|
|
|
tmp->root = *_tmpc;
|
|
|
|
|
*_last = NULL;
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_WARNING,
|
|
|
|
|
"parse error: no closing ']', line %d of %s\n", lineno, configfile);
|
|
|
|
|
}
|
|
|
|
|
} else if (cur[0] == '#') {
|
|
|
|
|
/* A directive */
|
|
|
|
|
cur++;
|
|
|
|
|
c = cur;
|
|
|
|
|
while(*c && (*c > 32)) c++;
|
|
|
|
|
if (*c) {
|
|
|
|
|
*c = '\0';
|
|
|
|
|
c++;
|
|
|
|
|
/* Find real argument */
|
|
|
|
|
while(*c && (*c < 33)) c++;
|
|
|
|
|
if (!*c)
|
|
|
|
|
c = NULL;
|
|
|
|
|
} else
|
|
|
|
|
c = NULL;
|
|
|
|
|
if (!strcasecmp(cur, "include")) {
|
|
|
|
|
/* A #include */
|
|
|
|
|
if (c) {
|
|
|
|
|
while((*c == '<') || (*c == '>') || (*c == '\"')) c++;
|
|
|
|
|
/* Get rid of leading mess */
|
|
|
|
|
cur = c;
|
|
|
|
|
while(strlen(cur)) {
|
|
|
|
|
c = cur + strlen(cur) - 1;
|
|
|
|
|
if ((*c == '>') || (*c == '<') || (*c == '\"'))
|
|
|
|
|
*c = '\0';
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (includelevel < MAX_INCLUDE_LEVEL) {
|
|
|
|
|
__ast_load(cur, tmp, _tmpc, _last, includelevel + 1);
|
|
|
|
|
} else
|
|
|
|
|
ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", includelevel);
|
|
|
|
|
} else
|
|
|
|
|
ast_log(LOG_WARNING, "Directive '#include' needs an argument (filename) at line %d of %s\n", lineno, configfile);
|
|
|
|
|
/* Strip off leading and trailing "'s and <>'s */
|
|
|
|
|
} else
|
|
|
|
|
ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile);
|
|
|
|
|
} else {
|
|
|
|
|
/* Just a line (variable = value) */
|
|
|
|
|
if (!*_tmpc) {
|
|
|
|
|
ast_log(LOG_WARNING,
|
|
|
|
|
"parse error: No category context for line %d of %s\n", lineno, configfile);
|
|
|
|
|
}
|
|
|
|
|
c = strchr(cur, '=');
|
|
|
|
|
if (c) {
|
|
|
|
|
*c = 0;
|
|
|
|
|
c++;
|
|
|
|
|
/* Ignore > in => */
|
|
|
|
|
if (*c== '>')
|
|
|
|
|
c++;
|
|
|
|
|
v = malloc(sizeof(struct ast_variable));
|
|
|
|
|
if (v) {
|
|
|
|
|
v->next = NULL;
|
|
|
|
|
v->name = strdup(strip(cur));
|
|
|
|
|
v->value = strdup(strip(c));
|
|
|
|
|
v->lineno = lineno;
|
|
|
|
|
if (*_last)
|
|
|
|
|
(*_last)->next = v;
|
|
|
|
|
else
|
|
|
|
|
(*_tmpc)->root = v;
|
|
|
|
|
*_last = v;
|
|
|
|
|
} else {
|
|
|
|
|
ast_destroy(tmp);
|
|
|
|
|
ast_log(LOG_WARNING, "Out of memory, line %d\n", lineno);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_WARNING, "No '=' (equal sign) in line %d of %s\n", lineno, configfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, int includelevel)
|
|
|
|
|
{
|
|
|
|
|
char fn[256];
|
|
|
|
|
char buf[256];
|
|
|
|
|
struct ast_config *tmp=NULL;
|
|
|
|
|
struct ast_category *tmpc=NULL;
|
|
|
|
|
struct ast_variable *v, *last=NULL;
|
|
|
|
|
FILE *f;
|
|
|
|
|
char *c, *cur;
|
|
|
|
|
int lineno=0;
|
|
|
|
|
|
|
|
|
|
if (configfile[0] == '/') {
|
|
|
|
@ -175,96 +281,22 @@ struct ast_config *ast_load(char *configfile)
|
|
|
|
|
ast_log(LOG_DEBUG, "Parsing %s\n", fn);
|
|
|
|
|
else if (option_verbose > 1)
|
|
|
|
|
ast_verbose( "Found\n");
|
|
|
|
|
tmp = malloc(sizeof(struct ast_config));
|
|
|
|
|
if (!tmp) {
|
|
|
|
|
tmp = malloc(sizeof(struct ast_config));
|
|
|
|
|
tmp->root = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (!tmp) {
|
|
|
|
|
ast_log(LOG_WARNING, "Out of memory\n");
|
|
|
|
|
fclose(f);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
tmp->root = NULL;
|
|
|
|
|
while(!feof(f)) {
|
|
|
|
|
fgets(buf, sizeof(buf), f);
|
|
|
|
|
lineno++;
|
|
|
|
|
if (!feof(f)) {
|
|
|
|
|
/* Strip off lines using ; as comment */
|
|
|
|
|
c = strchr(buf, ';');
|
|
|
|
|
if (c)
|
|
|
|
|
*c = '\0';
|
|
|
|
|
cur = strip(buf);
|
|
|
|
|
if (strlen(cur)) {
|
|
|
|
|
/* Actually parse the entry */
|
|
|
|
|
if (cur[0] == '[') {
|
|
|
|
|
/* A category header */
|
|
|
|
|
c = strchr(cur, ']');
|
|
|
|
|
if (c) {
|
|
|
|
|
*c = 0;
|
|
|
|
|
#if 0
|
|
|
|
|
/*
|
|
|
|
|
* Check category duplicity before structure
|
|
|
|
|
* allocation
|
|
|
|
|
*/
|
|
|
|
|
if (ast_category_exist(tmp,cur+1)) {
|
|
|
|
|
ast_destroy(tmp);
|
|
|
|
|
ast_log(LOG_WARNING,
|
|
|
|
|
"Found duplicit category [%s] in "
|
|
|
|
|
"file %s line %d\n",
|
|
|
|
|
cur+1,configfile,lineno);
|
|
|
|
|
fclose(f);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
tmpc = malloc(sizeof(struct ast_category));
|
|
|
|
|
if (!tmpc) {
|
|
|
|
|
ast_destroy(tmp);
|
|
|
|
|
ast_log(LOG_WARNING,
|
|
|
|
|
"Out of memory, line %d\n", lineno);
|
|
|
|
|
fclose(f);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
strncpy(tmpc->name, cur+1, sizeof(tmpc->name)-1);
|
|
|
|
|
tmpc->root = NULL;
|
|
|
|
|
tmpc->next = tmp->root;
|
|
|
|
|
tmp->root = tmpc;
|
|
|
|
|
last = NULL;
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_WARNING,
|
|
|
|
|
"parse error: no closing ']', line %d\n", lineno);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* Just a line (variable = value) */
|
|
|
|
|
if (!tmpc) {
|
|
|
|
|
ast_log(LOG_WARNING,
|
|
|
|
|
"parse error: No category context for line %d\n", lineno);
|
|
|
|
|
}
|
|
|
|
|
c = strchr(cur, '=');
|
|
|
|
|
if (c) {
|
|
|
|
|
*c = 0;
|
|
|
|
|
c++;
|
|
|
|
|
/* Ignore > in => */
|
|
|
|
|
if (*c== '>')
|
|
|
|
|
c++;
|
|
|
|
|
v = malloc(sizeof(struct ast_variable));
|
|
|
|
|
if (v) {
|
|
|
|
|
v->next = NULL;
|
|
|
|
|
v->name = strdup(strip(cur));
|
|
|
|
|
v->value = strdup(strip(c));
|
|
|
|
|
v->lineno = lineno;
|
|
|
|
|
if (last)
|
|
|
|
|
last->next = v;
|
|
|
|
|
else
|
|
|
|
|
tmpc->root = v;
|
|
|
|
|
last = v;
|
|
|
|
|
} else {
|
|
|
|
|
ast_destroy(tmp);
|
|
|
|
|
ast_log(LOG_WARNING, "Out of memory, line %d\n", lineno);
|
|
|
|
|
fclose(f);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_WARNING, "No '=' (equal sign) in line %d of %s\n", lineno, configfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (cfg_process(tmp, _tmpc, _last, buf, lineno, configfile, includelevel)) {
|
|
|
|
|
fclose(f);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -278,6 +310,13 @@ struct ast_config *ast_load(char *configfile)
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ast_config *ast_load(char *configfile)
|
|
|
|
|
{
|
|
|
|
|
struct ast_category *tmpc=NULL;
|
|
|
|
|
struct ast_variable *last = NULL;
|
|
|
|
|
return __ast_load(configfile, NULL, &tmpc, &last, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *ast_category_browse(struct ast_config *config, char *prev)
|
|
|
|
|
{
|
|
|
|
|
struct ast_category *cat;
|
|
|
|
|