Bläddra i källkod

Merge pull request #51 from troglobit/configure-with-udev

Add --with-udev[=PATH] to configure script, for non-SUID root operation
Joachim Nilsson 5 år sedan
förälder
incheckning
a7510d469b
No account linked to committer's email
7 ändrade filer med 89 tillägg och 27 borttagningar
  1. 5
    0
      Makefile.am
  2. 11
    5
      README.md
  3. 21
    0
      configure.ac
  4. 3
    1
      src/Makefile.am
  5. 1
    1
      src/helpers.h
  6. 43
    18
      src/light.c
  7. 5
    2
      src/light.h

+ 5
- 0
Makefile.am Visa fil

@@ -3,6 +3,11 @@ dist_man1_MANS = light.1
3 3
 doc_DATA       = README.md LICENSE CHANGELOG
4 4
 EXTRA_DIST     = README.md LICENSE CHANGELOG
5 5
 
6
+if UDEV
7
+udev_DATA      = 90-backlight.rules
8
+EXTRA_DIST    += $(top_srcdir)/90-backlight.rules
9
+endif
10
+
6 11
 #
7 12
 # Target to run when building a release
8 13
 #

+ 11
- 5
README.md Visa fil

@@ -185,13 +185,19 @@ because they are generated at release time with `make release`.
185 185
 
186 186
 ### Permissions
187 187
 
188
-**Optional:** Instead of SUID root you can set up udev rules to manage
189
-   sysfs permissions, you may skip the `make install` step and instead
190
-   copy the file `90-backlight.rules` to `/etc/udev/rules.d/`:
188
+Optionally, instead of the classic SUID root mode of operation, udev
189
+rules can be set up to manage the kernel sysfs permissions.  Use the
190
+configure script to enable this mode of operation:
191 191
 
192
+    ./configure --with-udev && make
193
+    sudo make install
194
+
195
+This installs the file `90-backlight.rules` into `/lib/udev/rules.d/`.
196
+If your udev rules are located elsewhere, use `--with-udev=PATH`.
192 197
 
193
-    ACTION=="add", SUBSYSTEM=="backlight", RUN+="/bin/chgrp video /sys/class/backlight/%k/brightness"
194
-    ACTION=="add", SUBSYSTEM=="backlight", RUN+="/bin/chmod g+w /sys/class/backlight/%k/brightness"
198
+Note, in this mode `light` runs unpriviliged, so the `/etc/light`
199
+directory (for cached settings) is not used, instead the per-user
200
+specific `~/.cache/light` is used.
195 201
 
196 202
 
197 203
 Origin & References

+ 21
- 0
configure.ac Visa fil

@@ -10,4 +10,25 @@ AC_PROG_CC
10 10
 AC_PROG_INSTALL
11 11
 AC_HEADER_STDC
12 12
 
13
+AC_ARG_WITH([udev],
14
+	AS_HELP_STRING([--with-udev@<:@=PATH@:>@], [use udev instead of SUID root, optional rules.d path]),
15
+	[udev=$withval], [udev=no])
16
+
17
+AC_MSG_CHECKING(for udev rules.d)
18
+AS_IF([test "x$udev" != "xno"], [
19
+	AS_IF([test "x$udev" = "xyes"], [
20
+		udevdir="\${prefix}/lib/udev/rules.d"
21
+	],[
22
+		udevdir="$udev"
23
+	])
24
+	AC_SUBST(udevdir)
25
+	AC_MSG_RESULT([$udevdir])
26
+],[
27
+	AC_MSG_RESULT([disabled, classic SUID root mode])
28
+])
29
+
30
+# Allow classic SUID root behavior if udev rule is not used
31
+AM_CONDITIONAL(UDEV,    [test "x$udev" != "xno"])
32
+AM_CONDITIONAL(CLASSIC, [test "x$udev"  = "xno"])
33
+
13 34
 AC_OUTPUT

+ 3
- 1
src/Makefile.am Visa fil

@@ -1,7 +1,9 @@
1 1
 bin_PROGRAMS   = light
2 2
 light_SOURCES  = main.c light.c light.h helpers.c helpers.h
3
-light_CPPFLAGS = -I../include -D_XOPEN_SOURCE=500
3
+light_CPPFLAGS = -I../include -D_GNU_SOURCE
4 4
 light_CFLAGS   = -W -Wall -Wextra -std=gnu99 -Wno-type-limits
