00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <stdio.h>
00015 #include <unistd.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <errno.h>
00019 #include <time.h>
00020 #include <asterisk/config.h>
00021 #include <asterisk/config_pvt.h>
00022 #include <asterisk/cli.h>
00023 #include <asterisk/lock.h>
00024 #include <asterisk/options.h>
00025 #include <asterisk/logger.h>
00026 #include <asterisk/utils.h>
00027 #include "asterisk.h"
00028 #include "astconf.h"
00029
00030
00031 static int ast_cust_config=0;
00032 struct ast_config *(*global_load_func)(char *, struct ast_config *,struct ast_category **,struct ast_variable **,int
00033 #ifdef PRESERVE_COMMENTS
00034 ,struct ast_comment_struct *
00035 #endif
00036 );
00037
00038 AST_MUTEX_DEFINE_STATIC(ast_cust_config_lock);
00039 static struct ast_config_reg *ast_cust_config_list;
00040 static char *config_conf_file = "extconfig.conf";
00041
00042 static char *strip(char *buf)
00043 {
00044 char *start;
00045
00046 while (!ast_strlen_zero(buf) && (buf[strlen(buf)-1]<33))
00047 buf[strlen(buf)-1] = '\0';
00048 start = buf;
00049
00050 while (*start && (*start < 33))
00051 *start++ = '\0';
00052 return start;
00053 }
00054
00055 #ifdef PRESERVE_COMMENTS
00056 static void free_comments(struct ast_comment *com)
00057 {
00058 struct ast_comment *l;
00059 while (com) {
00060 l = com;
00061 com = com->next;
00062 free(l);
00063 }
00064 }
00065 #endif
00066
00067 void ast_destroy(struct ast_config *ast)
00068 {
00069 struct ast_category *cat, *catn;
00070 struct ast_variable *v, *vn;
00071
00072 if (!ast)
00073 return;
00074
00075 cat = ast->root;
00076 while(cat) {
00077 v = cat->root;
00078 while(v) {
00079 vn = v;
00080 free(v->name);
00081 free(v->value);
00082 #ifdef PRESERVE_COMMENTS
00083 free_comments(v->precomments);
00084 free_comments(v->sameline);
00085 #endif
00086 v = v->next;
00087 free(vn);
00088 }
00089 catn = cat;
00090 #ifdef PRESERVE_COMMENTS
00091 free_comments(cat->precomments);
00092 free_comments(cat->sameline);
00093 #endif
00094 cat = cat->next;
00095 free(catn);
00096 }
00097 #ifdef PRESERVE_COMMENTS
00098 free_comments(ast->trailingcomments);
00099 #endif
00100 free(ast);
00101 }
00102
00103 int ast_true(char *s)
00104 {
00105 if (!s)
00106 return 0;
00107
00108 if (!strcasecmp(s, "yes") ||
00109 !strcasecmp(s, "true") ||
00110 !strcasecmp(s, "y") ||
00111 !strcasecmp(s, "t") ||
00112 !strcasecmp(s, "1") ||
00113 !strcasecmp(s, "on"))
00114 return -1;
00115 return 0;
00116 }
00117
00118 int ast_false(char *s)
00119 {
00120 if (!s)
00121 return 0;
00122
00123 if (!strcasecmp(s, "no") ||
00124 !strcasecmp(s, "false") ||
00125 !strcasecmp(s, "n") ||
00126 !strcasecmp(s, "f") ||
00127 !strcasecmp(s, "0") ||
00128 !strcasecmp(s, "off"))
00129 return -1;
00130 return 0;
00131 }
00132
00133 struct ast_variable *ast_variable_browse(struct ast_config *config, char *category)
00134 {
00135 struct ast_category *cat;
00136 cat = config->root;
00137 while(cat) {
00138 if (cat->name == category)
00139 return cat->root;
00140 cat = cat->next;
00141 }
00142 cat = config->root;
00143 while(cat) {
00144 if (!strcasecmp(cat->name, category))
00145 return cat->root;
00146 cat = cat->next;
00147 }
00148 return NULL;
00149 }
00150
00151 char *ast_variable_retrieve(struct ast_config *config, char *category, char *value)
00152 {
00153 struct ast_variable *v;
00154 if (category) {
00155 v = ast_variable_browse(config, category);
00156 while (v) {
00157 if (value == v->name)
00158 return v->value;
00159 v=v->next;
00160 }
00161 v = ast_variable_browse(config, category);
00162 while (v) {
00163 if (!strcasecmp(value, v->name))
00164 return v->value;
00165 v=v->next;
00166 }
00167 } else {
00168 struct ast_category *cat;
00169 cat = config->root;
00170 while(cat) {
00171 v = cat->root;
00172 while (v) {
00173 if (!strcasecmp(value, v->name))
00174 return v->value;
00175 v=v->next;
00176 }
00177 cat = cat->next;
00178 }
00179 }
00180 return NULL;
00181 }
00182
00183 #ifdef PRESERVE_COMMENTS
00184 int ast_variable_delete(struct ast_config *cfg, char *category, char *variable, char *value)
00185 {
00186 struct ast_variable *v, *pv, *bv, *bpv;
00187 struct ast_category *cat;
00188 cat = cfg->root;
00189 while(cat) {
00190 if (cat->name == category) {
00191 break;
00192 }
00193 cat = cat->next;
00194 }
00195 if (!cat) {
00196 cat = cfg->root;
00197 while(cat) {
00198 if (!strcasecmp(cat->name, category)) {
00199 break;
00200 }
00201 cat = cat->next;
00202 }
00203 }
00204 if (!cat)
00205 return -1;
00206 v = cat->root;
00207 pv = NULL;
00208 while (v) {
00209 if ((variable == v->name) && (!value || !strcmp(v->value, value)))
00210 break;
00211 pv = v;
00212 v=v->next;
00213 }
00214 if (!v) {
00215
00216 bv = NULL;
00217 bpv = NULL;
00218 v = cat->root;
00219 pv = NULL;
00220 while (v) {
00221 if (!strcasecmp(variable, v->name) && (!value || !strcmp(v->value, value))) {
00222 bv = v;
00223 bpv = pv;
00224 }
00225 pv = v;
00226 v=v->next;
00227 }
00228 v = bv;
00229 }
00230
00231 if (v) {
00232
00233 if (pv)
00234 pv->next = v->next;
00235 else
00236 cat->root = v->next;
00237 v->next = NULL;
00238 free(v->name);
00239 if (v->value)
00240 free(v->value);
00241 free_comments(v->sameline);
00242 free_comments(v->precomments);
00243 return 0;
00244 }
00245 return -1;
00246 }
00247
00248 int ast_category_delete(struct ast_config *cfg, char *category)
00249 {
00250 struct ast_variable *v, *pv;
00251 struct ast_category *cat, *cprev;
00252 cat = cfg->root;
00253 cprev = NULL;
00254 while(cat) {
00255 if (cat->name == category) {
00256 break;
00257 }
00258 cprev = cat;
00259 cat = cat->next;
00260 }
00261 if (!cat) {
00262 cat = cfg->root;
00263 cprev = NULL;
00264 while(cat) {
00265 if (!strcasecmp(cat->name, category)) {
00266 break;
00267 }
00268 cprev = cat;
00269 cat = cat->next;
00270 }
00271 }
00272 if (!cat)
00273 return -1;
00274
00275 if (cprev)
00276 cprev->next = cat->next;
00277 else
00278 cfg->root = cat->next;
00279 v = cat->root;
00280 while (v) {
00281 pv = v;
00282 v=v->next;
00283 if (pv->value)
00284 free(pv->value);
00285 if (pv->name)
00286 free(pv->name);
00287 free_comments(pv->sameline);
00288 free_comments(pv->precomments);
00289 free(pv);
00290 }
00291 free_comments(cat->sameline);
00292 free_comments(cat->precomments);
00293 free(cat);
00294 return 0;
00295 }
00296
00297 struct ast_variable *ast_variable_append_modify(struct ast_config *config, char *category, char *variable, char *value, int newcat, int newvar, int move)
00298 {
00299 struct ast_variable *v, *pv=NULL, *bv, *bpv;
00300 struct ast_category *cat, *pcat;
00301 cat = config->root;
00302 if (!newcat) {
00303 while(cat) {
00304 if (cat->name == category) {
00305 break;
00306 }
00307 cat = cat->next;
00308 }
00309 if (!cat) {
00310 cat = config->root;
00311 while(cat) {
00312 if (!strcasecmp(cat->name, category)) {
00313 break;
00314 }
00315 cat = cat->next;
00316 }
00317 }
00318 }
00319 if (!cat) {
00320 cat = malloc(sizeof(struct ast_category));
00321 if (!cat)
00322 return NULL;
00323 memset(cat, 0, sizeof(struct ast_category));
00324 strncpy(cat->name, category, sizeof(cat->name) - 1);
00325 if (config->root) {
00326
00327 pcat = config->root;
00328 while(pcat->next)
00329 pcat = pcat->next;
00330 pcat->next = cat;
00331 } else {
00332
00333 config->root = cat;
00334 }
00335
00336 }
00337 if (!newvar) {
00338 v = cat->root;
00339 pv = NULL;
00340 while (v) {
00341 if (variable == v->name)
00342 break;
00343 pv = v;
00344 v=v->next;
00345 }
00346 if (!v) {
00347
00348 bv = NULL;
00349 bpv = NULL;
00350 v = cat->root;
00351 pv = NULL;
00352 while (v) {
00353 if (!strcasecmp(variable, v->name)) {
00354 bv = v;
00355 bpv = pv;
00356 }
00357 pv = v;
00358 v=v->next;
00359 }
00360 v = bv;
00361 }
00362 } else v = NULL;
00363 if (v && move) {
00364
00365 if (pv)
00366 pv->next = v->next;
00367 else
00368 cat->root = v->next;
00369 v->next = NULL;
00370 }
00371 if (!v) {
00372 v = malloc(sizeof(struct ast_variable));
00373 if (!v)
00374 return NULL;
00375 memset(v, 0, sizeof(struct ast_variable));
00376 v->name = strdup(variable);
00377 move = 1;
00378 }
00379 if (v->value)
00380 free(v->value);
00381 if (value)
00382 v->value = strdup(value);
00383 else
00384 v->value = strdup("");
00385 if (move) {
00386 if (cat->root) {
00387 pv = cat->root;
00388 while (pv->next)
00389 pv = pv->next;
00390 pv->next = v;
00391 } else {
00392 cat->root = v;
00393 }
00394 }
00395 return v;
00396 }
00397 #endif
00398
00399 int ast_category_exist(struct ast_config *config, char *category_name)
00400 {
00401 struct ast_category *category = NULL;
00402
00403 category = config->root;
00404
00405 while(category) {
00406 if (!strcasecmp(category->name,category_name))
00407 return 1;
00408 category = category->next;
00409 }
00410
00411 return 0;
00412 }
00413
00414 #ifdef PRESERVE_COMMENTS
00415 static struct ast_comment *build_comment(char *cmt)
00416 {
00417 struct ast_comment *c;
00418 int len = strlen(cmt) + 1;
00419 c = malloc(sizeof(struct ast_comment) + len);
00420 if (c) {
00421
00422 memset(c, 0, sizeof(struct ast_comment));
00423
00424 strcpy(c->cmt, cmt);
00425 }
00426 return c;
00427 }
00428 #endif
00429
00430 static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, int includelevel
00431 #ifdef PRESERVE_COMMENTS
00432 , struct ast_comment_struct *acs
00433 #endif
00434 );
00435
00436 static int cfg_process(struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, char *buf, int lineno, char *configfile, int includelevel
00437 #ifdef PRESERVE_COMMENTS
00438 ,struct ast_comment_struct *acs
00439 #endif
00440 )
00441 {
00442 char *c;
00443 char *cur;
00444 char *arg=NULL;
00445 struct ast_config_reg *reg=NULL;
00446 struct ast_config *(*load_func)(char *, struct ast_config *,struct ast_category **,struct ast_variable **,int
00447 #ifdef PRESERVE_COMMENTS
00448 ,struct ast_comment_struct *
00449 #endif
00450 );
00451 struct ast_variable *v;
00452 #ifdef PRESERVE_COMMENTS
00453 struct ast_comment *com = NULL;
00454 #endif
00455 int object;
00456
00457 c = strchr(buf, ';');
00458 while (c) {
00459 if ((c == buf) || (*(c-1) != '\\')) {
00460 *c = '\0';
00461 #ifdef PRESERVE_COMMENTS
00462 c++;
00463 if (*c != '!')
00464 com = build_comment(c);
00465 #endif
00466 } else {
00467 *(c-1) = ';';
00468 memmove(c, c + 1, strlen(c + 1));
00469 }
00470 c = strchr(c + 1, ';');
00471 }
00472 cur = strip(buf);
00473 if (!ast_strlen_zero(cur)) {
00474
00475 if (cur[0] == '[') {
00476
00477 c = strchr(cur, ']');
00478 if (c) {
00479 *c = 0;
00480 *_tmpc = malloc(sizeof(struct ast_category));
00481 if (!*_tmpc) {
00482 ast_destroy(tmp);
00483 ast_log(LOG_WARNING,
00484 "Out of memory, line %d\n", lineno);
00485 return -1;
00486 }
00487 memset(*_tmpc, 0, sizeof(struct ast_category));
00488 strncpy((*_tmpc)->name, cur+1, sizeof((*_tmpc)->name) - 1);
00489 (*_tmpc)->root = NULL;
00490 #ifdef PRESERVE_COMMENTS
00491 (*_tmpc)->precomments = acs->root;
00492 (*_tmpc)->sameline = com;
00493 #endif
00494 if (!tmp->prev)
00495 tmp->root = *_tmpc;
00496 else
00497 tmp->prev->next = *_tmpc;
00498
00499 tmp->prev = *_tmpc;
00500 #ifdef PRESERVE_COMMENTS
00501 acs->root = NULL;
00502 acs->prev = NULL;
00503 #endif
00504 *_last = NULL;
00505 } else {
00506 ast_log(LOG_WARNING,
00507 "parse error: no closing ']', line %d of %s\n", lineno, configfile);
00508 }
00509 } else if (cur[0] == '#') {
00510
00511 cur++;
00512 c = cur;
00513 while(*c && (*c > 32)) c++;
00514 if (*c) {
00515 *c = '\0';
00516 c++;
00517
00518 while(*c && (*c < 33)) c++;
00519 if (!*c)
00520 c = NULL;
00521 } else
00522 c = NULL;
00523 if (!strcasecmp(cur, "include")) {
00524
00525 if (c) {
00526 while((*c == '<') || (*c == '>') || (*c == '\"')) c++;
00527
00528 cur = c;
00529 while (!ast_strlen_zero(cur)) {
00530 c = cur + strlen(cur) - 1;
00531 if ((*c == '>') || (*c == '<') || (*c == '\"'))
00532 *c = '\0';
00533 else
00534 break;
00535 }
00536
00537 if((c = strchr(cur,':'))) {
00538 *c = '\0';
00539 c++;
00540 arg = c;
00541 }
00542
00543 if (includelevel < MAX_INCLUDE_LEVEL) {
00544 if(arg && cur) {
00545 load_func = NULL;
00546 if(ast_cust_config_list)
00547 reg = get_ast_cust_config(cur);
00548 if(reg && reg->func)
00549 load_func = reg->func;
00550 if(load_func) {
00551 ast_log(LOG_NOTICE,"External Include '%s' via '%s' config engine\n",arg,cur);
00552 load_func(arg,tmp, _tmpc, _last, includelevel
00553 #ifdef PRESERVE_COMMENTS
00554 ,&acs
00555 #endif
00556 );
00557 }
00558 else
00559 ast_log(LOG_WARNING,"Cant Find Registered Config Engine [%s] for [%s]\n",cur,arg);
00560 }
00561 else {
00562 __ast_load(cur, tmp, _tmpc, _last, includelevel + 1
00563 #ifdef PRESERVE_COMMENTS
00564 ,acs
00565 #endif
00566 );
00567 }
00568 } else
00569 ast_log(LOG_WARNING, "Maximum Include level (%d) exceeded\n", includelevel);
00570 } else
00571 ast_log(LOG_WARNING, "Directive '#include' needs an argument (filename) at line %d of %s\n", lineno, configfile);
00572
00573 }
00574 else
00575 ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile);
00576 } else {
00577
00578 if (!*_tmpc) {
00579 ast_log(LOG_WARNING,
00580 "parse error: No category context for line %d of %s\n", lineno, configfile);
00581 ast_destroy(tmp);
00582 return -1;
00583 }
00584 c = strchr(cur, '=');
00585 if (c) {
00586 *c = 0;
00587 c++;
00588
00589 if (*c== '>') {
00590 object = 1;
00591 c++;
00592 } else
00593 object = 0;
00594 v = malloc(sizeof(struct ast_variable));
00595 if (v) {
00596 memset(v, 0, sizeof(struct ast_variable));
00597 v->next = NULL;
00598 v->name = strdup(strip(cur));
00599 v->value = strdup(strip(c));
00600 v->lineno = lineno;
00601 v->object = object;
00602
00603 #ifdef PRESERVE_COMMENTS
00604 v->precomments = acs->root;
00605 v->sameline = com;
00606 acs->prev = NULL;
00607 acs->root = NULL;
00608 #endif
00609 v->blanklines = 0;
00610 if (*_last)
00611 (*_last)->next = v;
00612 else
00613 (*_tmpc)->root = v;
00614 *_last = v;
00615 } else {
00616 ast_destroy(tmp);
00617 ast_log(LOG_WARNING, "Out of memory, line %d\n", lineno);
00618 return -1;
00619 }
00620 } else {
00621 ast_log(LOG_WARNING, "No '=' (equal sign) in line %d of %s\n", lineno, configfile);
00622 }
00623
00624 }
00625 } else {
00626
00627 #ifdef PRESERVE_COMMENTS
00628 if (com) {
00629 if (acs->prev)
00630 acs->prev->next = com;
00631 else
00632 acs->root = com;
00633 acs->prev = com;
00634 } else {
00635 if (*_last)
00636 (*_last)->blanklines++;
00637 }
00638 #endif
00639 }
00640 return 0;
00641 }
00642
00643 #ifdef PRESERVE_COMMENTS
00644 static void dump_comments(FILE *f, struct ast_comment *comment)
00645 {
00646 while (comment) {
00647 fprintf(f, ";%s", comment->cmt);
00648 comment = comment->next;
00649 }
00650 }
00651 #endif
00652
00653 int ast_save(char *configfile, struct ast_config *cfg, char *generator)
00654 {
00655 FILE *f;
00656 char fn[256];
00657 char date[256]="";
00658 time_t t;
00659 struct ast_variable *var;
00660 struct ast_category *cat;
00661 int blanklines = 0;
00662 if (configfile[0] == '/') {
00663 strncpy(fn, configfile, sizeof(fn)-1);
00664 } else {
00665 snprintf(fn, sizeof(fn), "%s/%s", AST_CONFIG_DIR, configfile);
00666 }
00667 time(&t);
00668 strncpy(date, ctime(&t), sizeof(date) - 1);
00669 if ((f = fopen(fn, "w"))) {
00670 if ((option_verbose > 1) && !option_debug)
00671 ast_verbose( VERBOSE_PREFIX_2 "Saving '%s': ", fn);
00672 fprintf(f, ";!\n");
00673 fprintf(f, ";! Automatically generated configuration file\n");
00674 fprintf(f, ";! Filename: %s (%s)\n", configfile, fn);
00675 fprintf(f, ";! Generator: %s\n", generator);
00676 fprintf(f, ";! Creation Date: %s", date);
00677 fprintf(f, ";!\n");
00678 cat = cfg->root;
00679 while(cat) {
00680 #ifdef PRESERVE_COMMENTS
00681
00682 dump_comments(f, cat->precomments);
00683 #endif
00684
00685 #ifdef PRESERVE_COMMENTS
00686 if (cat->sameline)
00687 fprintf(f, "[%s] ; %s\n", cat->name, cat->sameline->cmt);
00688 else
00689 #endif
00690 fprintf(f, "[%s]\n", cat->name);
00691 var = cat->root;
00692 while(var) {
00693 #ifdef PRESERVE_COMMENTS
00694 dump_comments(f, var->precomments);
00695 #endif
00696 if (var->sameline)
00697 fprintf(f, "%s %s %s ; %s\n", var->name, (var->object ? "=>" : "="), var->value, var->sameline->cmt);
00698 else
00699 fprintf(f, "%s %s %s\n", var->name, (var->object ? "=>" : "="), var->value);
00700 if (var->blanklines) {
00701 blanklines = var->blanklines;
00702 while (blanklines) {
00703 fprintf(f, "\n");
00704 blanklines--;
00705 }
00706 }
00707
00708 var = var->next;
00709 }
00710 #if 0
00711
00712 fprintf(f, "\n");
00713 #endif
00714 cat = cat->next;
00715 }
00716 #ifdef PRESERVE_COMMENTS
00717 dump_comments(f, cfg->trailingcomments);
00718 #endif
00719 } else {
00720 if (option_debug)
00721 printf("Unable to open for writing: %s\n", fn);
00722 else if (option_verbose > 1)
00723 printf( "Unable to write (%s)", strerror(errno));
00724 return -1;
00725 }
00726 fclose(f);
00727 return 0;
00728 }
00729
00730 static struct ast_config *__ast_load(char *configfile, struct ast_config *tmp, struct ast_category **_tmpc, struct ast_variable **_last, int includelevel
00731 #ifdef PRESERVE_COMMENTS
00732 , struct ast_comment_struct *acs
00733 #endif
00734 )
00735 {
00736 char fn[256];
00737 char buf[8192];
00738 FILE *f;
00739 int lineno=0;
00740 int master=0;
00741 struct ast_config_reg *reg=NULL;
00742 struct ast_config *(*load_func)(char *, struct ast_config *,struct ast_category **,struct ast_variable **,int
00743 #ifdef PRESERVE_COMMENTS
00744 ,struct ast_comment_struct *
00745 #endif
00746 );
00747
00748 load_func=NULL;
00749 if (strcmp(configfile,config_conf_file) && strcmp(configfile,"asterisk.conf") && ast_cust_config_list) {
00750 if (global_load_func) {
00751 load_func = global_load_func;
00752 } else {
00753 reg = get_ast_cust_config_keyword(configfile);
00754 if (reg && reg->func) {
00755 load_func = reg->func;
00756 } else {
00757 reg = get_ast_cust_config_keyword("global");
00758 if (reg && reg->func)
00759 global_load_func = load_func = reg->func;
00760 }
00761 }
00762
00763 if (load_func) {
00764 ast_log(LOG_NOTICE,"Loading Config %s via %s engine\n",configfile,reg && reg->name ? reg->name : "global");
00765 tmp = load_func(configfile,tmp, _tmpc, _last, includelevel
00766 #ifdef PRESERVE_COMMENTS
00767 ,&acs
00768 #endif
00769 );
00770
00771 if (tmp)
00772 return tmp;
00773 }
00774 }
00775
00776 if (configfile[0] == '/') {
00777 strncpy(fn, configfile, sizeof(fn)-1);
00778 } else {
00779 snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, configfile);
00780 }
00781 if ((option_verbose > 1) && !option_debug) {
00782 ast_verbose( VERBOSE_PREFIX_2 "Parsing '%s': ", fn);
00783 fflush(stdout);
00784 }
00785 if ((f = fopen(fn, "r"))) {
00786 if (option_debug)
00787 ast_log(LOG_DEBUG, "Parsing %s\n", fn);
00788 else if (option_verbose > 1)
00789 ast_verbose( "Found\n");
00790 if (!tmp) {
00791 tmp = malloc(sizeof(struct ast_config));
00792 if (tmp)
00793 memset(tmp, 0, sizeof(struct ast_config));
00794
00795 master = 1;
00796 }
00797 if (!tmp) {
00798 ast_log(LOG_WARNING, "Out of memory\n");
00799 fclose(f);
00800 return NULL;
00801 }
00802 while(!feof(f)) {
00803 lineno++;
00804 if (fgets(buf, sizeof(buf), f)) {
00805 if (cfg_process(tmp, _tmpc, _last, buf, lineno, configfile, includelevel
00806 #ifdef PRESERVE_COMMENTS
00807 , acs
00808 #endif
00809 )) {
00810 fclose(f);
00811 return NULL;
00812 }
00813 }
00814 }
00815 fclose(f);
00816 } else {
00817 if (option_debug)
00818 ast_log(LOG_DEBUG, "No file to parse: %s\n", fn);
00819 else if (option_verbose > 1)
00820 ast_verbose( "Not found (%s)\n", strerror(errno));
00821 }
00822 #ifdef PRESERVE_COMMENTS
00823 if (master) {
00824
00825 tmp->trailingcomments = acs->root;
00826 acs->root = NULL;
00827 acs->prev = NULL;
00828 }
00829 #endif
00830 return tmp;
00831 }
00832
00833 struct ast_config_reg *get_ast_cust_config_keyword(char *name)
00834 {
00835 struct ast_config_reg *reg,*ret=NULL;
00836 int x=0;
00837 ast_mutex_lock(&ast_cust_config_lock);
00838 for (reg=ast_cust_config_list;reg && !ret;reg=reg->next) {
00839 for (x=0;x<reg->keycount && !ret ;x++) {
00840 if (!strcmp(reg->keywords[x],name))
00841 ret=reg;
00842 }
00843 }
00844 ast_mutex_unlock(&ast_cust_config_lock);
00845 return ret;
00846 }
00847
00848 struct ast_config_reg *get_ast_cust_config(char *name)
00849 {
00850 struct ast_config_reg *ptr=NULL;
00851 ast_mutex_lock(&ast_cust_config_lock);
00852 for (ptr=ast_cust_config_list;ptr;ptr=ptr->next) {
00853 if (!strcmp(name,ptr->name))
00854 break;
00855 }
00856 ast_mutex_unlock(&ast_cust_config_lock);
00857 return ptr;
00858 }
00859
00860 void ast_config_destroy_all(void)
00861 {
00862 struct ast_config_reg *key;
00863 ast_mutex_lock(&ast_cust_config_lock);
00864 for (key=ast_cust_config_list;key;key=key->next) {
00865 ast_config_deregister(key);
00866 }
00867 ast_cust_config_list = NULL;
00868 ast_mutex_unlock(&ast_cust_config_lock);
00869 }
00870
00871 struct ast_config_reg *get_config_registrations(void)
00872 {
00873 return ast_cust_config_list;
00874 }
00875
00876 int ast_config_register(struct ast_config_reg *new)
00877 {
00878 struct ast_config_reg *ptr;
00879 ast_mutex_lock(&ast_cust_config_lock);
00880 new->keycount = 0;
00881 if (!ast_cust_config_list) {
00882 ast_cust_config_list = new;
00883 } else {
00884 for(ptr=ast_cust_config_list;ptr->next;ptr=ptr->next);
00885 ptr->next = new;
00886 }
00887 ast_mutex_unlock(&ast_cust_config_lock);
00888 ast_log(LOG_NOTICE,"Registered Config Engine %s\n",new->name);
00889 return 1;
00890 }
00891
00892 int ast_config_deregister(struct ast_config_reg *del)
00893 {
00894 struct ast_config_reg *ptr=NULL,*last=NULL;
00895 ast_mutex_lock(&ast_cust_config_lock);
00896 for (ptr=ast_cust_config_list;ptr;ptr=ptr->next) {
00897 if (ptr == del) {
00898 if (last && ptr->next) {
00899 last->next = ptr->next;
00900 } else if (last && ! ptr->next) {
00901 last->next = NULL;
00902 } else if (!last && ptr->next) {
00903 ast_cust_config_list = ptr->next;
00904 } else if (!last && !ptr->next) {
00905 ast_cust_config_list = NULL;
00906 }
00907 }
00908 last = ptr;
00909 }
00910 ast_mutex_unlock(&ast_cust_config_lock);
00911 return 0;
00912 }
00913
00914 int ast_cust_config_active(void) {
00915 return (ast_cust_config >0) ? 1 : 0;
00916 }
00917
00918 struct ast_config *ast_load(char *configfile)
00919 {
00920 struct ast_category *tmpc=NULL;
00921 struct ast_variable *last = NULL;
00922
00923
00924 #ifdef PRESERVE_COMMENTS
00925 struct ast_comment_struct acs = { NULL, NULL };
00926 #endif
00927
00928
00929 return __ast_load(configfile, NULL, &tmpc, &last, 0
00930 #ifdef PRESERVE_COMMENTS
00931 ,&acs
00932 #endif
00933 );
00934 }
00935
00936 char *ast_category_browse(struct ast_config *config, char *prev)
00937 {
00938 struct ast_category *cat;
00939 if (!prev) {
00940 if (config->root)
00941 return config->root->name;
00942 else
00943 return NULL;
00944 }
00945 cat = config->root;
00946 while(cat) {
00947 if (cat->name == prev) {
00948 if (cat->next)
00949 return cat->next->name;
00950 else
00951 return NULL;
00952 }
00953 cat = cat->next;
00954 }
00955 cat = config->root;
00956 while(cat) {
00957 if (!strcasecmp(cat->name, prev)) {
00958 if (cat->next)
00959 return cat->next->name;
00960 else
00961 return NULL;
00962 }
00963 cat = cat->next;
00964 }
00965 return NULL;
00966 }
00967
00968
00969 struct ast_config *ast_new_config(void)
00970 {
00971 struct ast_config *config;
00972 config = malloc(sizeof(struct ast_config));
00973 memset(config,0,sizeof(struct ast_config));
00974 return config;
00975 }
00976
00977
00978
00979 struct ast_category *ast_new_category(char *name)
00980 {
00981 struct ast_category *category;
00982 category = malloc(sizeof(struct ast_category));
00983 if (category) {
00984 memset(category,0,sizeof(struct ast_category));
00985 strncpy(category->name,name,sizeof(category->name) - 1);
00986 }
00987 return category;
00988 }
00989
00990
00991 struct ast_variable *ast_new_variable(char *name, char *value)
00992 {
00993 struct ast_variable *variable;
00994 variable = malloc(sizeof(struct ast_variable));
00995 if (variable) {
00996 memset(variable,0,sizeof(struct ast_variable));
00997 variable->object=0;
00998 variable->name = malloc(strlen(name)+1);
00999 if (variable->name) {
01000 strcpy(variable->name,name);
01001 variable->value = malloc(strlen(value)+1);
01002 if (variable->value) {
01003 strcpy(variable->value,value);
01004 } else {
01005 free(variable->name);
01006 variable->name = NULL;
01007 }
01008 }
01009 }
01010 if (!variable->value) {
01011 free(variable);
01012 variable = NULL;
01013 }
01014
01015 return variable;
01016 }
01017
01018 int ast_cust_config_register(struct ast_config_reg *new)
01019 {
01020 ast_config_register(new);
01021 read_ast_cust_config();
01022 return 1;
01023 }
01024 int ast_cust_config_deregister(struct ast_config_reg *new)
01025 {
01026 ast_config_deregister(new);
01027 read_ast_cust_config();
01028 return 1;
01029 }
01030
01031 static void clear_cust_keywords(void)
01032 {
01033 struct ast_config_reg *key;
01034 int x;
01035 ast_mutex_lock(&ast_cust_config_lock);
01036 for (key=get_config_registrations();key;key=key->next) {
01037 for (x=0;x<key->keycount;x++) {
01038 key->keywords[x][0] = '\0';
01039 }
01040 key->keycount=0;
01041 }
01042 ast_mutex_unlock(&ast_cust_config_lock);
01043 }
01044
01045 static int config_command(int fd, int argc, char **argv)
01046 {
01047 struct ast_config_reg *key;
01048 int x;
01049
01050 ast_cli(fd,"\n\n");
01051 ast_mutex_lock(&ast_cust_config_lock);
01052 for (key=get_config_registrations();key;key=key->next) {
01053 ast_cli(fd,"\nConfig Engine: %s\n",key->name);
01054 for (x=0;x<key->keycount;x++)
01055 ast_cli(fd,"===>%s\n",key->keywords[x]);
01056 }
01057 ast_mutex_unlock(&ast_cust_config_lock);
01058 ast_cli(fd,"\n\n");
01059
01060 return 0;
01061 }
01062
01063 static struct ast_cli_entry config_command_struct = {
01064 { "show","config","handles", NULL }, config_command,
01065 "Show Config Handles", NULL };
01066
01067 int register_config_cli()
01068 {
01069 return ast_cli_register(&config_command_struct);
01070 }
01071
01072 int read_ast_cust_config(void)
01073 {
01074 char *cfg = config_conf_file;
01075 struct ast_config *config;
01076 struct ast_variable *v;
01077 struct ast_config_reg *ptr;
01078 struct ast_config_reg *test = NULL;
01079
01080 clear_cust_keywords();
01081 config = ast_load(cfg);
01082 if (config) {
01083 for (v = ast_variable_browse(config,"settings");v;v=v->next) {
01084
01085 ptr = get_ast_cust_config(v->value);
01086 if (ptr) {
01087 if (ptr->keycount >= CONFIG_KEYWORD_ARRAYLEN) {
01088 ast_log(LOG_WARNING,"Max Number of Bindings exceeded for %s->%s %d/%d\n",v->name,v->value,ptr->keycount,CONFIG_KEYWORD_ARRAYLEN);
01089 } else {
01090 if (strcmp(v->name,config_conf_file) && strcmp(v->name,"asterisk.conf")) {
01091 if (!(test = get_ast_cust_config_keyword(v->name))) {
01092 ast_log(LOG_NOTICE,"Binding: %s to %s\n",v->name,v->value);
01093 strncpy(ptr->keywords[ptr->keycount],v->name,sizeof(ptr->keywords[ptr->keycount]) - 1);
01094 ptr->keywords[ptr->keycount][sizeof(ptr->keywords[ptr->keycount])-1] = '\0';
01095 ptr->keycount++;
01096 }
01097 } else {
01098 ast_log(LOG_WARNING,"Cannot bind %s, Permission Denied\n",v->name);
01099 }
01100 }
01101 }
01102 }
01103
01104 ast_destroy(config);
01105 }
01106
01107 return 0;
01108 }