initiated commitment
This commit is contained in:
commit
3299a68059
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
**/*.o
|
||||||
|
sbl*
|
||||||
|
tests/**
|
||||||
|
!**/*.c
|
||||||
|
!**/*.1
|
||||||
|
|
25
LICENSE
Normal file
25
LICENSE
Normal file
@ -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.
|
27
README.md
Normal file
27
README.md
Normal file
@ -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
|
25
makefile
Normal file
25
makefile
Normal file
@ -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
|
361
sbl.c
Normal file
361
sbl.c
Normal file
@ -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
Block a user