#include "conf.h" #include #include #include #include #include __thread int line_no; int conf_custom(const char *item, void *data, int argc, char *argv[]) { struct config_item_custom *item_custom = data; return item_custom->custom_func(item_custom->custom_data, argc, argv); } int conf_int(const char *item, void *data, int argc, char *argv[]) { struct config_item_int *item_int = data; int value = 0; if (argc < 2) { return -1; } value = atoi(argv[1]); if (value < item_int->min) { value = item_int->min; } else if (value > item_int->max) { value = item_int->max; } *(item_int->data) = value; return 0; } int conf_string(const char *item, void *data, int argc, char *argv[]) { struct config_item_string *item_string = data; if (argc < 2) { return -1; } strncpy(item_string->data, argv[1], item_string->size); return 0; } int conf_yesno(const char *item, void *data, int argc, char *argv[]) { struct config_item_yesno *item_yesno = data; int yes = 0; if (argc < 2) { return -1; } char *value = argv[1]; if (strncmp("yes", value, sizeof("yes")) == 0 || strncmp("YES", value, sizeof("YES")) == 0) { yes = 1; } else if (strncmp("no", value, sizeof("no")) == 0 || strncmp("NO", value, sizeof("NO")) == 0) { yes = 0; } *(item_yesno->data) = yes; return 0; } int conf_size(const char *item, void *data, int argc, char *argv[]) { /* read dns cache size */ int base = 1; size_t size = 0; int num = 0; struct config_item_size *item_size = data; char *value = argv[1]; if (strstr(value, "k") || strstr(value, "K")) { base = 1024; } else if (strstr(value, "m") || strstr(value, "M")) { base = 1024 * 1024; } else if (strstr(value, "g") || strstr(value, "G")) { base = 1024 * 1024 * 1024; } num = atoi(value); if (num < 0) { return -1; } size = num * base; if (size > item_size->max) { size = item_size->max; } else if (size < item_size->min) { size = item_size->min; } *(item_size->data) = size; return 0; } void conf_getopt_reset(void) { static struct option long_options[] = {{"-", 0, 0, 0}, {0, 0, 0, 0}}; int argc = 2; char *argv[3] = {"reset", "", 0}; optind = 1; opterr = 0; getopt_long(argc, argv, "", long_options, NULL); optind = 1; opterr = 0; } int conf_parse_args(char *key, char *value, int *argc, char **argv) { char *start = NULL; char *ptr = value; int count = 0; int sep_flag = ' '; argv[0] = key; count++; while (*ptr != '\0') { if (*ptr == '\\') { char *tmp = ptr + 1; while (*tmp != '\0') { *(tmp - 1) = *tmp; tmp++; } ptr++; continue; } if (*ptr == '"' && start == NULL) { sep_flag = '"'; start = NULL; } if (*ptr != sep_flag && start == NULL) { start = ptr; ptr++; continue; } if (*ptr == sep_flag && start == NULL) { ptr++; continue; } if (*ptr == sep_flag && start) { argv[count] = start; *ptr = '\0'; ptr++; start = ptr; count++; sep_flag = ' '; start = NULL; continue; } ptr++; } if (start != ptr && start) { argv[count] = start; count++; } *argc = count; argv[count + 1] = 0; return 0; } void load_exit(void) { return; } int load_conf_get_line_count(void) { return line_no; } int load_conf_file(const char *file, struct config_item *items) { FILE *fp = NULL; char line[MAX_LINE_LEN]; char key[MAX_KEY_LEN]; char value[MAX_LINE_LEN]; int filed_num = 0; int i; int argc; char *argv[1024]; fp = fopen(file, "r"); if (fp == NULL) { return -1; } line_no = 0; while (fgets(line, MAX_LINE_LEN, fp)) { line_no++; filed_num = sscanf(line, "%63s %1023[^\r\n]s", key, value); if (filed_num <= 0) { continue; } /* comment, skip */ if (key[0] == '#') { continue; } /* if field format is not key = value, error */ if (filed_num != 2) { goto errout; } for (i = 0;; i++) { if (items[i].item == NULL) { break; } if (strncmp(items[i].item, key, MAX_KEY_LEN) != 0) { continue; } if (conf_parse_args(key, value, &argc, argv) != 0) { continue; } conf_getopt_reset(); /* call item function */ if (items[i].item_func(items[i].item, items[i].data, argc, argv) != 0) { conf_getopt_reset(); goto errout; } conf_getopt_reset(); break; } } fclose(fp); return 0; errout: if (fp) { fclose(fp); } return -1; } int load_conf(const char *file, struct config_item items[]) { return load_conf_file(file, items); }