Main Page | Alphabetical List | Data Structures | Directories | 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 Sat Nov 25 19:09:34 2006 for Asterisk by  doxygen 1.4.2