5 5
 
6
+if CLASSIC
6 7
 install-exec-hook:
7 8
 	chmod 4755 $(DESTDIR)$(bindir)/light
9
+endif

+ 1
- 1
src/helpers.h Visa fil

@@ -27,7 +27,7 @@ light_loglevel_t light_loglevel;
27 27
 
28 28
 #define LIGHT_LOG(lvl, fp, fmt, args...)				\
29 29
 	if (light_loglevel >= lvl)					\
30
-		fprintf(fp, "%s:%d:" fmt, __FILE__, __LINE__, ##args)
30
+		fprintf(fp, "%s:%d:" fmt "\n", __FILE__, __LINE__, ##args)
31 31
 
32 32
 #define LIGHT_NOTE(fmt, args...) LIGHT_LOG(LIGHT_NOTE_LEVEL,  stdout, "NOTE:" fmt, ##args)
33 33
 #define LIGHT_WARN(fmt, args...) LIGHT_LOG(LIGHT_WARN_LEVEL,  stderr, "WARN:" fmt, ##args)

+ 43
- 18
src/light.c Visa fil

@@ -1,5 +1,6 @@
1 1
 #include "light.h"
2 2
 
3
+#include <libgen.h>
3 4
 #include <stdlib.h>
4 5
 #include <stdio.h>
5 6
 #include <string.h>
@@ -281,11 +282,34 @@ static bool light_parse_args(int argc, char **argv)
281 282
 	return true;
282 283
 }
283 284
 
285
+static int mkpath(char *dir, mode_t mode)
286
+{
287
+	struct stat sb;
288
+
289
+	if (!dir) {
290
+		errno = EINVAL;
291
+		return -1;
292
+	}
293
+
294
+	if (!stat(dir, &sb))
295
+		return 0;
296
+
297
+	mkpath(dirname(strdupa(dir)), mode);
298
+
299
+	return mkdir(dir, mode);
300
+}
301
+
284 302
 bool light_initialize(int argc, char **argv)
285 303
 {
286 304
 	light_cmd_t mode;
287 305
 	int rc;
288 306
 
307
+	/* Classic SUID root mode or new user based cache files */
308
+	if (geteuid() == 0)
309
+		snprintf(ctx.prefix, sizeof(ctx.prefix), "%s", "/etc/light");
310
+	else
311
+		snprintf(ctx.prefix, sizeof(ctx.prefix), "%s/.cache/light", getenv("HOME"));
312
+
289 313
 	light_defaults();
290 314
 	if (!light_parse_args(argc, argv)) {
291 315
 		LIGHT_ERR("could not parse arguments");
@@ -297,22 +321,23 @@ bool light_initialize(int argc, char **argv)
297 321
 	if (mode == LIGHT_PRINT_HELP || mode == LIGHT_PRINT_VERSION || mode == LIGHT_LIST_CTRL)
298 322
 		return true;
299 323
 
324
+	/* Make sure we have a valid cache directory for all files */
300 325
 	if (mode == LIGHT_SAVE || (mode == LIGHT_SET && ctx.field == LIGHT_MIN_CAP)) {
301
-		/* Make sure we have a valid /etc/light directory, as well as mincap and save */
302
-		char const *const dirs[5] =
303
-		    { "/etc/light", "/etc/light/mincap", "/etc/light/save", "/etc/light/mincap/kbd",
304
-			"/etc/light/save/kbd"
326
+		const char *dirs[5] = {
327
+			"/mincap/kbd", "/save/kbd", NULL
305 328
 		};
306
-		char const *const *dir = dirs;
329
+		char path[strlen(ctx.prefix) + 20];
330
+		int i;
331
+
332
+		for (i = 0; dirs[i]; i++) {
333
+			snprintf(path, sizeof(path), "%s%s", ctx.prefix, dirs[i]);
307 334
 
308
-		while (dir < dirs + 5) {
309
-			rc = mkdir(*dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
335
+			rc = mkpath(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
310 336
 			if (rc && errno != EEXIST) {
311 337
 				LIGHT_ERR("'%s' does not exist and could not be created,"
312
-					  " make sure this application is run as root.", *dir);
338
+					  " make sure this application is run as root.", path);
313 339
 				return false;
314 340
 			}
315
-			++dir;
316 341
 		}
317 342
 	}
318 343
 
@@ -584,11 +609,11 @@ bool light_gen_path(char const *controller, light_target_t target, light_field_t
584 609
 			break;
585 610
 
586 611
 		case LIGHT_MIN_CAP:
587
-			val = snprintf(path, PATH_MAX, "/etc/light/mincap/%s", controller);
612
+			val = snprintf(path, PATH_MAX, "%s/mincap/%s", ctx.prefix, controller);
588 613
 			break;
589 614
 
590 615
 		case LIGHT_SAVERESTORE:
591
-			val = snprintf(path, PATH_MAX, "/etc/light/save/%s", controller);
616
+			val = snprintf(path, PATH_MAX, "%s/save/%s", ctx.prefix, controller);
592 617
 			break;
593 618
 		}
594 619
 	} else {
@@ -602,11 +627,11 @@ bool light_gen_path(char const *controller, light_target_t target, light_field_t
602 627
 			break;
603 628
 
604 629
 		case LIGHT_MIN_CAP:
605
-			val = snprintf(path, PATH_MAX, "/etc/light/mincap/kbd/%s", controller);
630
+			val = snprintf(path, PATH_MAX, "%s/mincap/kbd/%s", ctx.prefix, controller);
606 631
 			break;
607 632
 
608 633
 		case LIGHT_SAVERESTORE:
609
-			val = snprintf(path, PATH_MAX, "/etc/light/save/kbd/%s", controller);
634
+			val = snprintf(path, PATH_MAX, "%s/save/kbd/%s", ctx.prefix, controller);
610 635
 			break;
611 636
 		}
612 637
 	}
@@ -718,8 +743,8 @@ bool light_ctrl_exist(char const *controller)
718 743
 		if (!light_ctrl_get_brightness_maxPath(controller, &path))
719 744
 			return false;
720 745
 		if (!light_file_is_readable(path)) {
721
-			LIGHT_WARN
722
-			    ("could not open controller max brightness file for reading, so controller is not accessible");
746
+			LIGHT_WARN("could not open controller max brightness "
747
+				   "file for reading, so controller is not accessible");
723 748
 			free(path);
724 749
 			return false;
725 750
 		}
@@ -729,7 +754,7 @@ bool light_ctrl_exist(char const *controller)
729 754
 	if (!light_ctrl_get_brightnessPath(controller, &path))
730 755
 		return false;
731 756
 
732
-	if (ctx.cmd != LIGHT_GET &&
757
+	if (ctx.cmd != LIGHT_GET && ctx.cmd != LIGHT_SAVE &&
733 758
 	    ctx.field != LIGHT_MIN_CAP && !light_file_is_writable(path)) {
734 759
 		LIGHT_WARN("could not open controller brightness file for writing, so controller is not accessible");
735 760
 		free(path);
@@ -933,7 +958,7 @@ bool light_ctrl_save_brightness(char const *controller, unsigned long val)
933 958
 		return false;
934 959
 	}
935 960
 
936
-	LIGHT_NOTE("saving brightness %lu (raw) to save file\n", val);
961
+	LIGHT_NOTE("saving brightness %lu (raw) to save file %s\n", val, path);
937 962
 	if (!light_file_write_val(path, val)) {
938 963
 		LIGHT_ERR("could not write to save/restore file");
939 964
 		free(path);
@@ -954,7 +979,7 @@ bool light_ctrl_restore_brightness(char const *controller)
954 979
 		return false;
955 980
 	}
956 981
 
957
-	LIGHT_NOTE("restoring brightness from saved file");
982
+	LIGHT_NOTE("restoring brightness from saved file %s", path);
958 983
 	if (!light_file_read_val(path, &val)) {
959 984
 		LIGHT_ERR("could not read saved value");
960 985
 		free(path);

+ 5
- 2
src/light.h Visa fil

@@ -60,9 +60,12 @@ typedef enum {
60 60
 } light_val_mode_t;
61 61
 
62 62
 typedef struct {
63
+	/* Cache file prefix */
64
+	char               prefix[NAME_MAX + 1];
65
+
63 66
 	/* Which controller to use */
64
-	light_ctrl_mode_t ctrl;
65
-	char              ctrl_name[NAME_MAX + 1];
67
+	light_ctrl_mode_t  ctrl;
68
+	char               ctrl_name[NAME_MAX + 1];
66 69
 
67 70
 	/* What to do with the controller */
68 71
 	light_cmd_t        cmd;