commit
3299a68059
@ -0,0 +1,6 @@ |
||||
**/*.o |
||||
sbl* |
||||
tests/** |
||||
!**/*.c |
||||
!**/*.1 |
||||
|
@ -0,0 +1,25 @@ |
||||
GLWT(Good Luck With That) Public License |
||||
Copyright (c) Everyone, except Author |
||||
|
||||
Everyone is permitted to copy, distribute, modify, merge, sell, publish, |
||||
sublicense or whatever they want with this software but at their OWN RISK. |
||||
|
||||
Preamble |
||||
|
||||
The author has absolutely no clue what the code in this project does. |
||||
It might just work or not, there is no third option. |
||||
|
||||
|
||||
GOOD LUCK WITH THAT PUBLIC LICENSE |
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION, AND MODIFICATION |
||||
|
||||
0. You just DO WHATEVER YOU WANT TO as long as you NEVER LEAVE A |
||||
TRACE TO TRACK THE AUTHOR of the original product to blame for or hold |
||||
responsible. |
||||
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
|
||||
Good luck and Godspeed. |
@ -0,0 +1,27 @@ |
||||
# Simple backlight |
||||
Simple utility to change the backlight |
||||
|
||||
## Features |
||||
- Set the monitor to change |
||||
- Save and restore backlight |
||||
- Written in C99, that is a pro i guess... |
||||
|
||||
## Getting |
||||
Clone this repository, then use `make` to compile, `make install` and `make |
||||
uninstall` to install and uninstall, finally `make clean` to remove all the |
||||
compiled junk from the folder. |
||||
|
||||
## Usage |
||||
Here are some examples: |
||||
|
||||
```sh |
||||
# Increase brightness by 10% and save the changed brightness to $HOME/.savefile |
||||
$ sbl -c $HOME/.savefile -S -i 10 |
||||
# Set the brightness to 30% |
||||
$ sbl -s 30 |
||||
# Restore the saved backlight value from example 1 |
||||
$ sbl -c $HOME/.savefile -r |
||||
# Forgot what does what? |
||||
$ sbl -h |
||||
``` |
||||
Read the man page for detailed instructions |
@ -0,0 +1,25 @@ |
||||
CC ?= gcc
|
||||
CFLAGS = -Wall -pedantic --std=c99 -O2
|
||||
PREFIX = /usr/local
|
||||
MANPREFIX = ${PREFIX}/share/man
|
||||
|
||||
sbl: sbl.c |
||||
|
||||
dbg: |
||||
gcc -O0 -g sbl.c -o sbl-dbg
|
||||
|
||||
install: sbl |
||||
mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||
cp -f sbl ${DESTDIR}${PREFIX}/bin/sbl
|
||||
chown root:root ${DESTDIR}${PREFIX}/bin/sbl
|
||||
chmod 4755 ${DESTDIR}${PREFIX}/bin/sbl
|
||||
mkdir -p ${DESTDIR}${MANPREFIX}/man1
|
||||
cp -f sbl.1 ${DESTDIR}${MANPREFIX}/man1/sbl.1
|
||||
chmod 644 ${DESTDIR}${MANPREFIX}/man1/sbl.1
|
||||
|
||||
uninstall: |
||||
rm -f ${DESTDIR}${PREFIX}/bin/sbl\
|
||||
${DESTDIR}${MANPREFIX}/man1/sbl.1
|
||||
|
||||
clean: |
||||
rm -f sbl sbl-dbg
|
@ -0,0 +1,361 @@ |
||||
#define _DEFAULT_SOURCE |
||||
#define _POSIX_C_SOURCE 200809L |
||||
#include <sys/types.h> |
||||
#include <sys/stat.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <dirent.h> |
||||
#include <stdarg.h> |
||||
#include <errno.h> |
||||
#include <string.h> |
||||
#include <wordexp.h> |
||||
#include <limits.h> |
||||
#include <getopt.h> |
||||
#include <unistd.h> |
||||
|
||||
#define BACKLIGHT_ROOT_PATH "/sys/class/backlight/" |
||||
#define BL_MIN 5 |
||||
|
||||
#define const_arr_size(val) ((int)(sizeof(val)/sizeof(val[0]))) |
||||
|
||||
const char *savefile_paths[] = { |
||||
NULL, /* reserved for external savefile path */ |
||||
"/etc/sbl/savefile" |
||||
}; |
||||
|
||||
enum action { |
||||
DISPLAY, INCREASE, DECREASE, SET, RESTORE |
||||
}; |
||||
|
||||
static uid_t ruid; |
||||
int device_index = 0; |
||||
|
||||
static void die (const char *, ...); |
||||
static void usage (void); |
||||
static void list_cards (void); |
||||
static void set_brightness (float); |
||||
static void change_permissions (const char *); |
||||
static void restore_permissions (void); |
||||
static int save_value (float); |
||||
static int get_max_brightness (void); |
||||
static float get_saved_value (void); |
||||
static float get_current_brightness (void); |
||||
static const char * backlight_path (int); |
||||
static const char * get_savefile (void); |
||||
|
||||
int main (int argc, char *argv[]) |
||||
{ |
||||
int opc = 0, store = 0; |
||||
enum action act = DISPLAY; |
||||
float value = BL_MIN; |
||||
char *extfile = NULL; |
||||
/* Parse command line arguments */ |
||||
while ((opc = getopt(argc, argv, "c:hI:li:d:s:Sr")) != -1) { |
||||
switch (opc) { |
||||
case 'l': |
||||
list_cards(); |
||||
break; |
||||
case 'h': |
||||
usage(); |
||||
break; |
||||
case 'c': |
||||
extfile = malloc(strlen(optarg) + 1); |
||||
if (!extfile) |
||||
die("malloc in main():"); |
||||
strcpy(extfile, optarg); |
||||
savefile_paths[0] = extfile; |
||||
break; |
||||
case 'I': |
||||
device_index = atoi(optarg); |
||||
break; |
||||
case 'i': |
||||
act = INCREASE; |
||||
value = atof(optarg); |
||||
break; |
||||
case 'd': |
||||
act = DECREASE; |
||||
value = atof(optarg); |
||||
break; |
||||
case 's': |
||||
act = SET; |
||||
value = atof(optarg); |
||||
break; |
||||
case 'r':
|
||||
act = RESTORE; |
||||
break; |
||||
case 'S': |
||||
store = 1; |
||||
break; |
||||
default: |
||||
exit(EXIT_FAILURE); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
ruid = getuid (); |
||||
|
||||
switch (act) { |
||||
case DISPLAY: |
||||
printf("%.2f\n", get_current_brightness()); |
||||
break; |
||||
case SET: |
||||
set_brightness(value); |
||||
break; |
||||
case INCREASE: |
||||
value += get_current_brightness(); |
||||
set_brightness(value); |
||||
break; |
||||
case DECREASE: |
||||
value = get_current_brightness() - value; |
||||
set_brightness(value); |
||||
break; |
||||
case RESTORE: |
||||
set_brightness(get_saved_value()); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
if (store) |
||||
save_value(get_current_brightness()); |
||||
|
||||
if (extfile) |
||||
free(extfile); |
||||
return 0; |
||||
} |
||||
|
||||
int save_value (float value) |
||||
{ |
||||
FILE *fd; |
||||
fd = fopen(get_savefile(), "w"); |
||||
if (!fd) |
||||
die("could not open savefile"); |
||||
fprintf(fd, "%f\n", value); |
||||
fclose(fd); |
||||
return 1; |
||||
} |
||||
|
||||
float get_saved_value (void) |
||||
{ |
||||
FILE *fd; |
||||
float rtf = -1; |
||||
fd = fopen(get_savefile(), "r"); |
||||
if (!fd) |
||||
die("could not open savefile"); |
||||
fscanf(fd, "%f", &rtf); |
||||
fclose(fd); |
||||
return rtf; |
||||
} |
||||
|
||||
float get_current_brightness (void) |
||||
{ |
||||
FILE *fd; |
||||
char buf[PATH_MAX] = {0}; |
||||
int cb = -1; |
||||
const char *path = backlight_path(device_index); |
||||
if (!path) |
||||
die("invalid device index");
|
||||
strcpy(buf, path); |
||||
strcat(buf, "/brightness"); |
||||
fd = fopen(buf, "r"); |
||||
if (!fd) |
||||
die("could not open %s", buf); |
||||
fscanf(fd, "%d", &cb); |
||||
fclose(fd); |
||||
|
||||
return ((float)cb / (float)get_max_brightness()) * 100.0;; |
||||
} |
||||
|
||||
int get_max_brightness (void) |
||||
{ |
||||
FILE *fd; |
||||
char buf[PATH_MAX] = {0}; |
||||
int rti = -1; |
||||
const char *path = backlight_path(device_index); |
||||
if (!path) |
||||
die("invalid device index");
|
||||
strcpy(buf, path); |
||||
strcat(buf, "/max_brightness"); |
||||
fd = fopen(buf, "r"); |
||||
if (!fd) |
||||
die("could not open %s", buf); |
||||
fscanf(fd, "%d", &rti); |
||||
fclose(fd); |
||||
|
||||
return rti; |
||||
} |
||||
|
||||
/* Return the correct savefile path, creating it if it does not exist */ |
||||
const char * get_savefile (void) |
||||
{ |
||||
static char buf[PATH_MAX]; |
||||
wordexp_t result = {0}; |
||||
FILE *fd; |
||||
|
||||
for (int i = 0; i < const_arr_size(savefile_paths); i++) { |
||||
if (!savefile_paths[i]) |
||||
continue; |
||||
switch (wordexp(savefile_paths[i], &result, 0)) { |
||||
case 0: |
||||
break; |
||||
case WRDE_NOSPACE: |
||||
wordfree (&result); |
||||
die("Not enough space"); |
||||
default: |
||||
die("Path not valid"); |
||||
} |
||||
|
||||
strcpy(buf, result.we_wordv[0]); |
||||
if ((fd = fopen(result.we_wordv[0], "r"))) |
||||
break; |
||||
} |
||||
/* Create a savefile */ |
||||
if (!fd) { |
||||
wordfree(&result); |
||||
for (int i = 0; i < const_arr_size(savefile_paths); i++) { |
||||
if (!savefile_paths[i]) |
||||
continue; |
||||
switch (wordexp(savefile_paths[i], &result, 0)) { |
||||
case 0: |
||||
break; |
||||
case WRDE_NOSPACE: |
||||
wordfree (&result); |
||||
die("Not enough space"); |
||||
default: |
||||
die("Path not valid"); |
||||
} |
||||
|
||||
strcpy(buf, result.we_wordv[0]); |
||||
if ((fd = fopen(result.we_wordv[0], "w"))) |
||||
break; |
||||
} |
||||
} |
||||
wordfree(&result); |
||||
if (!fd) |
||||
die("could not open or create a savefile"); |
||||
fclose(fd); |
||||
return buf; |
||||
}
|
||||
|
||||
const char * backlight_path (int index) |
||||
{ |
||||
DIR *dp; |
||||
struct dirent *de; |
||||
static char buf[PATH_MAX]; |
||||
|
||||
memset(buf, 0, PATH_MAX); |
||||
if (index < 0) |
||||
die("%d is not a valid index", index); |
||||
if (!(dp = opendir(BACKLIGHT_ROOT_PATH))) |
||||
die("error opening " BACKLIGHT_ROOT_PATH); |
||||
|
||||
errno = 0; |
||||
while ((de = readdir(dp))) { |
||||
if (!(de->d_type & DT_LNK)) |
||||
continue; |
||||
if (index) { |
||||
index--; |
||||
continue; |
||||
} else { |
||||
strcpy(buf, BACKLIGHT_ROOT_PATH); |
||||
strcat(buf, de->d_name); |
||||
break; |
||||
} |
||||
} |
||||
closedir(dp); |
||||
if (errno) |
||||
die("error reading " BACKLIGHT_ROOT_PATH); |
||||
// FIXME: actually check return value of this
|
||||
if (!buf[0]) |
||||
return NULL; |
||||
return buf; |
||||
|
||||
} |
||||
|
||||
void list_cards (void) |
||||
{ |
||||
int i = 0; |
||||
const char *s; |
||||
for (; (s = backlight_path(i)); i++) |
||||
printf("%d: %s\n", i, s); |
||||
exit(EXIT_SUCCESS); |
||||
} |
||||
|
||||
void set_brightness (float value) |
||||
{ |
||||
int set; |
||||
char buf[PATH_MAX] = {0}; |
||||
const char *path = backlight_path(device_index); |
||||
FILE *fd; |
||||
if (value > 100) |
||||
value = 100; |
||||
if (value < BL_MIN) |
||||
value = BL_MIN; |
||||
set = (value/100.0) * get_max_brightness(); |
||||
if (set < 0) |
||||
return; |
||||
if (!path) |
||||
die("invalid device index");
|
||||
strcpy(buf, path); |
||||
strcat(buf, "/brightness"); |
||||
change_permissions(buf); |
||||
fd = fopen(buf, "w"); |
||||
if (!fd) |
||||
die("could not open %s", buf); |
||||
fprintf(fd, "%d", set); |
||||
fclose(fd); |
||||
restore_permissions(); |
||||
} |
||||
|
||||
/* Change the process permissions matching the ones pointed by path */ |
||||
void change_permissions (const char *path) |
||||
{ |
||||
int status; |
||||
struct stat st; |
||||
|
||||
stat(path, &st); |
||||
status = seteuid(st.st_uid); |
||||
if (status < 0) |
||||
die("could not setuid"); |
||||
} |
||||
|
||||
static void restore_permissions (void) |
||||
{ |
||||
int status; |
||||
status = seteuid(ruid); |
||||
if (status < 0) |
||||
die("could not setuid"); |
||||
} |
||||
|
||||
void die(const char *fmt, ...) |
||||
{ |
||||
va_list ap; |
||||
va_start(ap, fmt); |
||||
|
||||
vfprintf(stderr, fmt, ap); |
||||
|
||||
if (fmt[0] && fmt[strlen(fmt) - 1] == ':') { |
||||
fputc(' ', stderr); |
||||
perror(NULL); |
||||
} else { |
||||
fputc('\n', stderr); |
||||
} |
||||
|
||||
va_end(ap); |
||||
exit(errno ? errno : 1); |
||||
} |
||||
|
||||
static void usage (void) |
||||
{ |
||||
puts("Usage: sbl [-hlrS] [-c savefile] [-I index] [-i/d/s percent]\n" |
||||
"-h print this message\n" |
||||
"-l list devices by index\n" |
||||
"-r restore saved value\n" |
||||
"-S save value\n" |
||||
"-c savefile specify savefile\n" |
||||
"-I index specify device by index\n" |
||||
"-i percent increase backlight by percent\n" |
||||
"-d percent decrease backlight by percent\n" |
||||
"-s percent set backlight to percent\n"); |
||||
exit(EXIT_SUCCESS); |
||||
} |
Loading…
Reference in new issue