/* config.c */ /* Copyright (c) 2004 Pierre Pronchery */ /* This file is part of GPuTTY. */ /* GPuTTY is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * GPuTTY is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GPuTTY; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "config.h" /* Config */ Config * config_new(void) { Config * config; if((config = hash_new()) == NULL) return NULL; return config; } /* FIXME should be an API to avoid this */ typedef struct _HashEntry { char * name; void * data; } HashEntry; void config_delete(Config * config) { unsigned int i; HashEntry * hi; int j; HashEntry * hj; for(i = array_get_size(config); i > 0; i--) { hi = array_get(config, i - 1); for(j = array_get_size(hi->data); j > 0; j--) { hj = array_get(hi->data, j - 1); free(hj->data); } hash_delete(hi->data); } hash_delete(config); } /* useful */ char * config_get(Config * config, char * section, char * variable) { void * p; if((p = hash_get(config, section)) == NULL) return NULL; return hash_get(p, variable); } int config_set(Config * config, char const * section, char const * variable, char const * value) { Hash * h; char * p; if((h = hash_get(config, section)) == NULL) { if((h = hash_new()) == NULL) return 1; if(hash_set(config, section, h) == 1) { hash_delete(h); return 1; } } if(value == NULL) return hash_set(h, variable, NULL) == 0 ? 0 : 1; if((p = strdup(value)) == NULL) return 1; if(hash_set(h, variable, p) == 0) return 0; free(p); return 1; } static char * _load_section(FILE * fp); static char * _load_variable(FILE * fp, int c); static char * _load_value(FILE * fp); int config_load(Config * config, char * filename) { FILE * fp; char * section; char * variable = NULL; int c; char * str; int ret = 0; if((section = strdup("")) == NULL || (fp = fopen(filename, "r")) == NULL) { free(section); return 1; } while((c = fgetc(fp)) != EOF) { if(c == '#') while((c = fgetc(fp)) != EOF && c != '\n'); else if(c == '[') { if((str = _load_section(fp)) == NULL) break; free(section); section = str; } else if(isprint(c)) { if((str = _load_variable(fp, c)) == NULL) break; free(variable); variable = str; if((str = _load_value(fp)) == NULL) break; config_set(config, section, variable, str); free(str); } else if(c != '\n') break; } free(section); free(variable); if(!feof(fp)) { errno = EINVAL; ret = 1; } fclose(fp); return ret; } static char * _load_section(FILE * fp) { int c; char * str = NULL; int len = 0; char * p; while((c = fgetc(fp)) != EOF && c != ']' && isprint(c)) { if((p = realloc(str, sizeof(char) * (len+2))) == NULL) { free(str); return NULL; } str = p; str[len++] = c; } if(c != ']') { free(str); return NULL; } str[len] = '\0'; return str; } static char * _load_variable(FILE * fp, int c) { char * str; int len = 1; char * p; if((str = malloc(sizeof(char) * (len+1))) == NULL) return NULL; str[0] = c; while((c = fgetc(fp)) != EOF && c != '=' && isprint(c)) { if((p = realloc(str, sizeof(char) * (len+2))) == NULL) { free(str); return NULL; } str = p; str[len++] = c; } if(c != '=') { free(str); return NULL; } str[len] = '\0'; return str; } static char * _load_value(FILE * fp) { int c; char * str = NULL; int len = 0; char * p; while((c = fgetc(fp)) != EOF && isprint(c)) { if((p = realloc(str, sizeof(char) * (len+2))) == NULL) { free(str); return NULL; } str = p; str[len++] = c; } if(c != '\n') { free(str); return NULL; } if(str == NULL) return strdup(""); str[len] = '\0'; return str; } static int _save_section(Hash * h, unsigned int i, FILE * fp); static int _save_variables(Hash * h, FILE * fp); int config_save(Config * config, char * filename) { FILE * fp; unsigned int i; unsigned int j; int ret = 0; if((i = array_get_size(config)) == 0) return 1; if((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "%s", "libutils: "); perror(filename); return 1; } for(j = 0; j < i; j++) if((ret = _save_section(config, j, fp)) != 0) break; fclose(fp); return ret; } static int _save_section(Hash * h, unsigned int i, FILE * fp) { HashEntry * he; he = array_get(h, i); if(he->name[0] != '\0') { if(fprintf(fp, "[%s]\n", he->name) < 0) return 1; } else if(i != 0) if(fwrite("[]\n", sizeof(char), 3, fp) != 3) return 1; if(_save_variables(he->data, fp) != 0) return 1; return fputc('\n', fp) == '\n' ? 0 : 1; } static int _save_variables(Hash * h, FILE * fp) { unsigned int i; unsigned int j; HashEntry * he; i = array_get_size(h); for(j = 0; j < i; j++) { he = array_get(h, j); if(he->name == NULL || he->data == NULL) continue; if(fprintf(fp, "%s=%s\n", he->name, (char*)he->data) < 0) return 1; } return 0; }