From abb03dcd40bbdd78c4f01670e7f34b73cbbe03e3 Mon Sep 17 00:00:00 2001 From: rexy712 Date: Tue, 4 Dec 2018 13:13:51 -0800 Subject: [PATCH] Moved restore file logic into its own file --- CMakeLists.txt | 2 +- include/cmd.h | 2 +- include/common.h | 17 +++- include/globals.h | 28 +++++++ include/restore.h | 36 ++++++++ include/rexbacklight.h | 27 ++++++ src/common.c | 25 ++++-- src/restore.c | 136 ++++++++++++++++++++++++++++++ src/rexbacklight.c | 184 +++++++---------------------------------- 9 files changed, 293 insertions(+), 164 deletions(-) create mode 100644 include/globals.h create mode 100644 include/restore.h create mode 100644 include/rexbacklight.h create mode 100644 src/restore.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 969c4ba..affbc50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ find_library(RJP_LIB rjp) find_path(RJP_HEADER_DIR rjp.h) #temporary library (no actual library generated) -add_library(common_srcs OBJECT src/cmd.c src/common.c) +add_library(common_srcs OBJECT src/cmd.c src/common.c src/restore.c) if(BUILD_REXLEDCTL) add_executable (rexledctl src/rexbacklight.c) diff --git a/include/cmd.h b/include/cmd.h index 23b0545..9eb435c 100644 --- a/include/cmd.h +++ b/include/cmd.h @@ -16,7 +16,7 @@ along with this program. If not, see . */ -#ifndef RECBACKLIGHT_CMD_H +#ifndef REXBACKLIGHT_CMD_H #define REXBACKLIGHT_CMD_H #define OP_INC 1 diff --git a/include/common.h b/include/common.h index 6979d3d..ec2af52 100644 --- a/include/common.h +++ b/include/common.h @@ -30,11 +30,26 @@ #define RETVAL_INTERNAL_ERROR 7 #define RETVAL_SUCCESS EXIT_SUCCESS +#define IO_ERROR_DIR "directory" +#define IO_ERROR_FILE "file" +#define IO_ERROR_OPEN "open" +#define IO_ERROR_READ "read" +#define IO_ERROR_WRITE "write to" + +void io_error(const char* error, const char* type, const char* name); +void io_error_2(const char* error, const char* type, const char* name, const char* name2); +void io_error_3(const char* error, const char* type, const char* name, const char* name2, const char* name3); + + extern int return_value; +struct string_array{ + char** list; + int size; +}; + void mem_error(void); _Noreturn void version(void); _Noreturn void usage(int exit_val); - #endif diff --git a/include/globals.h b/include/globals.h new file mode 100644 index 0000000..f06c1dc --- /dev/null +++ b/include/globals.h @@ -0,0 +1,28 @@ +/** + rexbacklight + Copyright (C) 2018 rexy712 + + 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 . +*/ + +#ifndef GLOBALS_H +#define GLOBALS_H + +const char* device_dir(void); +const char* executable_name(void); +const char* restore_file(void); +const char* brightness_file(void); +const char* max_brightness_file(void); + +#endif diff --git a/include/restore.h b/include/restore.h new file mode 100644 index 0000000..630f8d8 --- /dev/null +++ b/include/restore.h @@ -0,0 +1,36 @@ +/** + rexbacklight + Copyright (C) 2018 rexy712 + + 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 . +*/ + +#ifndef RESTORE_H +#define RESTORE_H + +#include + +#include "common.h" +#include "cmd.h" + +void save_restore_file(struct string_array* devices); +void process_restore_file(void); +int prep_restore(struct arg_values* curr, RJP_value** root, int* try_restore); +RJP_value* find_matching_json_device(const char* name, RJP_value* root); +RJP_value* read_restore_file(const char* file); +char* get_home_folder(); +char* get_home_restore_file(); + + +#endif diff --git a/include/rexbacklight.h b/include/rexbacklight.h new file mode 100644 index 0000000..5c21082 --- /dev/null +++ b/include/rexbacklight.h @@ -0,0 +1,27 @@ +/** + rexbacklight + Copyright (C) 2018 rexy712 + + 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 . +*/ + +#ifndef REXBACKLIGHT_H +#define REXBACKLIGHT_H + +#include "cmd.h" + +float get_brightness(const char* file); +int individual_device_op(struct arg_values* curr); + +#endif diff --git a/src/common.c b/src/common.c index 7c683af..97e4cee 100644 --- a/src/common.c +++ b/src/common.c @@ -19,27 +19,36 @@ #include "config.h" #include "common.h" #include "cmd.h" +#include "globals.h" -#include +#include //printf int return_value = RETVAL_SUCCESS; +void io_error(const char* error, const char* type, const char* name){ + fprintf(stderr, "Unable to %s %s '%s'!\n", error, type, name); +} +void io_error_2(const char* error, const char* type, const char* name, const char* name2){ + fprintf(stderr, "Unable to %s %s '%s%s'!\n", error, type, name, name2); +} +void io_error_3(const char* error, const char* type, const char* name, const char* name2, const char* name3){ + fprintf(stderr, "Unable to %s %s '%s%s%s'!\n", error, type, name, name2, name3); +} + + void mem_error(void){ fprintf(stderr, "Failed to allocate memory! Unable to continue!\n"); } -//name of the program being run so that we print the correct name in the usage -extern const char* executable_name; - _Noreturn void version(void){ - printf("%s version %d.%d\n", executable_name, REXBACKLIGHT_VERSION_MAJOR, REXBACKLIGHT_VERSION_MINOR); + printf("%s version %d.%d\n", executable_name(), REXBACKLIGHT_VERSION_MAJOR, REXBACKLIGHT_VERSION_MINOR); exit(return_value); } _Noreturn void usage(int exit_val){ int i; - printf("%s version %d.%d\n\n", executable_name, REXBACKLIGHT_VERSION_MAJOR, REXBACKLIGHT_VERSION_MINOR); - printf("Usage: %s [argument] [options] [argument]\n\n", executable_name); + printf("%s version %d.%d\n\n", executable_name(), REXBACKLIGHT_VERSION_MAJOR, REXBACKLIGHT_VERSION_MINOR); + printf("Usage: %s [argument] [options] [argument]\n\n", executable_name()); printf("Options:\n"); for(i = 0;i < rexbacklight_args_length;++i){ @@ -74,7 +83,7 @@ _Noreturn void usage(int exit_val){ printf(" max\n"); printf(" min\n"); - printf("\n%s Copyright (C) 2018 rexy712\n", executable_name); + printf("\n%s Copyright (C) 2018 rexy712\n", executable_name()); printf("This program comes with ABSOLUTELY NO WARRANTY.\n"); printf("This is free software, and you are welcome to redistribute it\n"); printf("under certain conditions; see the GNU GPLv3 for details.\n"); diff --git a/src/restore.c b/src/restore.c new file mode 100644 index 0000000..f049987 --- /dev/null +++ b/src/restore.c @@ -0,0 +1,136 @@ +/** + rexbacklight + Copyright (C) 2018 rexy712 + + 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 //stat, mkdir +#include //stat, mkdir +#include //stat, mkdir +#include //strcmp +#include + +#include "restore.h" +#include "common.h" +#include "cmd.h" +#include "globals.h" +#include "rexbacklight.h" + +RJP_value* read_restore_file(const char* file){ + size_t filesize; + char* file_contents; + int i; + FILE* fp = fopen(file, "r"); + if(!fp){ + fprintf(stderr, "Could not restore! No restore file found!\n"); + return NULL; + } + + fseek(fp, 0, SEEK_END); + filesize = ftell(fp); + fseek(fp, 0, SEEK_SET); + + file_contents = malloc(filesize+1); + i = fread(file_contents, filesize, 1, fp); + fclose(fp); + file_contents[filesize] = 0; + RJP_value* root = rjp_parse(file_contents); + free(file_contents); + return root; +} + +RJP_value* find_matching_json_device(const char* name, RJP_value* root){ + for(RJP_value* curr = rjp_get_member(root);curr;curr = rjp_next_member(curr)){ + if(!strcmp(rjp_member_name(curr), name)){ + return curr; + } + } + return NULL; +} +int prep_restore(struct arg_values* curr, RJP_value** root, int* try_restore){ + if(!*root && *try_restore){ + *root = read_restore_file(restore_file()); + if(!*root){ + *try_restore = 0; + return 0; + } + } + RJP_value* match = find_matching_json_device(curr->device, *root); + if(!match){ + fprintf(stderr, "No matching device '%s' in restore file!\n", curr->device); + return 0; + } + curr->operation = OP_SET; + curr->delta = rjp_value_dfloat(match); + return 1; +} +void process_restore_file(void){ + RJP_value* root = read_restore_file(restore_file()); + if(!root) + return; + struct arg_values tmp = {.next = NULL, + .fade_duration = 0, + .fade_steps = 1, + .operation = OP_SET}; + for(RJP_value* curr = rjp_get_member(root);curr;curr = rjp_next_member(curr)){ + tmp.device = rjp_member_name(curr); + tmp.delta = rjp_value_dfloat(curr); + individual_device_op(&tmp); + } + rjp_free_value(root); +} +void save_restore_file(struct string_array* devices){ + RJP_value* root = rjp_init_json(); + for(size_t i = 0;i < devices->size;++i){ + if(chdir(devices->list[i])){ + io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir(), devices->list[i]); + return_value = RETVAL_INVALID_DIR; + continue; + } + size_t esc_name_len = rjp_escape_strlen(devices->list[i]); + char* esc_str = rjp_alloc(esc_name_len + 1); + rjp_escape_strcpy(esc_str, devices->list[i]); + + float curr = get_brightness(brightness_file()); + float max = get_brightness(max_brightness_file()); + if(return_value == RETVAL_INVALID_FILE && (!curr || !max)){ + rjp_add_member(root, 0, esc_str, 0, rjp_null()); + }else{ + rjp_add_member(root, 0, esc_str, 0, rjp_dfloat(curr/max*100)); + } + + if(chdir(device_dir())){ + io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir()); + return_value = RETVAL_INVALID_DIR; + rjp_free_value(root); + free(esc_str); + return; + } + } + char* tmp = rjp_to_json(root); + FILE* restf = fopen(restore_file(), "w"); + if(!restf){ + io_error(IO_ERROR_OPEN, IO_ERROR_FILE, restore_file()); + }else{ + fprintf(restf, "//File generated by %s\n%s\n", executable_name(), tmp); + fclose(restf); + } + rjp_free(tmp); + rjp_free_value(root); +} + + + diff --git a/src/rexbacklight.c b/src/rexbacklight.c index 82e67e4..685874d 100644 --- a/src/rexbacklight.c +++ b/src/rexbacklight.c @@ -30,46 +30,26 @@ #include "common.h" #include "cmd.h" +#include "restore.h" +#include "globals.h" //name of the program being run so that we print the correct name in the usage #ifdef REXBACKLIGHT //This is where backlight devices can be found in sysfs -static const char* device_dir = "/sys/class/backlight/"; -const char* executable_name = "rexbacklight"; -static const char* restore_file = "/var/tmp/rexbacklight.json"; +const char* device_dir(void){return "/sys/class/backlight/";} +const char* executable_name(void){return "rexbacklight";} +const char* restore_file(void){return "/var/tmp/rexbacklight.json";} #elif defined(REXLEDCTL) //This is where led devices can be found in sysfs -static const char* device_dir = "/sys/class/leds"; -const char* executable_name = "rexledctl"; -static const char* restore_file = "/var/tmp/rexledctl.json"; +const char* device_dir(void){return "/sys/class/leds/";} +const char* executable_name(void){return "rexledctl";} +const char* restore_file(void){return "/var/tmp/rexledctl.json";} #else #error "UNDEFINED PROGRAM NAME!" #endif -static const char* brightness_file = "brightness"; -static const char* max_brightness_file = "max_brightness"; - -//Used to store a dynamic array of dynamic strings and number of strings -struct string_array{ - char** list; - int size; -}; - -#define IO_ERROR_DIR "directory" -#define IO_ERROR_FILE "file" -#define IO_ERROR_OPEN "open" -#define IO_ERROR_READ "read" -#define IO_ERROR_WRITE "write to" - -void io_error(const char* error, const char* type, const char* name){ - fprintf(stderr, "Unable to %s %s '%s'!\n", error, type, name); -} -void io_error_2(const char* error, const char* type, const char* name, const char* name2){ - fprintf(stderr, "Unable to %s %s '%s%s'!\n", error, type, name, name2); -} -void io_error_3(const char* error, const char* type, const char* name, const char* name2, const char* name3){ - fprintf(stderr, "Unable to %s %s '%s%s%s'!\n", error, type, name, name2, name3); -} +const char* brightness_file(void){return "brightness";} +const char* max_brightness_file(void){return "max_brightness";} //Clean up a string array void free_string_array(struct string_array* s){ @@ -86,9 +66,9 @@ struct string_array get_device_sources(void){ struct string_array arr = {0}; int list_size = 8; - fd = opendir(device_dir); + fd = opendir(device_dir()); if(!fd){ - io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir); + io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir()); return_value = RETVAL_INVALID_DIR; return arr; } @@ -174,9 +154,9 @@ void fade_out(const char* device_name, int iv, int fv, int ms_duration, int step while(ms_duration > tdelta){ //write gettimeofday(&start, NULL); - fd = fopen(brightness_file, "w+"); + fd = fopen(brightness_file(), "w+"); if(!fd){ - io_error_3(IO_ERROR_OPEN, IO_ERROR_FILE, device_dir, device_name, brightness_file); + io_error_3(IO_ERROR_OPEN, IO_ERROR_FILE, device_dir(), device_name, brightness_file()); return_value = RETVAL_INVALID_FILE; return; } @@ -201,9 +181,9 @@ void fade_out(const char* device_name, int iv, int fv, int ms_duration, int step //calc end of next step step_delta += step_inc; } - fd = fopen(brightness_file, "w+"); + fd = fopen(brightness_file(), "w+"); if(!fd){ - io_error_3(IO_ERROR_OPEN, IO_ERROR_FILE, device_dir, device_name, brightness_file); + io_error_3(IO_ERROR_OPEN, IO_ERROR_FILE, device_dir(), device_name, brightness_file()); return_value = RETVAL_INVALID_FILE; return; } @@ -214,16 +194,16 @@ void fade_out(const char* device_name, int iv, int fv, int ms_duration, int step //Write value to device files void do_assignment(struct arg_values* arg, const char* device){ - int start = get_brightness(brightness_file); - int out = process_op(arg, 0, start, get_brightness(max_brightness_file)); + int start = get_brightness(brightness_file()); + int out = process_op(arg, 0, start, get_brightness(max_brightness_file())); fade_out(device, start, out, arg->fade_duration, arg->fade_steps); } //Run get operation void do_get(const char* device){ float curr, max; - curr = get_brightness(brightness_file); - max = get_brightness(max_brightness_file); + curr = get_brightness(brightness_file()); + max = get_brightness(max_brightness_file()); if(return_value == RETVAL_INVALID_FILE && (!curr || !max)){ fprintf(stdout, "%s", device); }else{ @@ -238,31 +218,9 @@ void do_list(struct string_array* names){ fprintf(stdout, "%s\n", names->list[i]); } -RJP_value* read_restore_file(const char* file){ - size_t filesize; - char* file_contents; - int i; - FILE* fp = fopen(file, "r"); - if(!fp){ - fprintf(stderr, "Could not restore! No restore file found!\n"); - return NULL; - } - - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - fseek(fp, 0, SEEK_SET); - - file_contents = malloc(filesize+1); - i = fread(file_contents, filesize, 1, fp); - fclose(fp); - file_contents[filesize] = 0; - RJP_value* root = rjp_parse(file_contents); - free(file_contents); - return root; -} int individual_device_op(struct arg_values* curr){ if(chdir(curr->device)){ - io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir, curr->device); + io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir(), curr->device); return RETVAL_INVALID_DIR; } switch(curr->operation){ @@ -275,38 +233,13 @@ int individual_device_op(struct arg_values* curr){ do_get(curr->device); break; } - if(chdir(device_dir)){ - io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir); + if(chdir(device_dir())){ + io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir()); return RETVAL_INTERNAL_ERROR; } return return_value; } -RJP_value* find_matching_json_device(const char* name, RJP_value* root){ - for(RJP_value* curr = rjp_get_member(root);curr;curr = rjp_next_member(curr)){ - if(!strcmp(rjp_member_name(curr), name)){ - return curr; - } - } - return NULL; -} -int prep_restore(struct arg_values* curr, RJP_value** root, int* try_restore){ - if(!*root && *try_restore){ - *root = read_restore_file(restore_file); - if(!*root){ - *try_restore = 0; - return 0; - } - } - RJP_value* match = find_matching_json_device(curr->device, *root); - if(!match){ - fprintf(stderr, "No matching device '%s' in restore file!\n", curr->device); - return 0; - } - curr->operation = OP_SET; - curr->delta = rjp_value_dfloat(match); - return 1; -} //If devices were specified, this function will run void individual_device_loop(struct arg_values* a){ struct arg_values* curr; @@ -326,21 +259,6 @@ void individual_device_loop(struct arg_values* a){ rjp_free_value(root); } -void process_restore_file(void){ - RJP_value* root = read_restore_file(restore_file); - if(!root) - return; - struct arg_values tmp = {.next = NULL, - .fade_duration = 0, - .fade_steps = 1, - .operation = OP_SET}; - for(RJP_value* curr = rjp_get_member(root);curr;curr = rjp_next_member(curr)){ - tmp.device = rjp_member_name(curr); - tmp.delta = rjp_value_dfloat(curr); - individual_device_op(&tmp); - } - rjp_free_value(root); -} //If no devices were specified, this function will run void all_device_loop(struct string_array* device_names, struct arg_values* args){ @@ -351,13 +269,13 @@ void all_device_loop(struct string_array* device_names, struct arg_values* args) case OP_DEC: for(i = 0;i < device_names->size;++i){ if(chdir(device_names->list[i])){ - io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir, device_names->list[i]); + io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir(), device_names->list[i]); return_value = RETVAL_INVALID_DIR; continue; } do_assignment(args, device_names->list[i]); - if(chdir(device_dir)){ - io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir); + if(chdir(device_dir())){ + io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir()); return_value = RETVAL_INVALID_DIR; return; } @@ -369,13 +287,13 @@ void all_device_loop(struct string_array* device_names, struct arg_values* args) case OP_GET: for(i = 0;i < device_names->size;++i){ if(chdir(device_names->list[i])){ - io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir, device_names->list[i]); + io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir(), device_names->list[i]); return_value = RETVAL_INVALID_DIR; continue; } do_get(device_names->list[i]); - if(chdir(device_dir)){ - io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir); + if(chdir(device_dir())){ + io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir()); return_value = RETVAL_INVALID_DIR; return; } @@ -390,46 +308,6 @@ void all_device_loop(struct string_array* device_names, struct arg_values* args) } } -void save_restore_file(struct string_array* devices){ - RJP_value* root = rjp_init_json(); - for(size_t i = 0;i < devices->size;++i){ - if(chdir(devices->list[i])){ - io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir, devices->list[i]); - return_value = RETVAL_INVALID_DIR; - continue; - } - size_t esc_name_len = rjp_escape_strlen(devices->list[i]); - char* esc_str = rjp_alloc(esc_name_len + 1); - rjp_escape_strcpy(esc_str, devices->list[i]); - - float curr = get_brightness(brightness_file); - float max = get_brightness(max_brightness_file); - if(return_value == RETVAL_INVALID_FILE && (!curr || !max)){ - rjp_add_member(root, 0, esc_str, 0, rjp_null()); - }else{ - rjp_add_member(root, 0, esc_str, 0, rjp_dfloat(curr/max*100)); - } - - if(chdir(device_dir)){ - io_error(IO_ERROR_OPEN, IO_ERROR_DIR, device_dir); - return_value = RETVAL_INVALID_DIR; - rjp_free_value(root); - free(esc_str); - return; - } - } - char* tmp = rjp_to_json(root); - FILE* restf = fopen(restore_file, "w"); - if(!restf){ - io_error(IO_ERROR_OPEN, IO_ERROR_FILE, restore_file); - }else{ - fprintf(restf, "//File generated by %s\n%s\n", executable_name, tmp); - fclose(restf); - } - rjp_free(tmp); - rjp_free_value(root); -} - int main(int argc, char** argv){ struct arg_values args; //A linked list of devices and the requested settings. @@ -477,8 +355,8 @@ int main(int argc, char** argv){ } //Change to the base directory for all sysfs leds/backlights - if(chdir(device_dir)){ - io_error(IO_ERROR_READ, IO_ERROR_DIR, device_dir); + if(chdir(device_dir())){ + io_error(IO_ERROR_READ, IO_ERROR_DIR, device_dir()); CLEANUP(); return RETVAL_INVALID_DIR; }