diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/config.c | 231 | ||||
-rw-r--r-- | src/config.h | 37 |
3 files changed, 270 insertions, 0 deletions
@@ -6,6 +6,8 @@ INITDIR=/etc/rc.d all: cc $(CCOPTS) $(DBG) src/main.c -o luminous + if [ ! -d obj ]; then mkdir obj; fi + cc $(CCOPTS) $(DBG) src/config.c -c -o obj/config.o install: install -D luminous ${DESTDIR}/${BINDIR}/luminous diff --git a/src/config.c b/src/config.c new file mode 100644 index 0000000..1ff9a2b --- /dev/null +++ b/src/config.c @@ -0,0 +1,231 @@ +/** + * Copyright (C) 2017 Aaron Ball <nullspoon@oper.io> + * + * Luminous 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. + * + * Luminous 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 noteless. If not, see <http://www.gnu.org/licenses/>. + */ +#include "config.h" + + +/** + * config_new: + * @c Config struct to initialize + * @path Path to the config file to initialize from (only used by config_load) + * + * Config struct constructor. + * + * Returns success (0) or failure (-1). Failure occurs when specified config + * file is not accessible or could not be found. + */ +int config_new(struct config* c, const char* path) { + FILE* fd; + + // Check if the config file exists + fd = fopen(path, "r"); + if(!fd) + return -1; + fclose(fd); + + c->count = 0; + c->path = path; + c->keys = malloc(0); + c->vals = malloc(0); + return 0; +} + + +/** + * line_get_key: + * @line Line to search for key in + * @start Pointer to integer holding substring start index + * @end Pointer to integer holding substring end index + * + * Searches the specified string for a key (preceeding an '=' delimiter). + * + * Returns Length of found key, otherwise -1. + */ +int line_get_key(char* line, int* start, int* end) { + *start = 0; + *end = 0; + + // Find beginning of key, allowing for preceeding whitespace + while(line[*start] == ' ' && line[*start] != '\0') + *start = *start + 1; + + // Return error if no non-whitespace text was found + if(line[*start] == '\0') + return -1; + + *end = *start; + + // Find the end of the key + while(line[*end] != ' ' && line[*end] != '=' && line[*end] != '\0') + *end = *end + 1; + + return *end - *start; +} + + +/** + * line_get_val: + * @line Line to search for value in + * @start Pointer to integer holding substring start index + * @end Pointer to integer holding substring end index + * + * Searches the specified string for a value (following an '=' delimiter). + * + * Returns Length of found value, otherwise -1. + */ +int line_get_val(char* line, int* start, int* end) { + *start = 0; + *end = 0; + + // Find beginning of key, allowing for preceeding whitespace + // Set the start cursor to the first non-whitespace character after the + // equals sign + while(line[*start] != '=' && line[*start] != '\0') + *start = *start + 1; + + // Advance one to pass the equals sign + *start = *start + 1; + + // A seperate loop to handle leading whitespace. Having this outside of the + // previous loop prevents us from allowing for multiple contiguous equals + // signs + while(line[*start] == ' ') + *start = *start + 1; + + // Return error if no equals sign was found + if(line[*start] == '\0') + return -1; + + // Find the end of the string, not including the newline char if one is + // present (this is why we don't use strlen, becuase it includes the index of + // the newline char if one is present) + while(line[*end] != '\n' && line[*end] != '\0') + *end = *end + 1; + + return *end - *start; +} + + +/** + * config_load: + * @c Config struct to load config data into + * + * Returns number of config items found in the config file + */ +int config_load(struct config* c) { + // Values for tracking config line component start and end indexes + int keystart = 0, keyend = 0, keylen = 0; + int valstart = 0, valend = 0, vallen = 0; + char buf[512]; // Config line buffer + FILE* fd; // Config file descriptor + + fd = fopen(c->path, "r"); + + while(fgets(buf, 512, fd) != NULL) { + c->count++; + + // Allocate array space for new keys and values + c->keys = realloc(c->keys, sizeof(char*) * c->count); + c->vals = realloc(c->vals, sizeof(char*) * c->count); + + // Get the key start and end index + keylen = line_get_key(buf, &keystart, &keyend); + // Allocate space for new key + c->keys[c->count - 1] = malloc(keylen + 1); + // Copy the key into the new memory + strncpy(c->keys[c->count - 1], &buf[keystart], keylen); + // Dont' forget the null byte! + c->keys[c->count - 1][keylen] = '\0'; + + // Do the exact same thing for the value + vallen = line_get_val(buf, &valstart, &valend); + c->vals[c->count - 1] = malloc(vallen + 1); + strncpy(c->vals[c->count - 1], &buf[valstart], vallen); + c->vals[c->count - 1][vallen] = '\0'; + + // Reset our index variables + keystart = 0, keyend = 0, keylen = 0; + valstart = 0, valend = 0, vallen = 0; + } + + fclose(fd); + + return c->count; +} + + +/** + * config_dump: + * @c Config struct to dump + * @fd File descriptor to print dump text to. If NULL, prints to stdout + * + * Dumps the provided config struct to the specified file descriptor. + */ +void config_dump(struct config* c, FILE* fd) { + int i = 0; + if(!fd) + fd = stdout; + + while(i < c->count) { + fprintf(fd, "%d %s %s\n", i, c->keys[i], c->vals[i]); + i++; + } +} + + +/** + * config_get: + * @c Config struct to search for a matching key + * @key Config key to find value for + * @out Output buffer to copy value to + * + * Returns Status integer (0 == key found, -1 == key not found) + */ +int config_get(struct config* c, char* key, char* out) { + int i = 0; + + while(i < c->count) { + // Copy value for matching key to output buffer + if(strcmp(c->keys[i], key) == 0) { + strcpy(out, c->vals[i]); + return 0; + } + i++; + } + + // If we reach this point, no matching keys were found + return -1; +} + + +/** + * config_free: + * @c Config struct to free + */ +int config_free(struct config* c) { + while(c->count > 0) { + // Free the corresponding + free(c->keys[c->count - 1]); + free(c->vals[c->count - 1]); + c->count--; + } + + // Free the array space + free(c->keys); + free(c->vals); + + return 0; +} diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..247efb3 --- /dev/null +++ b/src/config.h @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2017 Aaron Ball <nullspoon@oper.io> + * + * Luminous 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. + * + * Luminous 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 noteless. If not, see <http://www.gnu.org/licenses/>. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +struct config { + const char* path; + int count; // Number of config entries + char** keys; + char** vals; +}; + + +int config_new(struct config*, const char*); + +int config_load(struct config*); + +void config_dump(struct config*, FILE*); + +int config_get(struct config*, char*, char*); + +int config_free(struct config*); |