From 99c21787cbbbde7ca1eb57abc8e7e3b3101eeb6d Mon Sep 17 00:00:00 2001 From: Antoine Damhet Date: Tue, 10 Sep 2019 00:24:05 +0200 Subject: Support the new `SetBrightness` logind API This API from `org.freedesktop.login1.Session` allows an unprivileged user with an active session to change its own backlight. Systemd >= v243 is needed. Signed-off-by: Antoine Damhet --- Makefile | 6 ++++++ README.md | 6 +++++- brightnessctl.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f324efd..22ff475 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,12 @@ INSTALL_UDEV_RULES = 1 INSTALL_UDEV_1 = install_udev_rules UDEVDIR ?= /lib/udev/rules.d +ifdef ENABLE_SYSTEMD + CFLAGS += ${shell pkg-config --cflags libsystemd} + LDLIBS += ${shell pkg-config --libs libsystemd} + CPPFLAGS += -DENABLE_SYSTEMD +endif + MODE_0 = 4711 MODE_1 = 0755 MODE = ${MODE_${INSTALL_UDEV_RULES}} diff --git a/README.md b/README.md index d349a4e..9601c9c 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,18 @@ One can build and install the program using `make install`. Consult the Makefile ## Permissions -Modifying brightness requires write permissions for device files. `brightnessctl` accomplishes this (without using `sudo`/`su`/etc.) by either of the following means: +Modifying brightness requires write permissions for device files or systemd support. `brightnessctl` accomplishes this (without using `sudo`/`su`/etc.) by either of the following means: 1) installing relevant udev rules to add permissions to backlight class devices for users in `video` and leds for users in `input`. (done by default) 2) installing `brightnessctl` as a suid binary. +3) using the `systemd-logind` API. + The behavior is controlled by the `INSTALL_UDEV_RULES` flag (setting it to `1` installs the udev rules, it is the default value). +The systemd support (since v243) is controlled by the `ENABLE_SYSTEMD` flag (in that case it is recommended to set `INSTALL_UDEV_RULES` to 0). + ## Usage ``` Usage: brightnessctl [options] [operation] [value] diff --git a/brightnessctl.c b/brightnessctl.c index f46b2bd..77dca5c 100644 --- a/brightnessctl.c +++ b/brightnessctl.c @@ -14,6 +14,10 @@ #include #include +#ifdef ENABLE_SYSTEMD +# include +#endif + static char *path = "/sys/class"; static char *classes[] = { "backlight", "leds", NULL }; @@ -103,7 +107,12 @@ int main(int argc, char **argv) { struct device *devs[255]; struct device *dev; struct utsname name; - char *dev_name, *file_path, *sys_run_dir; + char *dev_name, *sys_run_dir; + +#ifndef ENABLE_SYSTEMD + char *file_path; +#endif + int n, c, phelp = 0; if (uname(&name)) fail("Unable to determine current OS. Exiting!\n"); @@ -203,6 +212,8 @@ int main(int argc, char **argv) { fail("Invalid value given"); if (!(dev = find_device(devs, dev_name))) fail("Device '%s' not found.\n", dev_name); + +#ifndef ENABLE_SYSTEMD if ((p.operation == SET || p.restore) && !p.pretend && geteuid()) { errno = 0; file_path = cat_with('/', path, dev->class, dev->id, "brightness"); @@ -213,6 +224,8 @@ int main(int argc, char **argv) { } free(file_path); } +#endif + if ((sys_run_dir = getenv("XDG_RUNTIME_DIR"))) run_dir = dir_child(sys_run_dir, "brightnessctl"); if (p.save) @@ -351,6 +364,37 @@ apply: d->curr_brightness = new; } +#ifdef ENABLE_SYSTEMD + +bool write_device(struct device *d) { + sd_bus *bus = NULL; + int r = sd_bus_default_system(&bus); + if (r < 0) { + fprintf(stderr, "Can't connect to system bus: %s\n", strerror(-r)); + return false; + } + + r = sd_bus_call_method(bus, + "org.freedesktop.login1", + "/org/freedesktop/login1/session/auto", + "org.freedesktop.login1.Session", + "SetBrightness", + NULL, + NULL, + "ssu", + d->class, + d->id, + d->curr_brightness); + if (r < 0) + fprintf(stderr, "Failed to set brightness: %s\n", strerror(-r)); + + sd_bus_unref(bus); + + return r >= 0; +} + +#else + bool write_device(struct device *d) { FILE *f; char c[16]; @@ -374,6 +418,8 @@ fail: return !errno; } +#endif + bool read_device(struct device *d, char *class, char *id) { DIR *dirp; FILE *f; -- cgit v1.2.3