config.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:7k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** config.c
  3. **
  4. ** Copyright (c) 1994-1995 Peter Eriksson <pen@signum.se>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include <pwd.h>
  23. #include <grp.h>
  24. #include "phttpd.h"
  25. static int get_bool(const char *str)
  26. {
  27.     return (strcasecmp(str, "yes") == 0 ||
  28.     strcasecmp(str, "true") == 0 ||
  29.     strcasecmp(str, "on") == 0 ||
  30.     strcasecmp(str, "1") == 0 ||
  31.     strcasecmp(str, "light") == 0 ||
  32.     strcasecmp(str, "up") == 0);
  33. }
  34. static int get_number(const char *str)
  35. {
  36.     int num = 0;
  37.     int neg_flag = 0;
  38.     if (*str == '-')
  39.     {
  40. neg_flag = !neg_flag;
  41. ++str;
  42.     }
  43.     while (*str && s_isdigit(*str))
  44.     {
  45. num *= 10;
  46. num += (*str - '0');
  47. ++str;
  48.     }
  49.     switch (*str)
  50.     {
  51.       case 'k':
  52. num *= 1000;
  53. break;
  54.       case 'K':
  55. num *= 1024;
  56. break;
  57.       case 'M':
  58. num *= 1024*1024;
  59. break;
  60.     }
  61.     return (neg_flag ? -num : num);
  62. }
  63. static char **mk_pair(const char *a0, const char *a1)
  64. {
  65.     char **pair;
  66.     pair = s_malloc(2 * sizeof(char *));
  67.     pair[0] = s_strdup(a0);
  68.     pair[1] = s_strdup(a1);
  69.     return pair;
  70. }
  71. static int get_value(struct options *op,
  72.      int index,
  73.      const char *value)
  74. {
  75.     switch (op[index].type)
  76.     {
  77.       case T_NUMBER:
  78. if (value == NULL)
  79.     * (int *) op[index].var = op[index].def_number;
  80. else
  81.     * (int *) op[index].var = get_number(value);
  82. return 0;
  83.       case T_STRING:
  84. if (value == NULL)
  85.     * (char **) op[index].var = s_strdup(op[index].def_string);
  86. else
  87.     * (char **) op[index].var = s_strdup(value);
  88. return 0;
  89.       case T_BOOL:
  90. if (value == NULL)
  91.     * (int *) op[index].var = op[index].def_number;
  92. else
  93.     * (int *) op[index].var = get_bool(value);
  94. return 0;
  95.       case T_FILE:
  96. if (value)
  97.     return config_parse_file(value, op, 1);
  98.     
  99.       default:
  100. return -1;
  101.     }
  102. }
  103. int config_parse_file(const char *file,
  104.       struct options *op,
  105.       int verbose)
  106. {
  107.     int fd;
  108.     char buf[2048], *cp, *cmd, *val, *last;
  109.     int line, i = 0;
  110.     struct table *tp = NULL;
  111.     hashtable_t *htp = NULL;
  112.     if (debug > 2)
  113. fprintf(stderr, "config_parse_file, path=%sn", file);
  114.     
  115.     line = 0;
  116.     fd = fd_open(file, O_RDONLY);
  117.     if (fd < 0)
  118.     {
  119. if (verbose)
  120. {
  121.     fprintf(stderr, "Config file %s not found.n", file);
  122.     return -1;
  123. }
  124. else
  125.     return 0;
  126.     }
  127.     while (fd_gets(buf, sizeof(buf), fd))
  128.     {
  129. line++;
  130. cp = strchr(buf, '#');
  131. if (cp)
  132.     *cp = '';
  133. cp = buf + strlen(buf) - 1;
  134. while (cp >= buf && s_isspace(*cp))
  135.     --cp;
  136. ++cp;
  137. *cp = '';
  138. last = buf;
  139. cmd = strtok_r(buf, " =tnr", &last);
  140. if (tp || htp)
  141.     val = strtok_r(NULL, "nr", &last);
  142. else
  143.     val = strtok_r(NULL, " tnr", &last);
  144. if (cmd == NULL)
  145.     continue;
  146. if (val)
  147.     while (s_isspace(*val))
  148. ++val;
  149. if (htp)
  150. {
  151.     if (strcmp(cmd, "}") == 0)
  152.     {
  153. htp = NULL;
  154.     }
  155.     else
  156.     {
  157. if (op[i].var_cr_f)
  158. {
  159.     void *var;
  160.     
  161.     if (op[i].var_cr_f(cmd, val, &var) == 1)
  162. ht_insert(htp, cmd, 0, var, 0, s_free);
  163. }
  164. else
  165. {
  166.     ht_insert(htp, cmd, 0, s_strdup(val), 0, s_free);
  167. }
  168.     }
  169.     
  170.     continue;
  171. }
  172.     
  173. if (tp)
  174. {
  175.     if (strcmp(cmd, "}") == 0)
  176.     {
  177. tp = NULL;
  178.     }
  179.     else
  180.     {
  181. if (op[i].var_cr_f)
  182. {
  183.     void *var;
  184.     
  185.     if (op[i].var_cr_f(cmd, val, &var) == 1)
  186. tbl_append(tp, var);
  187. }
  188. else
  189. {
  190.     char **pair = mk_pair(cmd, val);
  191.     
  192.     if (pair == NULL)
  193. continue;
  194.     
  195.     tbl_append(tp, pair);
  196. }
  197.     }
  198.     
  199.     continue;
  200. }
  201. if (val && strcmp(val, "=") == 0)
  202.     val = strtok_r(NULL, "tnr", &last);
  203. for (i = 0; op[i].name; i++)
  204.     if (strcmp(op[i].name, cmd) == 0)
  205. break;
  206. if (op[i].name)
  207.     switch (op[i].type)
  208.     {
  209.       case T_FILE:
  210.       case T_BOOL:
  211.       case T_NUMBER:
  212.       case T_STRING:
  213. get_value(op, i, val);
  214. break;
  215.       case T_TABLE:
  216. if (val && strcmp(val, "{") == 0)
  217. {
  218.     tp = tbl_create(0);
  219.     * (struct table **) op[i].var = tp;
  220. }
  221. else
  222. {
  223.     if (debug > 2)
  224. fprintf(stderr,
  225. "Illegal table definition on line %d.n",
  226. line);
  227. }
  228. break;
  229.       case T_HTABLE:
  230. if (val && strcmp(val, "{") == 0)
  231. {
  232.     htp = s_malloc(sizeof(hashtable_t));
  233.     ht_init(htp, 0, NULL);
  234.     
  235.     * (hashtable_t **) op[i].var = htp;
  236. }
  237. else
  238. {
  239.     if (debug > 2)
  240. fprintf(stderr,
  241. "Illegal table definition on line %d.n",
  242. line);
  243. }
  244. break;
  245.     }
  246. else 
  247. {
  248.     if (debug > 2)
  249. fprintf(stderr, "Unknown command '%s' on line %d.n",
  250. cmd, line);
  251. }
  252.     }
  253.     fd_close(fd);
  254.     if (debug > 2)
  255. fprintf(stderr, "config_parse_file, exitingn");
  256.     return 0;
  257. }
  258. static char *type2str(int type)
  259. {
  260.     switch (type)
  261.     {
  262.       case T_BOOL:
  263. return "Boolean";
  264.       case T_NUMBER:
  265. return "Number";
  266.       case T_STRING:
  267. return "String";
  268.       case T_FILE:
  269. return "String";
  270.       default:
  271. return NULL;
  272.     }
  273. }
  274. static int help(struct options *op)
  275. {
  276.     int i;
  277.     char *type;
  278.     
  279.     fprintf(stderr, "Available options/switches:n");
  280.     for (i = 0; op[i].name; i++)
  281.     {
  282. type = type2str(op[i].type);
  283. if (type)
  284.     fprintf(stderr, "   %s%ct--%-20st%st  %sn",
  285.     op[i].flag ? "-" : "",
  286.     op[i].flag ? op[i].flag : ' ',
  287.     op[i].name,
  288.     type,
  289.     op[i].help ? op[i].help : "");
  290.     }
  291.     return 1;
  292. }
  293. int config_parse_argv(const char **argv,
  294.       struct options *op)
  295. {
  296.     int i, j, len;
  297.     const char *cp;
  298.     
  299.     
  300.     if (argv == NULL)
  301. return 0;
  302.     
  303.     for (i = 0; argv[i] && argv[i][0] == '-'; i++)
  304.     {
  305. if (argv[i][1] == '-')
  306. {
  307.     /* --long-option */
  308.     if (debug > 2)
  309. fprintf(stderr, "config_parse_argv: Got long option: %sn", argv[i]);
  310.     
  311.     if (argv[i][2] == '')
  312. return ++i;
  313.     
  314.     cp = strchr(argv[i]+2, '=');
  315.     len = cp - (argv[i]+2);
  316.     
  317.     if (cp)
  318. ++cp;
  319.     else
  320.     {
  321. if (argv[i+1] && argv[i+1][0] != '-')
  322.     cp = argv[++i];
  323. else
  324.     cp = NULL;
  325.     }
  326.     
  327.     for (j = 0; op[j].name &&
  328.  !(strncmp(op[j].name, argv[i]+2, len) == 0 &&
  329.    op[j].name[len] == ''); j++)
  330. ;
  331.     
  332.     if (op[j].name)
  333. get_value(op, j, cp);
  334.     else
  335.     {
  336. if (strcmp(argv[i]+2, "help") == 0)
  337.     exit(help(op));
  338. fprintf(stderr, "Illegal command line option: %sn", argv[i]);
  339. return -i;
  340.     }
  341. }
  342. else
  343. {
  344.     /* -s hort option */
  345.     if (debug > 2)
  346. fprintf(stderr, "config_parse_argv: Got short option: %sn", argv[i]);
  347.     for (j = 0; op[j].name && argv[i][1] != op[j].flag; j++)
  348. ;
  349.     if (op[j].name)
  350.     {
  351. if (argv[i][2])
  352.     get_value(op, j, argv[i]+2);
  353. else
  354.     if (argv[i+1] && argv[i+1][0] != '-')
  355. get_value(op, j, argv[++i]);
  356.     else
  357. get_value(op, j, NULL);
  358.     
  359.     }
  360.     else
  361.     {
  362. if (argv[i][1] == '?' || argv[i][1] == 'h' || argv[i][1] == 'H')
  363.     exit(help(op));
  364. fprintf(stderr, "Illegal command line option: %sn", argv[i]);
  365. return -i;
  366.     }
  367. }
  368.     }
  369.     return i;
  370. }