/* confparser.h - Configuration file parser for ck ---------------------*- C -*- * * This file is part of ck, the config keeper * * ----------------------------------------------------------------------------- * * Copyright (C) 2018 Anastasis Grammenos * GPLv3 (see LICENCE for the full notice) * * -------------------------------------------------------------------------- */ #include "ckutil.h" #include "confparser.h" #include "ckerrlog.h" ERRLOG(configfile); const char * const CONFIG_NAME = "/ckrc"; void conf_values_initialize(Conf *c) { #define X(var, str, name) \ c->var = NULL; CONFIG_VARIABLES_TABLE #undef X } int remove_newline(char buff[]) { int initLength = strlen(buff); for (int i = 0; i < initLength; i++) { if (buff[i] == '\n') { buff[i] = ' '; } } return strlen(buff); } int read_next_line(char *line, FILE *f) { char nextLine[STR_L]; if (fgets(nextLine, STR_L, f) == NULL) { return -1; } strcpy(line, nextLine); return 0; } ConfVar match_variables(char *line, char matched[]) { if (line[0] == '#' || str_is_empty(line)) { return CV_NO_VAL_OR_COMMENT; } #define X(var, str, name) \ if (sscanf(line, str, matched) == 1) { \ return CV_##var; \ } CONFIG_VARIABLES_TABLE #undef X return -1; } void make_config_name(char * ret, const char *confPath) { char tmp[STR_L]; strcpy(tmp, confPath); strcat(tmp, CONFIG_NAME); strcpy(ret, tmp); } ConfigParserResult parse(Conf *conf, UserOpt *opt) { conf_values_initialize(conf); FILE *confPtr; char confName[STR_L]; make_config_name(confName, opt->confDir); if ((confPtr = fopen(confName, "r")) == NULL) { ERR("%s is not readable, check the permissions.", confName) return CPR_NO_CONFIG_FILE; } int flag = 1; char line[STR_L]; char matched[STR_L]; while (read_next_line(line, confPtr) == 0) { if (strlen(line) > STR_L) { return CPR_WRONG_CONFIG; } switch(match_variables(line, matched)) { #define X(var, str, name) \ case CV_##var: \ conf->var = malloc(strlen(matched)+1); \ strcpy(conf->var, matched); \ if (!util_is_dir(matched)) { \ return CPR_WRONG_##var; \ } \ LOG("Found %s: %s", name, conf->var); \ break; CONFIG_VARIABLES_TABLE #undef X case CV_NO_VAL_OR_COMMENT: break; default: if (line[strlen(line) - 1] == '\n') { ERR("Config error in line: %.*s", strlen(line) - 1, line); } else { ERR("Config error in line: %s", line); } flag = 0; } } if (flag) { return CPR_OK; } return CPR_WRONG_CONFIG; } int config_file_parse(Conf *conf, UserOpt *opt) { LOG("Using '%s' for ck configuration directory", opt->confDir); switch (parse(conf, opt)) { #define X(var,str,name) \ case CPR_WRONG_##var: \ ERR("%s %s defined in config doesn't exist", name, conf->var); \ return -1; \ break; CONFIG_VARIABLES_TABLE #undef X case CPR_OK: return 0; case CPR_NO_CONFIG_FILE: case CPR_WRONG_CONFIG: break; } return -1; } void free_conf(Conf *conf) { #define X(var,str,name) \ if (conf->var) { \ free(conf->var); \ } CONFIG_VARIABLES_TABLE #undef X }