diff options
-rw-r--r-- | Makefile | 15 | ||||
-rw-r--r-- | sample.conf | 3 | ||||
-rw-r--r-- | src/config.c | 231 | ||||
-rw-r--r-- | src/config.h | 37 | ||||
-rw-r--r-- | src/main.c | 78 |
5 files changed, 349 insertions, 15 deletions
@@ -3,13 +3,22 @@ CCOPTS=-Wall BINDIR=/usr/bin INITDIR=/etc/rc.d +CONFDIR=/etc/ 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 + cc $(CCOPTS) $(DBG) obj/*.o src/main.c -o luminous install: - install -D luminous ${DESTDIR}/${BINDIR}/luminous - install -D init.sh ${DESTDIR}/${INITDIR}/luminous + install -D luminous ${DESTDIR}/${BINDIR}/luminous + install -D init.sh ${DESTDIR}/${INITDIR}/luminous + install -D sample.conf ${DESTDIR}/${CONFDIR}/luminous.conf debug: make DBG=-g + +leak-test: + make debug + valgrind --error-exitcode=1 luminous -l 800 && printf "\n\n--- No leaks found!\n\n" + valgrind --error-exitcode=1 luminous -l 150 && printf "\n\n--- No leaks found!\n\n" diff --git a/sample.conf b/sample.conf new file mode 100644 index 0000000..da257f9 --- /dev/null +++ b/sample.conf @@ -0,0 +1,3 @@ +level = 150 +rate = 20 +step = 12 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*); @@ -20,6 +20,10 @@ #include <time.h> #include <errno.h> +#include "config.h" + +#define CONF "/etc/luminous.conf" + struct props { int lvl; @@ -32,6 +36,17 @@ struct props { }; +void props_new(struct props* p) { + p->lvl = -1; + p->step = -1; + p->rate = -1; + p->max = -1; + p->cur = -1; + p->filebrightness[0] = '\0'; + p->filemax_bright[0] = '\0'; +} + + /** * fgeti: * @path @@ -183,7 +198,7 @@ void usage() { * returns: Success (0), failure (-1), or incomplete (-2) */ int parseargs(struct props* out, int argc, char* argv[]) { - int i = 0; + int i; strcpy(out->filebrightness, "/sys/class/backlight/intel_backlight/brightness"); @@ -194,11 +209,7 @@ int parseargs(struct props* out, int argc, char* argv[]) { out->cur = fgeti(out->filebrightness); out->max = fgeti(out->filemax_bright); - // Some defaults - out->rate = 10; - out->step = 8; - - for(;i < argc; i++) { + for(i = 0; i < argc; i++) { if(strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--rate") == 0) { i++; out->rate = atoi(argv[i]); @@ -221,6 +232,14 @@ int parseargs(struct props* out, int argc, char* argv[]) { } } + // Some defaults, if no values are set yet + if(out->rate < 0) + out->rate = 20; + if(out->step < 0) + out->step = 12; + if(out->lvl == -1) + out->lvl = 200; + // Ensure min and max thresholds are respected if(out->lvl > out->max) { out->lvl = out->max; @@ -231,6 +250,38 @@ int parseargs(struct props* out, int argc, char* argv[]) { } +int config_to_props(char* confpath, struct props* p) { + struct config c; + char lvlbuf[32]; // Buffer to store config value for "level" if found + char ratebuf[32]; // Buffer to store config value for "rate" if found + char stepbuf[32]; // Buffer to store config value for "step" if found + + if(config_new(&c, confpath) == 0) { + config_load(&c); + } else { + // Config file not found, return -2 code + return -2; + } + + // If the config specifies a "level" key, set it to the props object + if(config_get(&c, "level", lvlbuf) == 0) + p->lvl = atoi(lvlbuf); + + // If the config specifies a "step" key, set it to the props object + if(config_get(&c, "step", stepbuf) == 0) + p->step = atoi(stepbuf); + + // If the config specifies a "rate" key, set it to the props object + if(config_get(&c, "rate", ratebuf) == 0) + p->rate = atoi(ratebuf); + + // Don't forget to clean up! + config_free(&c); + + return 0; +} + + /** * Ye olde main */ @@ -238,16 +289,19 @@ int main(int argc, char* argv[]) { int r = 0; struct props p; + props_new(&p); + + // Load configs into properties struct + config_to_props(CONF, &p); + + // Parse cli arguments (overriding any configs if specified at runtime) if(parseargs(&p, argc, argv) != 0) return 1; - if(argc == 1) { - printf("%d\n", p.cur); - return 0; - } - // Determine if we should fade up or fade down - if(p.lvl > p.cur) { + if(p.lvl < 0) { + printf("%d\n", p.cur); + } else if(p.lvl > p.cur) { r = fadeup(&p); } else if (p.lvl < p.cur) { r = fadedown(&p); |