/* * This program 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 3 of the License, or * (at your option) any later version. * * This program 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 this program. If not, see . */ #include #include #include #include "cfg.h" int cfgsetup(struct cfgfile *cfg, char *filename) { /* * sets up the cfgfile struct pointed to by cfg, using the cfg * file location pointed to by filename */ cfg->count = 0; cfg->file = strdup(filename); if (!cfg->file) return 0; FILE *fp; fp = fopen(cfg->file, "r"); if (!fp) return 0; if (!readfile(cfg, fp)) { fclose(fp); return 0; } fclose(fp); //printlist(cfg->headnode); return 1; } void cfgfree(struct cfgfile *cfg) { /* * frees all memory allocated by cfg */ freenodes(cfg->headnode); free(cfg->file); free(cfg); } int cfggetvalue(struct cfgfile *cfg, char *key, char *buffer, size_t buffersize) { /* * stores the value from the option pointed to by key in buffer with * a maximum size of buffersize */ if (!cfg->headnode) return 0; struct cfgnode *tmp = cfg->headnode; while (tmp) { if (strcmp(key, tmp->key) == 0) { strncpy(buffer, tmp->value, buffersize); return 1; } tmp = tmp->next; } return 0; } void cfgappendchar(char *dest, char ch) { /* * appends char ch to dest * assumes there is enough allocated memory */ int len = strlen(dest); dest[len] = ch; dest[len+1] = '\0'; } int readfile(struct cfgfile *cfg, FILE *fp) { /* * read file pointer to by fp parsing lines * storing them in the cfgfile structure cfg */ cfg->headnode = createnode(); if (!cfg->headnode) return 0; char ch; size_t bufsize = 30; size_t linesize = 0; char *line = NULL; char *buffer = malloc(bufsize); if (!buffer) return 0; while ((ch = getc(fp)) != EOF) { if (!(ch == '\n') && !(ch == '\r')) { if (linesize >= bufsize-1) { bufsize += 10; buffer = realloc(buffer, bufsize); if (!buffer) return 0; } cfgappendchar(buffer, ch); linesize += sizeof(char); } else { free(line); line = strdup(buffer); if (!line) { free(buffer); return 0; } if (!parseline(line, cfg)) { free(line); free(buffer); return 0; } buffer[0] = '\0'; /* I could free buffer here, though I don't * see a point, we already have the memory * allocated, may as well keep it */ linesize = 0; } } free(line); free(buffer); return 1; } int parseline(char *line, struct cfgfile *cfg) { /* parse line pointed to by line string * results in a cfgnode node appended to head */ /* determine if the line is a comment (#) * also strip whitespaces from the beginning */ char ch = line[0]; while (ch == ' ' || ch == '\t') { memmove(line, line+1, strlen(line)); ch = line[0]; } if (ch == '#') return 1; else { // TODO: strip whitespaces from the key and value // while key[strlen(key)-1 == ' '] struct cfgnode *tmp; if (cfg->count == 0) tmp = cfg->headnode; else { tmp = createnode(); if (!tmp) return 0; if (!addnode(cfg->headnode, tmp)) return 0; } // malloc memory for key and value int c = 0; int doingkey = 1; size_t keybufsize = 1; size_t keysize = 255; size_t valbufsize = 255; size_t valsize = 0; tmp->key = malloc(keybufsize); tmp->value = malloc(valbufsize); if (!tmp->key) return 0; while ((ch = line[c]) != '\0') { if (doingkey) { if (ch == '=') doingkey = 0; else { if (keysize >= keybufsize-1) { keybufsize += 10; tmp->key = realloc(tmp->key, keybufsize); if (!tmp->key) return 0; } cfgappendchar(tmp->key, ch); valsize += sizeof(char); } } else { if (valsize >= valbufsize-1) { valbufsize += 10; tmp->value = realloc(tmp->value, valbufsize); if (!tmp->value) return 0; } cfgappendchar(tmp->value, ch); valsize += sizeof(char); } c++; } cfg->count++; } return 1; } struct cfgnode *createnode(void) { /* * create a cfgnode and return a pointer to it */ struct cfgnode *tmp = malloc(sizeof(struct cfgnode)); if (!tmp) return NULL; tmp->next = NULL; tmp->key = NULL; tmp->value = NULL; return tmp; } int addnode(struct cfgnode *head, struct cfgnode *node) { /* * add a cfgnode to the end head */ if (!head || !node) return 0; struct cfgnode *tmp = head; while (tmp->next) tmp = tmp->next; tmp->next = node; return 1; } void freenodes(struct cfgnode *head) { /* * free all cfgnode in the linked list */ if (!head) return; struct cfgnode *tmp; while (head) { tmp = head; head = head->next; free(tmp->key); free(tmp->value); free(tmp); } } void printlist(struct cfgnode *head) { struct cfgnode *tmp = head; while (tmp) { printf("key: %s\nvalue: %s\n", tmp->key, tmp->value); tmp = tmp->next; } }