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

Generated on Tue Aug 17 16:13:52 2004 for Asterisk by doxygen 1.3.8