cfg.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:16k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * cfg.c - configuration file handling
  3.  *
  4.  * Lars Wirzenius
  5.  */
  6. #include "gwlib/gwlib.h"
  7. /* for include dir */
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <unistd.h>
  11. #include <dirent.h>
  12. struct CfgGroup {
  13.     Octstr *name;
  14.     Dict *vars;
  15.     Octstr *configfile; 
  16.     long line; 
  17. };
  18. static CfgGroup *create_group(void)
  19. {
  20.     CfgGroup *grp;
  21.     
  22.     grp = gw_malloc(sizeof(*grp));
  23.     grp->name = NULL;
  24.     grp->vars = dict_create(64, octstr_destroy_item);
  25.     grp->configfile = NULL; 
  26.     grp->line = 0; 
  27.     return grp;
  28. }
  29. static void destroy_group(void *arg)
  30. {
  31.     CfgGroup *grp;
  32.     
  33.     if (arg != NULL) {
  34. grp = arg;
  35. octstr_destroy(grp->name);
  36. octstr_destroy(grp->configfile); 
  37. dict_destroy(grp->vars);
  38. gw_free(grp);
  39.     }
  40. }
  41. struct CfgLoc { 
  42.     Octstr *filename; 
  43.     long line_no; 
  44.     Octstr *line; 
  45. }; 
  46. static CfgLoc *cfgloc_create(Octstr *filename) 
  47.     CfgLoc *cfgloc; 
  48.      
  49.     cfgloc = gw_malloc(sizeof(*cfgloc)); 
  50.     cfgloc->filename = octstr_duplicate(filename); 
  51.     cfgloc->line_no = 0; 
  52.     cfgloc->line = NULL; 
  53.     return cfgloc; 
  54.  
  55.  
  56. static void cfgloc_destroy(CfgLoc *cfgloc) 
  57.     if (cfgloc != NULL) { 
  58. octstr_destroy(cfgloc->filename); 
  59. octstr_destroy(cfgloc->line); 
  60. gw_free(cfgloc); 
  61.     } 
  62.  
  63. static void destroy_group_list(void *arg)
  64. {
  65.     list_destroy(arg, destroy_group);
  66. }
  67. static void set_group_name(CfgGroup *grp, Octstr *name)
  68. {
  69.     octstr_destroy(grp->name);
  70.     grp->name = octstr_duplicate(name);
  71. }
  72. struct Cfg {
  73.     Octstr *filename;
  74.     Dict *single_groups;
  75.     Dict *multi_groups;
  76. };
  77. static int is_allowed_in_group(Octstr *group, Octstr *variable)
  78. {
  79.     Octstr *groupstr;
  80.     
  81.     groupstr = octstr_imm("group");
  82.     #define OCTSTR(name) 
  83.      if (octstr_compare(octstr_imm(#name), variable) == 0) 
  84.     return 1;
  85.     #define SINGLE_GROUP(name, fields) 
  86.      if (octstr_compare(octstr_imm(#name), group) == 0) { 
  87.     if (octstr_compare(groupstr, variable) == 0) 
  88. return 1; 
  89.     fields 
  90.     return 0; 
  91. }
  92.     #define MULTI_GROUP(name, fields) 
  93.      if (octstr_compare(octstr_imm(#name), group) == 0) { 
  94.     if (octstr_compare(groupstr, variable) == 0) 
  95. return 1; 
  96.     fields 
  97.     return 0; 
  98. }
  99.     #include "cfg.def"
  100.     return 0;
  101. }
  102. static int is_single_group(Octstr *query)
  103. {
  104.     #define OCTSTR(name)
  105.     #define SINGLE_GROUP(name, fields) 
  106.      if (octstr_compare(octstr_imm(#name), query) == 0) 
  107.     return 1;
  108.     #define MULTI_GROUP(name, fields) 
  109.      if (octstr_compare(octstr_imm(#name), query) == 0) 
  110.     return 0;
  111.     #include "cfg.def"
  112.     return 0;
  113. }
  114. static int add_group(Cfg *cfg, CfgGroup *grp)
  115. {
  116.     Octstr *groupname;
  117.     Octstr *name;
  118.     List *names;
  119.     List *list;
  120.     
  121.     groupname = cfg_get(grp, octstr_imm("group"));
  122.     if (groupname == NULL) {
  123. error(0, "Group does not contain variable 'group'.");
  124.      return -1;
  125.     }
  126.     set_group_name(grp, groupname);
  127.     names = dict_keys(grp->vars);
  128.     while ((name = list_extract_first(names)) != NULL) {
  129. if (!is_allowed_in_group(groupname, name)) {
  130.     error(0, "Group '%s' may not contain field '%s'.",
  131.   octstr_get_cstr(groupname), octstr_get_cstr(name));
  132.     octstr_destroy(name);
  133.     octstr_destroy(groupname);
  134.     list_destroy(names, octstr_destroy_item);
  135.     return -1;
  136. }
  137. octstr_destroy(name);
  138.     }
  139.     list_destroy(names, NULL);
  140.     if (is_single_group(groupname))
  141.      dict_put(cfg->single_groups, groupname, grp);
  142.     else {
  143. list = dict_get(cfg->multi_groups, groupname);
  144. if (list == NULL) {
  145.     list = list_create();
  146.     dict_put(cfg->multi_groups, groupname, list);
  147. }
  148.      list_append(list, grp);
  149.     }
  150.     octstr_destroy(groupname);
  151.     return 0;
  152. }
  153. Cfg *cfg_create(Octstr *filename)
  154. {
  155.     Cfg *cfg;
  156.     
  157.     cfg = gw_malloc(sizeof(*cfg));
  158.     cfg->filename = octstr_duplicate(filename);
  159.     cfg->single_groups = dict_create(64, destroy_group);
  160.     cfg->multi_groups = dict_create(64, destroy_group_list);
  161.     return cfg;
  162. }
  163. void cfg_destroy(Cfg *cfg)
  164. {
  165.     if (cfg != NULL) {
  166. octstr_destroy(cfg->filename);
  167. dict_destroy(cfg->single_groups);
  168. dict_destroy(cfg->multi_groups);
  169. gw_free(cfg);
  170.     }
  171. }
  172. static void parse_value(Octstr *value)
  173. {
  174.     Octstr *temp;
  175.     long len;
  176.     int c;
  177.     
  178.     octstr_strip_blanks(value);
  179.     len = octstr_len(value);
  180.     if (octstr_get_char(value, 0) != '"' || 
  181.         octstr_get_char(value, len - 1) != '"')
  182. return;
  183.     octstr_delete(value, len - 1, 1);
  184.     octstr_delete(value, 0, 1);
  185.     temp = octstr_duplicate(value);
  186.     octstr_truncate(value, 0);
  187.     
  188.     while (octstr_len(temp) > 0) {
  189. c = octstr_get_char(temp, 0);
  190. octstr_delete(temp, 0, 1);
  191.      if (c != '\' || octstr_len(temp) == 0)
  192.     octstr_append_char(value, c);
  193. else {
  194.     c = octstr_get_char(temp, 0);
  195.     octstr_delete(temp, 0, 1);
  196.     switch (c) {
  197.          case '\':
  198.          case '"':
  199.      octstr_append_char(value, c);
  200.      break;
  201.          default:
  202.      octstr_append_char(value, '\');
  203.      octstr_append_char(value, c);
  204. break;
  205.     }
  206. }
  207.     }
  208.     
  209.     octstr_destroy(temp);
  210. }
  211. static List *expand_file(Octstr *file, int forward) 
  212. {
  213.     Octstr *os;
  214.     Octstr *line;
  215.     List *lines; 
  216.     List *expand; 
  217.     long lineno; 
  218.     CfgLoc *loc; 
  219.  
  220.     os = octstr_read_file(octstr_get_cstr(file)); 
  221.     if (os == NULL) 
  222.      return NULL; 
  223.  
  224.     lines = octstr_split(os, octstr_imm("n")); 
  225.     lineno = 0; 
  226.     expand = list_create(); 
  227.               
  228.     while ((line = list_extract_first(lines)) != NULL) { 
  229.         ++lineno; 
  230.         loc = cfgloc_create(file); 
  231.         loc->line_no = lineno; 
  232.         loc->line = line; 
  233.         if (forward) 
  234.             list_append(expand, loc); 
  235.         else 
  236.             list_insert(expand, 0, loc); 
  237.     } 
  238.     
  239.     /* 
  240.      * add newline at each end of included files to avoid 
  241.      * concatenating different groups by mistake
  242.      */
  243.     if (lineno > 0) {
  244.         loc = cfgloc_create(file); 
  245.         loc->line_no = lineno;
  246.         loc->line = octstr_create("n");
  247.         if (forward) 
  248.             list_append(expand, loc); 
  249.         else 
  250.             list_insert(expand, 0, loc); 
  251.     }
  252.          
  253.     list_destroy(lines, octstr_destroy_item); 
  254.     octstr_destroy(os); 
  255.  
  256.     return expand; 
  257.  
  258.  
  259. int cfg_read(Cfg *cfg) 
  260.     CfgLoc *loc; 
  261.     CfgLoc *loc_inc; 
  262.     List *lines;
  263.     List *expand; 
  264.     List *stack; 
  265.     Octstr *name;
  266.     Octstr *value;
  267.     Octstr *filename; 
  268.     CfgGroup *grp;
  269.     long equals;
  270.     long lineno;
  271.     long error_lineno;
  272.     
  273.     loc = loc_inc = NULL;
  274.     /* 
  275.      * expand initial main config file and add it to the recursion 
  276.      * stack to protect against cycling 
  277.      */ 
  278.     if ((lines = expand_file(cfg->filename, 1)) == NULL) { 
  279.         panic(0, "Failed to load main configuration file `%s'. Aborting!", 
  280.               octstr_get_cstr(cfg->filename)); 
  281.     } 
  282.     stack = list_create(); 
  283.     list_insert(stack, 0, octstr_duplicate(cfg->filename)); 
  284.     grp = NULL;
  285.     lineno = 0;
  286.     error_lineno = 0;
  287.     while (error_lineno == 0 && (loc = list_extract_first(lines)) != NULL) { 
  288.         octstr_strip_blanks(loc->line); 
  289.         if (octstr_len(loc->line) == 0) { 
  290.             if (grp != NULL && add_group(cfg, grp) == -1) { 
  291.                 error_lineno = loc->line_no; 
  292.                 destroy_group(grp); 
  293.             } 
  294.             grp = NULL; 
  295.         } else if (octstr_get_char(loc->line, 0) != '#') { 
  296.             equals = octstr_search_char(loc->line, '=', 0); 
  297.             if (equals == -1) { 
  298.                 error(0, "An equals sign ('=') is missing on line %ld of file %s.", 
  299.                       loc->line_no, octstr_get_cstr(loc->filename)); 
  300.                 error_lineno = loc->line_no; 
  301.             } else  
  302.              
  303.             /* 
  304.              * check for special config directives, like include or conditional 
  305.              * directives here 
  306.              */ 
  307.             if (octstr_search(loc->line, octstr_imm("include"), 0) != -1) { 
  308.                 filename = octstr_copy(loc->line, equals + 1, octstr_len(loc->line)); 
  309.                 parse_value(filename); 
  310.  
  311.                 /* check if we are cycling */ 
  312.                 if (list_search(stack, filename, octstr_item_match) != NULL) { 
  313.                     panic(0, "Recursive include for config file `%s' detected " 
  314.                              "(on line %ld of file %s).", 
  315.                           octstr_get_cstr(filename), loc->line_no,  
  316.                           octstr_get_cstr(loc->filename)); 
  317.                 } else {     
  318.                     List *files = list_create();
  319.                     Octstr *file;
  320.                     struct stat filestat;
  321.                     /* check if included file is a directory */
  322.                     lstat(octstr_get_cstr(filename), &filestat);
  323.                     /* is a directory. create a list with files */
  324.                     if (S_ISDIR(filestat.st_mode)) {
  325.                         DIR *dh;
  326.                         struct dirent *diritem;
  327.                         debug("gwlib.cfg", 0, "Loading include dir `%s' "
  328.                               "(on line %ld of file %s).",  
  329.                               octstr_get_cstr(filename), loc->line_no,  
  330.                               octstr_get_cstr(loc->filename)); 
  331.                         dh = opendir(octstr_get_cstr(filename));
  332.                         while ((diritem = readdir(dh))) {
  333.                             Octstr *fileitem;
  334.                             fileitem = octstr_duplicate(filename);
  335.                             octstr_append(fileitem, octstr_create("/"));
  336.                             octstr_append(fileitem, octstr_create(diritem->d_name));
  337.                             lstat(octstr_get_cstr(fileitem), &filestat);
  338.                             if (!S_ISDIR(filestat.st_mode)) {
  339.                                 list_insert(files, 0, fileitem);
  340.                             }
  341.                         }
  342.                         closedir(dh);
  343.                     } 
  344.     
  345.                     /* is a file, create a list with it */
  346.                     else {
  347.                         list_insert(files, 0, octstr_duplicate(filename));
  348.                     }
  349.                     /* include files */
  350.                     while((file = list_extract_first(files)) != NULL) {
  351.                         list_insert(stack, 0, octstr_duplicate(file)); 
  352.                         debug("gwlib.cfg", 0, "Loading include file `%s' (on line %ld of file %s).",  
  353.                               octstr_get_cstr(file), loc->line_no,  
  354.                               octstr_get_cstr(loc->filename)); 
  355.                         /*  
  356.                          * expand the given include file and add it to the current 
  357.                          * processed main while loop 
  358.                          */ 
  359.                         if ((expand = expand_file(file, 0)) != NULL) {
  360.                             while ((loc_inc = list_extract_first(expand)) != NULL) 
  361.                                 list_insert(lines, 0, loc_inc); 
  362.                         } else { 
  363.                             panic(0, "Failed to load whole configuration. Aborting!"); 
  364.                         } 
  365.                  
  366.                         list_destroy(expand, NULL); 
  367.                         cfgloc_destroy(loc_inc); 
  368.                     }
  369.                 list_destroy(files, octstr_destroy_item);
  370.                 } 
  371.                 octstr_destroy(filename); 
  372.             }  
  373.              
  374.             /* 
  375.              * this is a "normal" line, so process it accodingly 
  376.              */ 
  377.             else  { 
  378.                 name = octstr_copy(loc->line, 0, equals); 
  379.                 octstr_strip_blanks(name); 
  380.                 value = octstr_copy(loc->line, equals + 1, octstr_len(loc->line)); 
  381.                 parse_value(value); 
  382.  
  383.           if (grp == NULL)
  384.                     grp = create_group(); 
  385.                  
  386.                 if (grp->configfile != NULL) {
  387.                     octstr_destroy(grp->configfile); grp->configfile=NULL;
  388.                 }
  389.                 grp->configfile = octstr_duplicate(cfg->filename); 
  390.                 cfg_set(grp, name, value); 
  391.                 octstr_destroy(name); 
  392.                 octstr_destroy(value); 
  393.             } 
  394.         } 
  395.         cfgloc_destroy(loc); 
  396.     }
  397.     if (grp != NULL && add_group(cfg, grp) == -1) {
  398.         error_lineno = 1; 
  399.         destroy_group(grp); 
  400.     }
  401.     list_destroy(lines, NULL); 
  402.     list_destroy(stack, octstr_destroy_item); 
  403.     if (error_lineno != 0) {
  404.         error(0, "Error found on line %ld of file `%s'.",  
  405.           error_lineno, octstr_get_cstr(cfg->filename)); 
  406.         return -1; 
  407.     }
  408.     return 0;
  409. }
  410. CfgGroup *cfg_get_single_group(Cfg *cfg, Octstr *name)
  411. {
  412.     return dict_get(cfg->single_groups, name);
  413. }
  414. List *cfg_get_multi_group(Cfg *cfg, Octstr *name)
  415. {
  416.     List *list, *copy;
  417.     long i;
  418.     
  419.     list = dict_get(cfg->multi_groups, name);
  420.     if (list == NULL)
  421.      return NULL;
  422.     copy = list_create();
  423.     for (i = 0; i < list_len(list); ++i)
  424.      list_append(copy, list_get(list, i));
  425.     return copy;
  426. }
  427. Octstr *cfg_get_group_name(CfgGroup *grp)
  428. {
  429.     return octstr_duplicate(grp->name);
  430. }
  431. Octstr *cfg_get_configfile(CfgGroup *grp)
  432. {
  433.     return octstr_duplicate(grp->configfile);
  434. }
  435. Octstr *cfg_get_real(CfgGroup *grp, Octstr *varname, const char *file, 
  436.                long line, const char *func)
  437. {
  438.     Octstr *os;
  439.     if (grp->name != NULL && !is_allowed_in_group(grp->name, varname))
  440.      panic(0, "Trying to fetch variable `%s' in group `%s', not allowed.",
  441.       octstr_get_cstr(varname), octstr_get_cstr(grp->name));
  442.     os = dict_get(grp->vars, varname);
  443.     if (os == NULL)
  444.      return NULL;
  445.     return gw_claim_area_for(octstr_duplicate(os), file, line, func);
  446. }
  447. int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
  448. {
  449.     Octstr *os;
  450.     int ret;
  451.     
  452.     os = cfg_get(grp, varname);
  453.     if (os == NULL)
  454.      return -1;
  455.     if (octstr_parse_long(n, os, 0, 0) == -1)
  456.      ret = -1;
  457.     else
  458.      ret = 0;
  459.     octstr_destroy(os);
  460.     return ret;
  461. }
  462. int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
  463. {
  464.     Octstr *os;
  465.     os = cfg_get(grp, varname);
  466.     if (os == NULL) {
  467. *n = 0;
  468.      return -1;
  469.     }
  470.     if (octstr_case_compare(os, octstr_imm("true")) == 0
  471. || octstr_case_compare(os, octstr_imm("yes")) == 0
  472. || octstr_case_compare(os, octstr_imm("on")) == 0
  473. || octstr_case_compare(os, octstr_imm("1")) == 0)
  474.     {     
  475. *n = 1;
  476.     } else if (octstr_case_compare(os, octstr_imm("false")) == 0
  477. || octstr_case_compare(os, octstr_imm("no")) == 0
  478. || octstr_case_compare(os, octstr_imm("off")) == 0
  479. || octstr_case_compare(os, octstr_imm("0")) == 0)
  480.     {
  481. *n = 0;
  482.     }
  483.     else {
  484. *n = 1;
  485. warning(0, "bool variable set to strange value, assuming 'true'");
  486.     }
  487.     octstr_destroy(os);
  488.     return 0;
  489. }
  490. List *cfg_get_list(CfgGroup *grp, Octstr *varname)
  491. {
  492.     Octstr *os;
  493.     List *list;
  494.     
  495.     os = cfg_get(grp, varname);
  496.     if (os == NULL)
  497.      return NULL;
  498.     list = octstr_split_words(os);
  499.     octstr_destroy(os);
  500.     return list;
  501. }
  502. void cfg_set(CfgGroup *grp, Octstr *varname, Octstr *value)
  503. {
  504.     dict_put(grp->vars, varname, octstr_duplicate(value));
  505. }
  506. void grp_dump(CfgGroup *grp)
  507. {
  508.     List *names;
  509.     Octstr *name;
  510.     Octstr *value;
  511.     if (grp->name == NULL)
  512. debug("gwlib.cfg", 0, "  dumping group (name not set):");
  513.     else
  514. debug("gwlib.cfg", 0, "  dumping group (%s):",
  515.       octstr_get_cstr(grp->name));
  516.     names = dict_keys(grp->vars);
  517.     while ((name = list_extract_first(names)) != NULL) {
  518. value = cfg_get(grp, name);
  519. debug("gwlib.cfg", 0, "    <%s> = <%s>", 
  520.       octstr_get_cstr(name),
  521.       octstr_get_cstr(value));
  522.      octstr_destroy(value);
  523.      octstr_destroy(name);
  524.     }
  525.     list_destroy(names, NULL);
  526. }
  527. void cfg_dump(Cfg *cfg)
  528. {
  529.     CfgGroup *grp;
  530.     List *list;
  531.     List *names;
  532.     Octstr *name;
  533.     debug("gwlib.cfg", 0, "Dumping Cfg %p", (void *) cfg);
  534.     debug("gwlib.cfg", 0, "  filename = <%s>", 
  535.        octstr_get_cstr(cfg->filename));
  536.     names = dict_keys(cfg->single_groups);
  537.     while ((name = list_extract_first(names)) != NULL) {
  538. grp = cfg_get_single_group(cfg, name);
  539. if (grp != NULL)
  540.     grp_dump(grp);
  541.      octstr_destroy(name);
  542.     }
  543.     list_destroy(names, NULL);
  544.     names = dict_keys(cfg->multi_groups);
  545.     while ((name = list_extract_first(names)) != NULL) {
  546. list = cfg_get_multi_group(cfg, name);
  547. while ((grp = list_extract_first(list)) != NULL)
  548.     grp_dump(grp);
  549. list_destroy(list, NULL);
  550.      octstr_destroy(name);
  551.     }
  552.     list_destroy(names, NULL);
  553.     debug("gwlib.cfg", 0, "Dump ends.");
  554. }