summaryrefslogtreecommitdiff
path: root/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfg.c')
-rw-r--r--cfg.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/cfg.c b/cfg.c
new file mode 100644
index 0000000..ddfd113
--- /dev/null
+++ b/cfg.c
@@ -0,0 +1,288 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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
+appendchar(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;
+ }
+ appendchar(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 = 30;
+ size_t valbufsize = 30;
+ 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;
+ }
+ appendchar(tmp->key, ch);
+ valsize += sizeof(char);
+ }
+ }
+ else
+ {
+ if (valsize >= valbufsize-1)
+ {
+ valbufsize += 10;
+ tmp->value = realloc(tmp->value, valbufsize);
+ if (!tmp->value)
+ return 0;
+ }
+ appendchar(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;
+ }
+}