aboutsummaryrefslogblamecommitdiffstats
path: root/src/confparser.c
blob: f7b6268f5a1e5e7982c5c8a9a50ab74935bf64c8 (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                                                                                
                       
                     
 
                   
 
                                                
 
                               
                                                 


                        

 
                                         
                            
                                          
              
   
                         
           

 
                                                     
                                             

                                
                                                  




                                                  
                      

 
                                                         
                       

                           
 
                   

 



































                                                                                         
                          


            

                                                                 
                


                            
 
                                           
                                                 
                                                               
                
   
                                              
                               
                
     
                                            
                                                                         








                                                                         





                              

                               
     
   

                                                             

                                                 




                                                 
           
 
 
                            
                                                 

                                                 
   

                        
 
/* 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 "confparser.h"
#include "ckerrlog.h"

ERRLOG(configfile);

static const char * const CONFIG_NAME = "/ckrc";

void initialize_conf(Conf *c) {
#define X(var, str, name, optional)             \
  c->var = NULL;
  CONFIG_VARIABLES_TABLE
#undef X
}

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, optional)              \
  if (sscanf(line, str, matched) == 1) {         \
    return CV_##var;                             \
  }
  CONFIG_VARIABLES_TABLE
#undef X
  return CV_WRONG_VAL;
}

void make_config_name(char * ret, const char *confPath) {
  char tmp[STR_L] = "";
  strcpy(tmp, confPath);
  strcat(tmp, CONFIG_NAME);

  strcpy(ret, tmp);
}

int find_config(UserOpt *opt) {
  /* If env CK_CONFIG is set */
  char *config_home = getenv("CK_CONFIG");
  if (config_home) {
    if (util_is_dir(config_home)) {
      opt->confDir = strdup(config_home);
      LOG("Using $CK_CONFIG: %s", config_home);
      return 0;
    }
  }
  LOG("$CK_CONFIG not avaliable.")

  /* If XDG_CONFIG_HOME exists*/
  config_home = getenv("XDG_CONFIG_HOME");
  if (config_home) {
    if (util_is_dir(config_home)) {
      char defaultConf[STR_S] = "ck";
      opt->confDir = malloc(strlen(config_home) + 1 /* '/' */ + strlen(defaultConf) + 1);
      str_join_dirname_with_basename(opt->confDir, config_home, defaultConf);
      LOG("Using $XDG_CONFIG_HOME: %s", config_home);
      return 0;
    }
  }
  LOG("$XDG_CONFIG_HOME not avaliable.")

  /* fallback to HOME/.ck */
  config_home = getenv("HOME");
  if (config_home) {
    if (util_is_dir(config_home)) {
      char defaultConf[STR_S] = ".ck";
      opt->confDir = malloc(strlen(config_home) + 1 /* '/' */ + strlen(defaultConf) + 1);
      str_join_dirname_with_basename(opt->confDir, config_home, defaultConf);
      LOG("Using $HOME: %s", config_home);
      return 0;
    }
  }
  ERR("No config found.");
  return -1;
}

int config_file_parse(Conf *conf, UserOpt *opt) {
  LOG("Using '%s' for ck configuration directory", opt->confDir);
  FILE *confPtr;
  char confName[STR_L] = "";
  char line[STR_L] = "";
  char matched[STR_L] = "";

  make_config_name(confName, opt->confDir);
  if ((confPtr = fopen(confName, "r")) == NULL) {
    ERR("%s is not readable, check the permissions.", confName)
      return -1;
  }
  while (read_next_line(line, confPtr) == 0) {
    if (strlen(line) > STR_L) {
      return -1;
    }
    switch(match_variables(line, matched)) {
#define X(var, str, name, optional)                                     \
      case CV_##var:                                                    \
        conf->var = malloc(strlen(matched)+1);                          \
        strcpy(conf->var, matched);                                     \
        if (!util_is_dir(matched)) {                                    \
          ERR("%s %s defined in config doesn't exist",                  \
              name, conf->var);                                         \
          return -1;                                                    \
        }                                                               \
        LOG("Found %s: %s", name, conf->var);                           \
        break;
      CONFIG_VARIABLES_TABLE
#undef X
    case CV_NO_VAL_OR_COMMENT:
      break;
    default:
      ERR("In line: %s", line);
      return -1;
    }
  }
  /* Could add an optional row that would make the config var
   * optional. */
#define X(var, str, name, optional)             \
  if (!optional && !conf->var) {                \
    ERR("Missing %s", name);                    \
    return -1;                                  \
  }
  CONFIG_VARIABLES_TABLE
#undef X
  return 0;
}

void free_conf(Conf *conf) {
#define X(var, str, name, optional)             \
  if (conf->var) {                              \
    free(conf->var);                            \
  }
  CONFIG_VARIABLES_TABLE
#undef X
}