diff --git a/.gitignore b/.gitignore index 437da04..df90c65 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o *.d rexbacklight +rexledctl *.swp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c854a90 --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +all: obj/dep rexbacklight rexledctl + +rexbacklight: obj/rexbacklight.o obj/common.o obj/cmd.o + gcc -o rexbacklight $^ + +rexledctl: obj/rexledctl.o obj/common.o obj/cmd.o + gcc -o rexledctl $^ + +obj/rexledctl.o: src/rexbacklight.c + gcc -c -g -o $@ $< -DREXLEDCTL -I"include" -MMD -MP -MF"obj/dep/rexledctl.d" + +obj/%.o: src/%.c + gcc -c -g -o $@ $< -DREXBACKLIGHT -I"include" -MMD -MP -MF"obj/dep/$*.d" + +.PHONY: install +install: rexbacklight rexledctl + install -m755 -o root -g root -s rexbacklight /usr/bin/rexbacklight + install -m755 -o root -g root -s rexledctl /usr/bin/rexledctl + install -m600 -o root -g root rules/91-backlight.rules /etc/udev/rules.d/91-backlight.rules + install -m600 -o root -g root rules/91-leds.rules /etc/udev/rules.d/91-leds.rules + install -m755 -o root -g root rules/rexbacklight.init /etc/init.d/rexbacklight + +.PHONY: uninstall +uninstall: + rm /usr/bin/rexbacklight + rm /usr/bin/rexledctl + rm /etc/udev/rules.d/91-backlight.rules + rm /etc/udev/rules.d/91-leds.rules + rm /etc/init.d/rexbacklight + +obj: + mkdir -p $@ +obj/dep: + mkdir -p $@ + +.PHONY: clean +clean: + rm -rf obj + rm -f rexbacklight + rm -f rexledctl +-include $(wildcard obj/dep/*.d) + diff --git a/TODO b/TODO index 047493c..1e1e46a 100644 --- a/TODO +++ b/TODO @@ -4,3 +4,4 @@ xbacklight compat option (-get/-set/-inc/-dec/-help/-time/-steps) #allow fade in and fade out a lot of cleanup +rename "backlight" things to "device" things because led/backlight ambiguity diff --git a/include/common.h b/include/common.h index c49bb5c..8b2491e 100644 --- a/include/common.h +++ b/include/common.h @@ -26,6 +26,7 @@ #define RETVAL_UNRECOGNIZED_OPTION 3 #define RETVAL_MISSING_OPTION 4 #define RETVAL_INVALID_DEVICE -5 +#define RETVAL_MEM_ERROR 6 #define RETVAL_SUCCESS EXIT_SUCCESS _Noreturn void usage(int exit_val); diff --git a/makefile b/makefile deleted file mode 100644 index 0c2c2f6..0000000 --- a/makefile +++ /dev/null @@ -1,69 +0,0 @@ -#Copyright 2018 rexy712 of Rexy & Co -#Makefile for project 'rexbacklight' - -#Project directory and file setup -SOURCE_DIRS:=src -OBJDIR:=obj -DEPDIR:=obj/dep -INCLUDE_DIRS:=include -EXT:=c -MAIN_EXECUTABLE:=rexbacklight - -#Compiler/Linker setup -CC:=gcc -CFLAGS:=-g -std=c11 -Wall -pedantic -Wextra -release: CFLAGS:=-std=c11 -Wall -pedantic -Wextra -O2 -LDFLAGS= -LDLIBS:= -STRIP:=strip - -#Internal management of sources/objects and additional cflags -INTERNAL_CFLAGS=-c $(foreach dir,$(INCLUDE_DIRS),-I"$(dir)") -MMD -MP -MF"$(DEPDIR)/$*.d" -SOURCES:=$(foreach source,$(SOURCE_DIRS),$(foreach ext,$(EXT),$(wildcard $(source)/*.$(ext)))) -OBJECTS:=$(addprefix $(OBJDIR)/,$(subst \,.,$(subst /,.,$(addsuffix .o,$(SOURCES))))) - -all: $(MAIN_EXECUTABLE) - -$(MAIN_EXECUTABLE): $(OBJECTS) - $(CC) $(LDFLAGS) $^ -o "$(basename $@)" $(LDLIBS) - -.PHONY: release -release: $(OBJECTS) - $(CC) $(LDFLAGS) $^ -o "$(basename $(MAIN_EXECUTABLE))" $(LDLIBS) - $(STRIP) --strip-all "$(MAIN_EXECUTABLE)" - -.PHONY: install -install: $(MAIN_EXECUTABLE) - install -m755 -o root -g root -s "$(MAIN_EXECUTABLE)" /usr/bin/rexbacklight - install -m600 -o root -g root rules/91-backlight.rules /etc/udev/rules.d/91-backlight.rules - install -m755 -o root -g root rules/rexbacklight.init /etc/init.d/rexbacklight - -.PHONY: uninstall -uninstall: - rm /usr/bin/rexbacklight - rm /etc/udev/rules.d/91-backlight-conf - rm /etc/init.d/rexbacklight.init - -define GENERATE_OBJECTS - -$$(OBJDIR)/$(subst \,.,$(subst /,.,$(1))).%.o: $(1)/% - $$(CC) $$(CFLAGS) $$(INTERNAL_CFLAGS) "$$<" -o "$$@" - -endef - -$(foreach dir,$(SOURCE_DIRS),$(eval $(call GENERATE_OBJECTS,$(dir)))) -$(OBJECTS): | $(OBJDIR) $(DEPDIR) - -$(OBJDIR): - mkdir -p "$@" -$(DEPDIR): - mkdir -p "$@" - -.PHONY: clean -clean: - rm -rf "$(DEPDIR)" - rm -rf "$(OBJDIR)" - rm -f "$(MAIN_EXECUTABLE)" --include $(wildcard $(DEPDIR)/*.d) - - diff --git a/rules/91-leds.rules b/rules/91-leds.rules new file mode 100644 index 0000000..a24e2a8 --- /dev/null +++ b/rules/91-leds.rules @@ -0,0 +1,4 @@ +SUBSYSTEM=="leds", ACTION="add", \ + RUN+="/bin/chgrp video %S%p/brightness", \ + RUN+="/bin/chmod g+w %S%p/brightness" + diff --git a/src/common.c b/src/common.c index fead469..549d5fc 100644 --- a/src/common.c +++ b/src/common.c @@ -21,8 +21,11 @@ #include +//name of the program being run so that we print the correct name in the usage +extern const char* executable_name; + _Noreturn void usage(int exit_val){ - printf("Usage: rexbacklight [argument] [options] [argument]\n\n"); + printf("Usage: %s [argument] [options] [argument]\n\n", executable_name); printf("Options:\n"); for(int i = 0;i < rexbacklight_args_length;i++){ @@ -38,7 +41,7 @@ _Noreturn void usage(int exit_val){ printf(" max\n"); printf(" min\n"); - printf("\nrexbacklight Copyright (C) 2018 rexy712\n"); + 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/rexbacklight.c b/src/rexbacklight.c index 5020711..51fae54 100644 --- a/src/rexbacklight.c +++ b/src/rexbacklight.c @@ -29,11 +29,23 @@ #include "common.h" #include "cmd.h" +//name of the program being run so that we print the correct name in the usage + //This is where backlight devices can be found in sysfs +#ifdef REXBACKLIGHT static const char* backlight_dir = "/sys/class/backlight/"; +const char* executable_name = "rexbacklight"; +#elif defined(REXLEDCTL) +static const char* backlight_dir = "/sys/class/leds"; +const char* executable_name = "rexledctl"; +#else +#error "UNDEFINED PROGRAM NAME!" +#endif static const char* backlight_file = "brightness"; static const char* max_backlight_file = "max_brightness"; +static int return_value = RETVAL_SUCCESS; + //Used to store a dynamic array of dynamic strings and number of strings struct string_array{ char** list; @@ -46,11 +58,14 @@ struct string_array{ #define IO_ERROR_READ "read" #define IO_ERROR_WRITE "write to" -void io_error(const char* type, const char* error, const char* name){ +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* type, const char* error, const char* name, const char* name2){ - fprintf(stderr, "Unable to %s %s '%s%s'!\n", error, type, name, name2); +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 mem_error(void){ + fprintf(stderr, "Failed to allocate memory! Unable to continue!\n"); } //Clean up a string array @@ -70,6 +85,7 @@ struct string_array get_backlight_sources(void){ //If the dir can't be opened, return no backlight devices if(!fd){ io_error(IO_ERROR_OPEN, IO_ERROR_DIR, backlight_dir); + return_value = RETVAL_INVALID_DIR; return (struct string_array){.list = NULL, .size = 0}; } @@ -84,7 +100,7 @@ struct string_array get_backlight_sources(void){ } //Resize list if more than 8 backlight devices exist (not likely) - if(i > list_size){ + if(i >= list_size){ char** tmp = malloc(sizeof(const char*) * (list_size += 8)); for(int j = 0;j < i;j++){ tmp[j] = list[j]; @@ -93,8 +109,10 @@ struct string_array get_backlight_sources(void){ list = tmp; } - list[i] = malloc(strlen(dir->d_name) + 1); + int slen = strlen(dir->d_name); + list[i] = malloc(slen + 1); strcpy(list[i], dir->d_name); + list[i][slen] = 0; i++; } @@ -110,10 +128,12 @@ float get_brightness(const char* file){ FILE* bright = fopen(file, "r"); if(!bright){ io_error(IO_ERROR_OPEN, IO_ERROR_FILE, file); + return_value = RETVAL_INVALID_FILE; return 0; } if(!fgets(buff, sizeof(buff), bright)){ io_error(IO_ERROR_READ, IO_ERROR_FILE, file); + return_value = RETVAL_INVALID_FILE; fclose(bright); return 0; } @@ -137,6 +157,7 @@ void fade_out(int iv, int fv, int ms_duration, int steps){ fd = fopen(backlight_file, "w+"); if(!fd){ io_error_2(IO_ERROR_OPEN, IO_ERROR_FILE, backlight_dir, backlight_file); + return_value = RETVAL_INVALID_FILE; return; } fprintf(fd, "%d", (int)value); @@ -160,6 +181,7 @@ void fade_out(int iv, int fv, int ms_duration, int steps){ fd = fopen(backlight_file, "w+"); if(!fd){ io_error_2(IO_ERROR_OPEN, IO_ERROR_FILE, backlight_dir, backlight_file); + return_value = RETVAL_INVALID_FILE; return; } fprintf(fd, "%d", fv); @@ -190,6 +212,7 @@ void individual_device_loop(struct arg_values* a){ for(struct arg_values* curr = a->next;curr;curr = curr->next){ if(chdir(curr->device)){ io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, backlight_dir, curr->device); + return_value = RETVAL_INVALID_DIR; continue; } switch(curr->operation){ @@ -214,9 +237,11 @@ void all_device_loop(struct string_array* backlight_names, struct arg_values* ar for(int i = 0;i < backlight_names->size;i++){ if(chdir(backlight_names->list[i])){ io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, backlight_dir, backlight_names->list[i]); + return_value = RETVAL_INVALID_DIR; continue; } do_assignment(args); + chdir(backlight_dir); } break; case OP_LIST: @@ -226,9 +251,11 @@ void all_device_loop(struct string_array* backlight_names, struct arg_values* ar for(int i = 0;i < backlight_names->size;i++){ if(chdir(backlight_names->list[i])){ io_error_2(IO_ERROR_OPEN, IO_ERROR_DIR, backlight_dir, backlight_names->list[i]); + return_value = RETVAL_INVALID_DIR; continue; } do_get(backlight_names->list[i]); + chdir(backlight_dir); } break; } @@ -250,7 +277,13 @@ int main(int argc, char** argv){ //If there are no backlights, we can't do anything if(backlight_names.size == 0){ +#ifdef REXBACKLIGHT fprintf(stderr, "No backlights devices found!\n"); +#elif defined(REXLEDCTL) + fprintf(stderr, "No led devices found!\n"); +#else +#error "UNDEFINED PROGRAM NAME!" +#endif CLEANUP(); return RETVAL_INVALID_DEVICE; } @@ -268,7 +301,16 @@ int main(int argc, char** argv){ continue_outer:; } - char* starting_dir = getcwd(NULL, 0); + int starting_dir_max_len = pathconf(".", _PC_PATH_MAX); + char* starting_dir = malloc(starting_dir_max_len); + if(!starting_dir){ + mem_error(); + CLEANUP(); + return RETVAL_MEM_ERROR; + } + if(!getcwd(starting_dir, starting_dir_max_len)){ + fprintf(stderr, "Unable to determine starting dir!\nWill be unable to return to it on completion!\n"); + } #undef CLEANUP #define CLEANUP() do{free_string_array(&backlight_names);free_cmd_args(&args);free(starting_dir);}while(0) @@ -300,6 +342,6 @@ int main(int argc, char** argv){ } CLEANUP(); - return RETVAL_SUCCESS; + return return_value; } #undef CLEANUP