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