const char *config_set(const char *section, const char *name, const char *value) { struct config_value *cv; debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value); pthread_rwlock_wrlock(&config_rwlock); struct config *co = config_find_section(section); if(!co) co = config_create(section); cv = config_value_index_find(co, name, 0); if(!cv) cv = config_value_create(co, name, value); cv->flags |= CONFIG_VALUE_USED; if(strcmp(cv->value, value) != 0) cv->flags |= CONFIG_VALUE_CHANGED; free(cv->value); cv->value = strdup(value); if(!cv->value) fatal("Cannot allocate config.value"); pthread_rwlock_unlock(&config_rwlock); return value; }
char *config_get(const char *section, const char *name, const char *default_value) { struct config_value *cv; debug(D_CONFIG, "request to get config in section '%s', name '%s', default_value '%s'", section, name, default_value); pthread_rwlock_rdlock(&config_rwlock); struct config *co = config_find_section(section); if(!co) co = config_create(section); cv = config_value_index_find(co, name, 0); if(!cv) { cv = config_value_create(co, name, default_value); if(!cv) return NULL; } cv->flags |= CONFIG_VALUE_USED; if((cv->flags & CONFIG_VALUE_LOADED) || (cv->flags & CONFIG_VALUE_CHANGED)) { // this is a loaded value from the config file // if it is different that the default, mark it if(!(cv->flags & CONFIG_VALUE_CHECKED)) { if(strcmp(cv->value, default_value) != 0) cv->flags |= CONFIG_VALUE_CHANGED; cv->flags |= CONFIG_VALUE_CHECKED; } } pthread_rwlock_unlock(&config_rwlock); return(cv->value); }
const char *config_set_default(const char *section, const char *name, const char *value) { struct config_value *cv; debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value); struct config *co = config_find_section(section); if(!co) return config_set(section, name, value); cv = config_value_index_find(co, name, 0); if(!cv) return config_set(section, name, value); cv->flags |= CONFIG_VALUE_USED; if(cv->flags & CONFIG_VALUE_LOADED) return cv->value; if(strcmp(cv->value, value) != 0) { cv->flags |= CONFIG_VALUE_CHANGED; free(cv->value); cv->value = strdup(value); if(!cv->value) fatal("Cannot allocate config.value"); } return cv->value; }
int config_exists(const char *section, const char *name) { struct config_value *cv; debug(D_CONFIG, "request to get config in section '%s', name '%s'", section, name); struct config *co = config_section_find(section); if(!co) return 0; cv = config_value_index_find(co, name, 0); if(!cv) return 0; return 1; }
int load_config(char *filename, int overwrite_used) { int line = 0; struct config *co = NULL; pthread_rwlock_wrlock(&config_rwlock); char buffer[CONFIG_FILE_LINE_MAX + 1], *s; if(!filename) filename = CONFIG_DIR "/" CONFIG_FILENAME; FILE *fp = fopen(filename, "r"); if(!fp) { error("Cannot open file '%s'", CONFIG_DIR "/" CONFIG_FILENAME); pthread_rwlock_unlock(&config_rwlock); return 0; } while(fgets(buffer, CONFIG_FILE_LINE_MAX, fp) != NULL) { buffer[CONFIG_FILE_LINE_MAX] = '\0'; line++; s = trim(buffer); if(!s) { debug(D_CONFIG, "Ignoring line %d, it is empty.", line); continue; } int len = strlen(s); if(*s == '[' && s[len - 1] == ']') { // new section s[len - 1] = '\0'; s++; co = config_find_section(s); if(!co) co = config_create(s); continue; } if(!co) { // line outside a section error("Ignoring line %d ('%s'), it is outsize all sections.", line, s); continue; } char *name = s; char *value = strchr(s, '='); if(!value) { error("Ignoring line %d ('%s'), there is no = in it.", line, s); continue; } *value = '\0'; value++; name = trim(name); value = trim(value); if(!name) { error("Ignoring line %d, name is empty.", line); continue; } if(!value) { debug(D_CONFIG, "Ignoring line %d, value is empty.", line); continue; } struct config_value *cv = config_value_index_find(co, name, 0); if(!cv) cv = config_value_create(co, name, value); else { if(((cv->flags & CONFIG_VALUE_USED) && overwrite_used) || !(cv->flags & CONFIG_VALUE_USED)) { debug(D_CONFIG, "Overwriting '%s/%s'.", line, co->name, cv->name); free(cv->value); cv->value = strdup(value); if(!cv->value) fatal("Cannot allocate config.value"); } else debug(D_CONFIG, "Ignoring line %d, '%s/%s' is already present and used.", line, co->name, cv->name); } cv->flags |= CONFIG_VALUE_LOADED; } fclose(fp); pthread_rwlock_unlock(&config_rwlock); return 1; }