123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- /*
- setbrightness - sets your laptop's screen brightness (backlight) from the
- command-line.
- This program does nothing more than open a file and write some specific
- numerical value to it, obtained from the command-line.
- Only that this file will be the backlight brightness file, thus allowing us
- to set it with sudo, or even without it via setuid ;)
- Copyright 2022 kzimmermann - https://tilde.town/~kzimmermann/
- This program is Free Software licensed under the GNU GPLv3 or later.
- For more information, please see https://www.gnu.org/licenses
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- // Alpine Linux with intel chips sets this file here. Change as needed.
- const char *BRIGHTFILE = "/sys/class/backlight/intel_backlight/brightness";
- // Likewise, this is the location of the file indicating max value for it:
- const char *MAX_BRIGHTFILE = "/sys/class/backlight/intel_backlight/max_brightness";
- void
- helper(char *progname) {
- printf("%s - utility to set the laptop's display brightness (backlight) from the command-line\n", progname);
- printf("Usage: %s BRIGHTNESS [+BRIGHTNESS] [-BRIGHTNESS]\n", progname);
- printf("Where BRIGHTNESS is an absolute value between 1 and 100, or a 'step' value preceeded by a + (increase) or a - (decrease) sign.\n");
- printf("Examples:\n");
- printf("%s 50 # sets the display brightness to 50%%\n", progname);
- printf("%s +10 # sets the brightness 10%% brighter\n", progname);
- printf("%s -15 # sets the brightness 15%% dimmer\n", progname);
- }
- // datatype of a "tuple" containing a leading character and a numerical value:
- struct
- argtuple {
- char sign;
- int value;
- };
- // this function will process a token like "+83239" and identify the parts:
- struct argtuple
- parseArg(char token[])
- {
- struct argtuple t;
- sscanf(token, "%1c%d", &t.sign, &t.value);
- if (!(t.sign == '+' || t.sign == '-')) {
- // parsing error. Let's use the (!,0) tuple as an error code
- t.sign = '!';
- t.value = 0;
- }
- return t;
- }
- int
- main(int argc, char *argv[])
- {
- int status = 0;
- int maxbrightness = 0;
- int brightness = 0;
- int is_absolute = 0;
- int multiplier = 1;
- struct argtuple at;
- FILE *fp;
- // parse -h or --help argument:
- if (argc == 2) {
- if (strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--help", 6) == 0) {
- helper(argv[0]);
- return 0;
- }
- }
- fp = fopen(BRIGHTFILE, "r");
- if (fp == NULL) {
- printf("Error: brightness file does not exist.\n");
- printf("Make sure some sort of brightness file exists under '/sys', edit it in the source and try again.\n");
- return 1;
- }
- else {
- fscanf(fp, "%d", &brightness);
- status = fclose(fp);
- }
-
- // Now that the file indeed exists, get the maximum brightness:
- fp = fopen(MAX_BRIGHTFILE, "r");
- if (fp == NULL) {
- printf("Error: maximum brightness file does not exist.\n");
- printf("Make sure this file exists under '/sys', edit it in the source and try again.\n");
- return 1;
- }
- else {
- // Read the maximum possible value from it:
- fscanf(fp, "%d", &maxbrightness);
- status = fclose(fp);
- }
- // Read command-line arguments:
- if (argc == 1) {
- printf("The current brightness is %d, or %.1f%%\n", brightness, 100.0*brightness / maxbrightness);
- printf("Pass a value from 1 to 100 to set the new brightness.\n");
- return 0;
- }
- // Scan the input, see if the chars '-' or '+' are present. If they are,
- // we will set the brightness relative to the current (respecting limits)
- at = parseArg(argv[1]);
- if (at.sign == '!') {
- printf("[DEBUG] Setting *absolute* brightness\n");
- is_absolute = 1;
- }
- else {
- printf("[DEBUG] Setting *relative* brightness\n");
- is_absolute = 0;
- }
- // Here's now how we actually do the logic of it: the user will pass a
- // number between 1 and 100 as $1 and from this, we will calculate a
- // percentage of the maximum allowed brightness. If the boundaries are
- // respected (and the value passed is actually a digit, not a string),
- // then we overwrite the system's brightness file with that safe value.
- if (is_absolute == 1) {
- multiplier = atoi(argv[1]);
- // integer parsing errors are expressed as a 0, so we can check
- // the bounds:
- if (multiplier > 100 || multiplier < 1) {
- printf("Error: pass a number from 1 to 100 to set new brightness.\n");
- return 1;
- }
- // If everything is within bounds, then:
- brightness = (int)((0.01 * multiplier) * maxbrightness);
- }
- else {
- // relative change. Get the "int" version of percentual brightness:
- multiplier = (int)((100.0 * brightness) / maxbrightness);
- if (at.sign == '-')
- multiplier -= at.value;
- else
- multiplier += at.value;
- if (multiplier <= 0) {
- printf("Cannot set brightness lower than 0. Already at minimum.\n");
- multiplier = 2;
- }
- else if (multiplier >= 100) {
- printf("Cannot set brightness higher than 100. Already at max.\n");
- multiplier = 100;
- }
- }
- // If everything is within bounds, then:
- brightness = (int)((0.01 * multiplier) * maxbrightness);
- fp = fopen(BRIGHTFILE, "w");
- if (fp == NULL) {
- printf("Error: could not open the brightness file for writing.\n");
- printf("Try it as root or with sudo as member of the 'video' group.\n");
- return 1;
- }
- else {
- fprintf(fp, "%d\n", brightness);
- status = fclose(fp);
- printf("The new brightness is %d, or %d%%\n", brightness, multiplier);
- }
- return 0;
- }
|