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

cfg.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * cfg.c - configuration file handling
00059  *
00060  * Lars Wirzenius
00061  */
00062 
00063 
00064 #include "gwlib/gwlib.h"
00065 
00066 /* for include dir */
00067 #include <sys/types.h>
00068 #include <sys/stat.h>
00069 #include <unistd.h>
00070 #include <dirent.h>
00071 
00072 struct CfgGroup {
00073     Octstr *name;
00074     Dict *vars;
00075     Octstr *configfile; 
00076     long line; 
00077 };
00078 
00079 
00080 static CfgGroup *create_group(void)
00081 {
00082     CfgGroup *grp;
00083     
00084     grp = gw_malloc(sizeof(*grp));
00085     grp->name = NULL;
00086     grp->vars = dict_create(64, octstr_destroy_item);
00087     grp->configfile = NULL; 
00088     grp->line = 0; 
00089     return grp;
00090 }
00091 
00092 static void destroy_group(void *arg)
00093 {
00094     CfgGroup *grp;
00095     
00096     if (arg != NULL) {
00097     grp = arg;
00098     octstr_destroy(grp->name);
00099     octstr_destroy(grp->configfile); 
00100     dict_destroy(grp->vars);
00101     gw_free(grp);
00102     }
00103 }
00104 
00105 
00106 struct CfgLoc { 
00107     Octstr *filename; 
00108     long line_no; 
00109     Octstr *line; 
00110 }; 
00111 
00112 
00113 static CfgLoc *cfgloc_create(Octstr *filename) 
00114 { 
00115     CfgLoc *cfgloc; 
00116      
00117     cfgloc = gw_malloc(sizeof(*cfgloc)); 
00118     cfgloc->filename = octstr_duplicate(filename); 
00119     cfgloc->line_no = 0; 
00120     cfgloc->line = NULL; 
00121     return cfgloc; 
00122 } 
00123  
00124  
00125 static void cfgloc_destroy(CfgLoc *cfgloc) 
00126 { 
00127     if (cfgloc != NULL) { 
00128     octstr_destroy(cfgloc->filename); 
00129     octstr_destroy(cfgloc->line); 
00130     gw_free(cfgloc); 
00131     } 
00132 } 
00133 
00134  
00135 static void destroy_group_list(void *arg)
00136 {
00137     gwlist_destroy(arg, destroy_group);
00138 }
00139 
00140 
00141 static void set_group_name(CfgGroup *grp, Octstr *name)
00142 {
00143     octstr_destroy(grp->name);
00144     grp->name = octstr_duplicate(name);
00145 }
00146 
00147 
00148 struct Cfg {
00149     Octstr *filename;
00150     Dict *single_groups;
00151     Dict *multi_groups;
00152 };
00153 
00154 
00155 /********************************************************************
00156  * Section providing hooks to external modules to apply their specific
00157  * is_allowed_in_group() and is_single_group() with their own
00158  * foobar-cfg.def.
00159  */
00160 
00161 static List *allowed_hooks;
00162 static List *single_hooks;
00163 
00164 static int core_is_allowed_in_group(Octstr *group, Octstr *variable)
00165 {
00166     Octstr *groupstr;
00167     
00168     groupstr = octstr_imm("group");
00169 
00170     #define OCTSTR(name) \
00171         if (octstr_compare(octstr_imm(#name), variable) == 0) \
00172         return 1;
00173     #define SINGLE_GROUP(name, fields) \
00174         if (octstr_compare(octstr_imm(#name), group) == 0) { \
00175         if (octstr_compare(groupstr, variable) == 0) \
00176         return 1; \
00177         fields \
00178         return 0; \
00179     }
00180     #define MULTI_GROUP(name, fields) \
00181         if (octstr_compare(octstr_imm(#name), group) == 0) { \
00182         if (octstr_compare(groupstr, variable) == 0) \
00183         return 1; \
00184         fields \
00185         return 0; \
00186     }
00187     #include "cfg.def"
00188 
00189     /* unknown group identifier */
00190     return -1;
00191 }
00192 
00193 
00194 static int core_is_single_group(Octstr *query)
00195 {
00196     #define OCTSTR(name)
00197     #define SINGLE_GROUP(name, fields) \
00198         if (octstr_compare(octstr_imm(#name), query) == 0) \
00199         return 1;
00200     #define MULTI_GROUP(name, fields) \
00201         if (octstr_compare(octstr_imm(#name), query) == 0) \
00202         return 0;
00203     #include "cfg.def"
00204     return 0;
00205 }
00206 
00207 
00208 static int is_allowed_in_group(Octstr *group, Octstr *variable)
00209 {
00210     long i;
00211     int x, r = -1;
00212 
00213     for (i = 0; i < gwlist_len(allowed_hooks); ++i) {
00214         x = ((int(*)(Octstr *, Octstr *))
00215             gwlist_get(allowed_hooks, i))(group, variable);
00216         r = (x == -1 ? (r == -1 ? x : r) : (r == -1 ? x : r + x));
00217     }
00218 
00219     return r;
00220 }
00221 
00222 
00223 static int is_single_group(Octstr *query)
00224 {
00225     long i;
00226     int r = 0;
00227 
00228     for (i = 0; i < gwlist_len(single_hooks); ++i) {
00229         r += ((int(*)(Octstr *))
00230             gwlist_get(single_hooks, i))(query);
00231     }
00232 
00233     return (r > 0);
00234 }
00235 
00236 
00237 void cfg_add_hooks(void *allowed, void *single)
00238 {
00239     gwlist_append(allowed_hooks, allowed);
00240     gwlist_append(single_hooks, single);
00241 }
00242 
00243 
00244 static int add_group(Cfg *cfg, CfgGroup *grp)
00245 {
00246     Octstr *groupname;
00247     Octstr *name;
00248     List *names;
00249     List *list;
00250     
00251     groupname = cfg_get(grp, octstr_imm("group"));
00252     if (groupname == NULL) {
00253         error(0, "Group does not contain variable 'group'.");
00254         return -1;
00255     }
00256     set_group_name(grp, groupname);
00257 
00258     names = dict_keys(grp->vars);
00259 
00260     while ((name = gwlist_extract_first(names)) != NULL) {
00261         int a = is_allowed_in_group(groupname, name);
00262         switch (a) {
00263             case 0:
00264                 error(0, "Group '%s' may not contain field '%s'.",
00265                       octstr_get_cstr(groupname), octstr_get_cstr(name));
00266                 octstr_destroy(name);
00267                 octstr_destroy(groupname);
00268                 gwlist_destroy(names, octstr_destroy_item);
00269                 return -1;
00270                 break;
00271             case -1:
00272                 error(0, "Group '%s' is no valid group identifier.",
00273                       octstr_get_cstr(groupname));
00274                 octstr_destroy(name);
00275                 octstr_destroy(groupname);
00276                 gwlist_destroy(names, octstr_destroy_item);
00277                 return -1;
00278                 break;
00279             default:
00280                 octstr_destroy(name);
00281                 break;
00282         }
00283     }
00284     gwlist_destroy(names, NULL);
00285 
00286     if (is_single_group(groupname)) {
00287         dict_put(cfg->single_groups, groupname, grp);
00288     } else {
00289         list = dict_get(cfg->multi_groups, groupname);
00290         if (list == NULL) {
00291             list = gwlist_create();
00292             dict_put(cfg->multi_groups, groupname, list);
00293         }
00294         gwlist_append(list, grp);
00295     }
00296 
00297     octstr_destroy(groupname);
00298     return 0;
00299 }
00300 
00301 
00302 Cfg *cfg_create(Octstr *filename)
00303 {
00304     Cfg *cfg;
00305     
00306     cfg = gw_malloc(sizeof(*cfg));
00307     cfg->filename = octstr_duplicate(filename);
00308     cfg->single_groups = dict_create(64, destroy_group);
00309     cfg->multi_groups = dict_create(64, destroy_group_list);
00310 
00311     return cfg;
00312 }
00313 
00314 
00315 void cfg_destroy(Cfg *cfg)
00316 {
00317     if (cfg != NULL) {
00318         octstr_destroy(cfg->filename);
00319         dict_destroy(cfg->single_groups);
00320         dict_destroy(cfg->multi_groups);
00321         gw_free(cfg);
00322     }
00323 }
00324 
00325 
00326 static void parse_value(Octstr *value)
00327 {
00328     Octstr *temp;
00329     long len;
00330     int c;
00331     
00332     octstr_strip_blanks(value);
00333 
00334     len = octstr_len(value);
00335     if (octstr_get_char(value, 0) != '"' || 
00336         octstr_get_char(value, len - 1) != '"')
00337     return;
00338 
00339     octstr_delete(value, len - 1, 1);
00340     octstr_delete(value, 0, 1);
00341 
00342     temp = octstr_duplicate(value);
00343     octstr_truncate(value, 0);
00344     
00345     while (octstr_len(temp) > 0) {
00346     c = octstr_get_char(temp, 0);
00347     octstr_delete(temp, 0, 1);
00348     
00349         if (c != '\\' || octstr_len(temp) == 0)
00350         octstr_append_char(value, c);
00351     else {
00352         c = octstr_get_char(temp, 0);
00353         octstr_delete(temp, 0, 1);
00354 
00355         switch (c) {
00356             case '\\':
00357             case '"':
00358             octstr_append_char(value, c);
00359             break;
00360         
00361             default:
00362             octstr_append_char(value, '\\');
00363             octstr_append_char(value, c);
00364         break;
00365         }
00366     }
00367     }
00368     
00369     octstr_destroy(temp);
00370 }
00371 
00372 
00373 static List *expand_file(Octstr *file, int forward) 
00374 {
00375     Octstr *os;
00376     Octstr *line;
00377     List *lines; 
00378     List *expand; 
00379     long lineno; 
00380     CfgLoc *loc = NULL; 
00381  
00382     os = octstr_read_file(octstr_get_cstr(file)); 
00383     if (os == NULL) 
00384         return NULL; 
00385  
00386     lines = octstr_split(os, octstr_imm("\n")); 
00387     lineno = 0; 
00388     expand = gwlist_create(); 
00389               
00390     while ((line = gwlist_extract_first(lines)) != NULL) {
00391         if (loc == NULL) {
00392             ++lineno; 
00393             loc = cfgloc_create(file); 
00394             loc->line_no = lineno;
00395             loc->line = octstr_create("");
00396             if (forward) 
00397                 gwlist_append(expand, loc); 
00398             else 
00399                 gwlist_insert(expand, 0, loc);
00400         }
00401         /* check for escape and then add to existing loc */
00402         if (octstr_get_char(line, octstr_len(line) - 1) == '\\') {
00403             octstr_delete(line, octstr_len(line) - 1, 1);
00404             octstr_append(loc->line, line); 
00405             /* check for second escape */
00406             if (octstr_get_char(line, octstr_len(line) - 1) == '\\')
00407                 loc = NULL;
00408         } else {
00409             octstr_append(loc->line, line);
00410             loc = NULL;
00411         }
00412         octstr_destroy(line);
00413     } 
00414     
00415     /* 
00416      * add newline at each end of included files to avoid 
00417      * concatenating different groups by mistake
00418      */
00419     if (lineno > 0) {
00420         loc = cfgloc_create(file); 
00421         loc->line_no = lineno;
00422         loc->line = octstr_create("\n");
00423         if (forward) 
00424             gwlist_append(expand, loc); 
00425         else 
00426             gwlist_insert(expand, 0, loc); 
00427     }
00428          
00429     gwlist_destroy(lines, octstr_destroy_item); 
00430     octstr_destroy(os); 
00431  
00432     return expand; 
00433 } 
00434  
00435  
00436 int cfg_read(Cfg *cfg) 
00437 { 
00438     CfgLoc *loc; 
00439     CfgLoc *loc_inc; 
00440     List *lines;
00441     List *expand; 
00442     List *stack; 
00443     Octstr *name;
00444     Octstr *value;
00445     Octstr *filename; 
00446     CfgGroup *grp;
00447     long equals;
00448     long lineno;
00449     long error_lineno;
00450     
00451     loc = loc_inc = NULL;
00452 
00453     /* 
00454      * expand initial main config file and add it to the recursion 
00455      * stack to protect against cycling 
00456      */ 
00457     if ((lines = expand_file(cfg->filename, 1)) == NULL) { 
00458         panic(0, "Failed to load main configuration file `%s'. Aborting!", 
00459               octstr_get_cstr(cfg->filename)); 
00460     } 
00461     stack = gwlist_create(); 
00462     gwlist_insert(stack, 0, octstr_duplicate(cfg->filename)); 
00463 
00464     grp = NULL;
00465     lineno = 0;
00466     error_lineno = 0;
00467     while (error_lineno == 0 && (loc = gwlist_extract_first(lines)) != NULL) { 
00468         octstr_strip_blanks(loc->line); 
00469         if (octstr_len(loc->line) == 0) { 
00470             if (grp != NULL && add_group(cfg, grp) == -1) { 
00471                 error_lineno = loc->line_no; 
00472                 destroy_group(grp); 
00473             } 
00474             grp = NULL; 
00475         } else if (octstr_get_char(loc->line, 0) != '#') { 
00476             equals = octstr_search_char(loc->line, '=', 0); 
00477             if (equals == -1) { 
00478                 error(0, "An equals sign ('=') is missing on line %ld of file %s.", 
00479                       loc->line_no, octstr_get_cstr(loc->filename)); 
00480                 error_lineno = loc->line_no; 
00481             } else  
00482              
00483             /* 
00484              * check for special config directives, like include or conditional 
00485              * directives here 
00486              */ 
00487             if (octstr_search(loc->line, octstr_imm("include"), 0) != -1) { 
00488                 filename = octstr_copy(loc->line, equals + 1, octstr_len(loc->line)); 
00489                 parse_value(filename); 
00490  
00491                 /* check if we are cycling */ 
00492                 if (gwlist_search(stack, filename, octstr_item_match) != NULL) { 
00493                     panic(0, "Recursive include for config file `%s' detected " 
00494                              "(on line %ld of file %s).", 
00495                           octstr_get_cstr(filename), loc->line_no,  
00496                           octstr_get_cstr(loc->filename)); 
00497                 } else {     
00498                     List *files = gwlist_create();
00499                     Octstr *file;
00500                     struct stat filestat;
00501 
00502                     /* check if included file is a directory */
00503                     lstat(octstr_get_cstr(filename), &filestat);
00504 
00505                     /* 
00506                      * is a directory, create a list with files of
00507                      * this directory and load all as part of the
00508                      * whole configuration.
00509                      */
00510                     if (S_ISDIR(filestat.st_mode)) {
00511                         DIR *dh;
00512                         struct dirent *diritem;
00513 
00514                         debug("gwlib.cfg", 0, "Loading include dir `%s' "
00515                               "(on line %ld of file %s).",  
00516                               octstr_get_cstr(filename), loc->line_no,  
00517                               octstr_get_cstr(loc->filename)); 
00518 
00519                         dh = opendir(octstr_get_cstr(filename));
00520                         while ((diritem = readdir(dh))) {
00521                             Octstr *fileitem;
00522 
00523                             fileitem = octstr_duplicate(filename);
00524                             octstr_append_cstr(fileitem, "/");
00525                             octstr_append_cstr(fileitem, diritem->d_name);
00526 
00527                             lstat(octstr_get_cstr(fileitem), &filestat);
00528                             if (!S_ISDIR(filestat.st_mode)) {
00529                                 gwlist_insert(files, 0, fileitem);
00530                             } else {
00531                                 octstr_destroy(fileitem);
00532                             }
00533                         }
00534                         closedir(dh);
00535                     } 
00536             
00537                     /* is a file, create a list with it */
00538                     else {
00539                         gwlist_insert(files, 0, octstr_duplicate(filename));
00540                     }
00541 
00542                     /* include files */
00543                     while ((file = gwlist_extract_first(files)) != NULL) {
00544 
00545                         gwlist_insert(stack, 0, octstr_duplicate(file)); 
00546                         debug("gwlib.cfg", 0, "Loading include file `%s' (on line %ld of file %s).",  
00547                               octstr_get_cstr(file), loc->line_no,  
00548                               octstr_get_cstr(loc->filename)); 
00549 
00550                         /*  
00551                          * expand the given include file and add it to the current 
00552                          * processed main while loop 
00553                          */ 
00554                         if ((expand = expand_file(file, 0)) != NULL) {
00555                             while ((loc_inc = gwlist_extract_first(expand)) != NULL) 
00556                                 gwlist_insert(lines, 0, loc_inc); 
00557                         } else { 
00558                             panic(0, "Failed to load whole configuration. Aborting!"); 
00559                         } 
00560                  
00561                         gwlist_destroy(expand, NULL); 
00562                         cfgloc_destroy(loc_inc);
00563                         octstr_destroy(file);
00564                     }
00565                     gwlist_destroy(files, octstr_destroy_item);
00566                 } 
00567                 octstr_destroy(filename); 
00568             }  
00569              
00570             /* 
00571              * this is a "normal" line, so process it accodingly 
00572              */ 
00573             else  { 
00574                 name = octstr_copy(loc->line, 0, equals); 
00575                 octstr_strip_blanks(name); 
00576                 value = octstr_copy(loc->line, equals + 1, octstr_len(loc->line)); 
00577                 parse_value(value); 
00578  
00579                 if (grp == NULL)
00580                     grp = create_group(); 
00581                  
00582                 if (grp->configfile != NULL) {
00583                     octstr_destroy(grp->configfile); 
00584                     grp->configfile = NULL;
00585                 }
00586                 grp->configfile = octstr_duplicate(cfg->filename); 
00587 
00588                 cfg_set(grp, name, value); 
00589                 octstr_destroy(name); 
00590                 octstr_destroy(value); 
00591             } 
00592         } 
00593 
00594         cfgloc_destroy(loc); 
00595     }
00596 
00597     if (grp != NULL && add_group(cfg, grp) == -1) {
00598         error_lineno = 1; 
00599         destroy_group(grp); 
00600     }
00601 
00602     gwlist_destroy(lines, NULL); 
00603     gwlist_destroy(stack, octstr_destroy_item); 
00604 
00605     if (error_lineno != 0) {
00606         error(0, "Error found on line %ld of file `%s'.",  
00607               error_lineno, octstr_get_cstr(cfg->filename)); 
00608         return -1; 
00609     }
00610 
00611     return 0;
00612 }
00613 
00614 
00615 CfgGroup *cfg_get_single_group(Cfg *cfg, Octstr *name)
00616 {
00617     return dict_get(cfg->single_groups, name);
00618 }
00619 
00620 
00621 List *cfg_get_multi_group(Cfg *cfg, Octstr *name)
00622 {
00623     List *list, *copy;
00624     long i;
00625     
00626     list = dict_get(cfg->multi_groups, name);
00627     if (list == NULL)
00628         return NULL;
00629 
00630     copy = gwlist_create();
00631     for (i = 0; i < gwlist_len(list); ++i)
00632         gwlist_append(copy, gwlist_get(list, i));
00633     return copy;
00634 }
00635 
00636 
00637 Octstr *cfg_get_group_name(CfgGroup *grp)
00638 {
00639     return octstr_duplicate(grp->name);
00640 }
00641 
00642 Octstr *cfg_get_configfile(CfgGroup *grp)
00643 {
00644     return octstr_duplicate(grp->configfile);
00645 }
00646 
00647 
00648 Octstr *cfg_get_real(CfgGroup *grp, Octstr *varname, const char *file, 
00649                      long line, const char *func)
00650 {
00651     Octstr *os;
00652 
00653     if(grp == NULL) 
00654         panic(0, "Trying to fetch variable `%s' in non-existing group",
00655           octstr_get_cstr(varname));
00656 
00657     if (grp->name != NULL && !is_allowed_in_group(grp->name, varname))
00658         panic(0, "Trying to fetch variable `%s' in group `%s', not allowed.",
00659           octstr_get_cstr(varname), octstr_get_cstr(grp->name));
00660 
00661     os = dict_get(grp->vars, varname);
00662     if (os == NULL)
00663         return NULL;
00664     return gw_claim_area_for(octstr_duplicate(os), file, line, func);
00665 }
00666 
00667 
00668 int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
00669 {
00670     Octstr *os;
00671     int ret;
00672     
00673     os = cfg_get(grp, varname);
00674     if (os == NULL)
00675         return -1;
00676     if (octstr_parse_long(n, os, 0, 0) == -1)
00677         ret = -1;
00678     else
00679         ret = 0;
00680     octstr_destroy(os);
00681     return ret;
00682 }
00683 
00684 
00685 int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
00686 {
00687     Octstr *os;
00688 
00689     os = cfg_get(grp, varname);
00690     if (os == NULL) {
00691     *n = 0;
00692         return -1;
00693     }
00694     if (octstr_case_compare(os, octstr_imm("true")) == 0
00695     || octstr_case_compare(os, octstr_imm("yes")) == 0
00696     || octstr_case_compare(os, octstr_imm("on")) == 0
00697     || octstr_case_compare(os, octstr_imm("1")) == 0)
00698     {       
00699     *n = 1;
00700     } else if (octstr_case_compare(os, octstr_imm("false")) == 0
00701     || octstr_case_compare(os, octstr_imm("no")) == 0
00702     || octstr_case_compare(os, octstr_imm("off")) == 0
00703     || octstr_case_compare(os, octstr_imm("0")) == 0)
00704     {
00705     *n = 0;
00706     }
00707     else {
00708     *n = 1;
00709     warning(0, "bool variable set to strange value, assuming 'true'");
00710     }
00711     octstr_destroy(os);
00712     return 0;
00713 }
00714 
00715 
00716 List *cfg_get_list(CfgGroup *grp, Octstr *varname)
00717 {
00718     Octstr *os;
00719     List *list;
00720     
00721     os = cfg_get(grp, varname);
00722     if (os == NULL)
00723         return NULL;
00724 
00725     list = octstr_split_words(os);
00726     octstr_destroy(os);
00727     return list;
00728 }
00729 
00730 
00731 void cfg_set(CfgGroup *grp, Octstr *varname, Octstr *value)
00732 {
00733     dict_put(grp->vars, varname, octstr_duplicate(value));
00734 }
00735 
00736 
00737 void grp_dump(CfgGroup *grp)
00738 {
00739     List *names;
00740     Octstr *name;
00741     Octstr *value;
00742 
00743     if (grp->name == NULL)
00744     debug("gwlib.cfg", 0, "  dumping group (name not set):");
00745     else
00746     debug("gwlib.cfg", 0, "  dumping group (%s):",
00747           octstr_get_cstr(grp->name));
00748     names = dict_keys(grp->vars);
00749     while ((name = gwlist_extract_first(names)) != NULL) {
00750     value = cfg_get(grp, name);
00751     debug("gwlib.cfg", 0, "    <%s> = <%s>", 
00752           octstr_get_cstr(name),
00753           octstr_get_cstr(value));
00754         octstr_destroy(value);
00755         octstr_destroy(name);
00756     }
00757     gwlist_destroy(names, NULL);
00758 }
00759 
00760 
00761 void cfg_dump(Cfg *cfg)
00762 {
00763     CfgGroup *grp;
00764     List *list;
00765     List *names;
00766     Octstr *name;
00767 
00768     debug("gwlib.cfg", 0, "Dumping Cfg %p", (void *) cfg);
00769     debug("gwlib.cfg", 0, "  filename = <%s>", 
00770           octstr_get_cstr(cfg->filename));
00771 
00772     names = dict_keys(cfg->single_groups);
00773     while ((name = gwlist_extract_first(names)) != NULL) {
00774     grp = cfg_get_single_group(cfg, name);
00775     if (grp != NULL)
00776         grp_dump(grp);
00777         octstr_destroy(name);
00778     }
00779     gwlist_destroy(names, NULL);
00780 
00781     names = dict_keys(cfg->multi_groups);
00782     while ((name = gwlist_extract_first(names)) != NULL) {
00783     list = cfg_get_multi_group(cfg, name);
00784     while ((grp = gwlist_extract_first(list)) != NULL)
00785         grp_dump(grp);
00786     gwlist_destroy(list, NULL);
00787         octstr_destroy(name);
00788     }
00789     gwlist_destroy(names, NULL);
00790 
00791     debug("gwlib.cfg", 0, "Dump ends.");
00792 }
00793 
00794 
00795 void cfg_dump_all(void)
00796 {
00797     #define OCTSTR(name) \
00798         printf("%s = <please consult user doc>\n", #name);
00799     #define SINGLE_GROUP(name, fields) \
00800         printf("#\n#  Single Group\n#\n"); \
00801         printf("group = %s\n", #name); \
00802         fields; \
00803         printf("\n\n");
00804     #define MULTI_GROUP(name, fields) \
00805         printf("#\n#  Multi Group\n#\n"); \
00806         printf("group = %s\n", #name); \
00807         fields; \
00808         printf("\n\n");
00809     #include "cfg.def"
00810 }
00811 
00812 
00813 void cfg_init(void)
00814 {
00815     /* make sure we put our own core hooks into the lists */
00816     allowed_hooks = gwlist_create();
00817     single_hooks = gwlist_create();
00818 
00819     gwlist_append(allowed_hooks, &core_is_allowed_in_group);
00820     gwlist_append(single_hooks, &core_is_single_group);
00821 }
00822 
00823 
00824 void cfg_shutdown(void)
00825 {
00826     gwlist_destroy(allowed_hooks, NULL);
00827     gwlist_destroy(single_hooks, NULL);
00828     allowed_hooks = single_hooks = NULL;
00829 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.