#include #include #include #include #include #include "config.h" #include "macros.h" #include "misc.h" config_val parse_option_value(const config_opt *opt, char *value) { config_val val = {0}; switch (opt->type) { case TYPE_INT : case TYPE_BOOL : val.i = strtol(value, NULL, 0); break; case TYPE_STRING: val.str = make_str(value); break; case TYPE_FLOAT : val.f = strtof(value, NULL); break; default : break; } return val; } void set_config_opt(config *conf, config_type type, size_t offset, config_val val) { char *cfg = (char *)conf; switch (type) { case TYPE_INT : case TYPE_BOOL : *(int *)(cfg+offset) = val.i; break; case TYPE_STRING: *(char **)(cfg+offset) = val.str; break; case TYPE_FLOAT : *(float *)(cfg+offset) = val.f; break; default : break; } } void cleanup_config(config *conf) { char *cfg = (char *)conf; for (const config_opt *opt = config_opts; opt->name != NULL; opt++) { /* Is this config option's type a string, and is the string of that config option in conf not NULL? */ if (opt->type == TYPE_STRING && *(char **)(cfg+opt->offset) != NULL) { free(*(char **)(cfg+opt->offset)); } } free(conf); } config *parse_config(const char *filename) { /* Size of the file, in bytes. */ long filesize = 0; /* Config settings. */ config *cfg; /* Buffer of the file contents. */ char *buf = read_file(filename, &filesize); char *tmp = buf; /* Return NULL, if the buffer wasn't allocated */ if (buf == NULL) { return NULL; } cfg = calloc(1, sizeof(config)); /* Return NULL, if cfg wasn't allocated. */ if (cfg == NULL) { free(buf); return NULL; } while (*tmp != '\0') { char *line = get_line(&tmp); char *value; char *name = strtok_r(line, "=", &value); const config_opt *opt; /* Check to see if the config option name we got is valid. */ for (opt = config_opts; opt->name != NULL && strcmp(name, opt->name); opt++); /* Is the config option valid? */ if (opt->name != NULL) { config_val val = parse_option_value(opt, value); if (opt->offset == offsetof(config, port)) { const int port = strtol(val.str, NULL, 0); if (port <= 0 || port > 65535) { log(LOG_ERR, "Invalid port %d. (Valid port must be between 1, and 65535.)", port); cleanup_config(cfg); free(line); free(buf); return NULL; } } set_config_opt(cfg, opt->type, opt->offset, val); } free(line); } free(buf); return cfg; }