ソースを参照

Use systemd/elogind to set brightness if possible

Since version 243, systemd-logind supports setting the brightness of an
"leds" or "backlight" kernel class device [1]. This method call requires
no privileges to call, but a caller can only change the brightness on
sessions that are currently active, and they must own the session.

Using systemd/elogind for unprivileged brightness changes is a nice
feature to have since it allows to changes brightness without giving
explicit permissions to users via groups or setting SUID bit.

[1] https://github.com/systemd/systemd/commit/2a66c2a1eda48433cb7f4ac6e9b9abcf4bd41bf3
Ihor Kalnytskyi 4 年 前
コミット
bce9c8f175
コミット者のEメールアドレスに関連付けられたアカウントが存在しません
共有4 個のファイルを変更した70 個の追加0 個の削除を含む
  1. 20
    0
      configure.ac
  2. 43
    0
      src/helpers.c
  3. 3
    0
      src/helpers.h
  4. 4
    0
      src/impl/sysfs.c

+ 20
- 0
configure.ac ファイルの表示

@@ -13,6 +13,12 @@ AC_HEADER_STDC
13 13
 AC_ARG_WITH([udev],
14 14
 	AS_HELP_STRING([--with-udev@<:@=PATH@:>@], [use udev instead of SUID root, optional rules.d path]),
15 15
 	[udev=$withval], [udev=no])
16
+AC_ARG_WITH([systemd],
17
+	AS_HELP_STRING([--with-systemd], [use systemd-logind for unprivileged brightness changes]),
18
+	[], [systemd=no])
19
+AC_ARG_WITH([elogind],
20
+	AS_HELP_STRING([--with-elogind], [use elogind for unprivileged brightness changes]),
21
+	[], [elogind=no])
16 22
 
17 23
 AC_MSG_CHECKING(for udev rules.d)
18 24
 AS_IF([test "x$udev" != "xno"], [
@@ -27,6 +33,20 @@ AS_IF([test "x$udev" != "xno"], [
27 33
 	AC_MSG_RESULT([disabled, classic SUID root mode])
28 34
 ])
29 35
 
36
+AC_MSG_CHECKING(for systemd)
37
+AS_IF([test "x$systemd" != "xno"], [
38
+	AC_CHECK_LIB([systemd], [sd_bus_call_method])
39
+],[
40
+	AC_MSG_RESULT([disabled])
41
+])
42
+
43
+AC_MSG_CHECKING(for elogind)
44
+AS_IF([test "x$elogind" != "xno"], [
45
+	AC_CHECK_LIB([elogind], [sd_bus_call_method])
46
+],[
47
+	AC_MSG_RESULT([disabled])
48
+])
49
+
30 50
 # Allow classic SUID root behavior if udev rule is not used
31 51
 AM_CONDITIONAL(UDEV,    [test "x$udev" != "xno"])
32 52
 AM_CONDITIONAL(CLASSIC, [test "x$udev"  = "xno"])

+ 43
- 0
src/helpers.c ファイルの表示

@@ -1,3 +1,4 @@
1
+#include "light.h"
1 2
 #include "helpers.h"
2 3
 
3 4
 #include <stdio.h>
@@ -9,6 +10,11 @@
9 10
 #include <errno.h> // errno
10 11
 #include <libgen.h> // dirname 
11 12
 
13
+#if HAVE_LIBSYSTEMD
14
+#include <systemd/sd-bus.h>
15
+#elif HAVE_LIBELOGIND
16
+#include <elogind/sd-bus.h>
17
+#endif
12 18
 
13 19
 bool light_file_read_uint64(char const *filename, uint64_t *val)
14 20
 {
@@ -146,3 +152,40 @@ int light_mkpath(char *dir, mode_t mode)
146 152
     return mkdir(dir, mode);
147 153
 }
148 154
 
155
+#if HAVE_LIBSYSTEMD || HAVE_LIBELOGIND
156
+bool light_logind_set_brightness(light_device_target_t *target, uint64_t in_value) {
157
+    sd_bus *bus = NULL;
158
+    sd_bus_message *message = NULL;
159
+    sd_bus_error error = SD_BUS_ERROR_NULL;
160
+
161
+    int ret = sd_bus_default_system(&bus);
162
+
163
+    if (ret < 0) {
164
+        LIGHT_ERR("Failed to open D-Bus connection: %s", strerror(-ret));
165
+        return false;
166
+    }
167
+
168
+    ret = sd_bus_call_method(
169
+        bus,
170
+        "org.freedesktop.login1",
171
+        "/org/freedesktop/login1/session/auto",
172
+        "org.freedesktop.login1.Session",
173
+        "SetBrightness",
174
+        &error,
175
+        &message,
176
+        "ssu",
177
+        target->device->name,
178
+        target->name,
179
+        in_value
180
+    );
181
+
182
+    if (ret < 0) {
183
+        LIGHT_ERR("Failed to set brightness: %s", error.message);
184
+    }
185
+
186
+    sd_bus_error_free(&error);
187
+    sd_bus_message_unref(message);
188
+    sd_bus_unref(bus);
189
+    return ret >= 0;
190
+}
191
+#endif  // HAVE_LIBSYSTEMD || HAVE_LIBELOGIND

+ 3
- 0
src/helpers.h ファイルの表示

@@ -54,3 +54,6 @@ double light_percent_clamp(double percent);
54 54
 
55 55
 int light_mkpath(char *dir, mode_t mode);
56 56
 
57
+#if HAVE_LIBSYSTEMD || HAVE_LIBELOGIND
58
+bool light_logind_set_brightness(light_device_target_t *target, uint64_t in_value);
59
+#endif

+ 4
- 0
src/impl/sysfs.c ファイルの表示

@@ -131,6 +131,10 @@ bool impl_sysfs_set(light_device_target_t *target, uint64_t in_value)
131 131
     if(!light_file_write_uint64(data->brightness, in_value))
132 132
     {
133 133
         LIGHT_ERR("failed to write to sysfs device");
134
+
135
+#if HAVE_LIBSYSTEMD || HAVE_LIBELOGIND
136
+        return light_logind_set_brightness(target, in_value);
137
+#endif
134 138
         return false;
135 139
     }
136 140