Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

config.c

Go to the documentation of this file.
00001 /* 00002 * Asterisk -- A telephony toolkit for Linux. 00003 * 00004 * Configuration File Parser 00005 * 00006 * Copyright (C) 1999, Mark Spencer 00007 * 00008 * Mark Spencer <markster@linux-support.net> 00009 * 00010 * This program is free software, distributed under the terms of 00011 * the GNU General Public License 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 /* Strip off trailing whitespace, returns, etc */ 00046 while (!ast_strlen_zero(buf) && (buf[strlen(buf)-1]<33)) 00047 buf[strlen(buf)-1] = '\0'; 00048 start = buf; 00049 /* Strip off leading whitespace, returns, etc */ 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 /* Determine if this is a true value */ 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 /* Determine if this is a false value */ 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 /* Get the last one that looks like it */ 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 /* Unlink from original position */ 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 /* Unlink it */ 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 /* Put us at the end */ 00327 pcat = config->root; 00328 while(pcat->next) 00329 pcat = pcat->next; 00330 pcat->next = cat; 00331 } else { 00332 /* We're the first one */ 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 /* Get the last one that looks like it */ 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 /* Unlink from original position */ 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 /* Memset the header */ 00422 memset(c, 0, sizeof(struct ast_comment)); 00423 /* Copy the rest */ 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 /* Strip off lines using ; as comment */ 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 /* Actually parse the entry */ 00475 if (cur[0] == '[') { 00476 /* A category header */ 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 /* A directive */ 00511 cur++; 00512 c = cur; 00513 while(*c && (*c > 32)) c++; 00514 if (*c) { 00515 *c = '\0'; 00516 c++; 00517 /* Find real argument */ 00518 while(*c && (*c < 33)) c++; 00519 if (!*c) 00520 c = NULL; 00521 } else 00522 c = NULL; 00523 if (!strcasecmp(cur, "include")) { 00524 /* A #include */ 00525 if (c) { 00526 while((*c == '<') || (*c == '>') || (*c == '\"')) c++; 00527 /* Get rid of leading mess */ 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 /* Strip off leading and trailing "'s and <>'s */ 00573 } 00574 else 00575 ast_log(LOG_WARNING, "Unknown directive '%s' at line %d of %s\n", cur, lineno, configfile); 00576 } else { 00577 /* Just a line (variable = value) */ 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 /* Ignore > in => */ 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 /* Put and reset comments */ 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 /* store any comments if there are any */ 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 /* Dump any precomments */ 00682 dump_comments(f, cat->precomments); 00683 #endif 00684 /* Dump section with any appropriate comment */ 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 /* Put an empty line */ 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 /* Keep trailing comments */ 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 }

Generated on Fri Sep 24 21:03:46 2004 for Asterisk by doxygen 1.3.8