[gnome-settings-daemon] power: Add a backlight helper, as xbacklight isn't always present



commit 6bf9c04f17ccc1985b8b68efa8d6e69b98e1fc7b
Author: Richard Hughes <richard hughsie com>
Date:   Wed Aug 3 11:55:44 2011 +0100

    power: Add a backlight helper, as xbacklight isn't always present
    
    This helper uses PolicyKit to do a one-time-authentication, which is not
    required by default on an active session. This only works on Linux.
    
    The PolicyKit helper has been moved from the gnome-power-manager project, and
    was security reviewed by Vincent Untz.

 configure.ac                                       |    5 +
 plugins/power/Makefile.am                          |   29 ++-
 plugins/power/gsd-backlight-helper.c               |  271 ++++++++++++++++++++
 ...nome.settings-daemon.plugins.power.policy.in.in |   32 +++
 po/POTFILES.in                                     |    1 +
 po/POTFILES.skip                                   |    1 +
 6 files changed, 335 insertions(+), 4 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 27595f2..9f145bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -77,6 +77,11 @@ PKG_CHECK_MODULES(SETTINGS_PLUGIN,
         gsettings-desktop-schemas
 )
 
+PKG_CHECK_MODULES(BACKLIGHT_HELPER,
+        glib-2.0 >= $GLIB_REQUIRED_VERSION
+        gio-2.0 >= $GIO_REQUIRED_VERSION
+)
+
 GSD_PLUGIN_LDFLAGS="-export_dynamic -module -avoid-version -no-undefined"
 case $host_os in
   darwin*)
diff --git a/plugins/power/Makefile.am b/plugins/power/Makefile.am
index 97968dd..5fee2dd 100644
--- a/plugins/power/Makefile.am
+++ b/plugins/power/Makefile.am
@@ -49,16 +49,37 @@ plugin_in_files = 					\
 
 plugin_DATA = $(plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
 
+org.gnome.settings-daemon.plugins.power.policy.in: org.gnome.settings-daemon.plugins.power.policy.in.in Makefile
+	$(AM_V_GEN) sed -e "s|\ libexecdir\@|$(libexecdir)|" $< > $@
+
+ INTLTOOL_POLICY_RULE@
+polkit_policydir = $(datadir)/polkit-1/actions
+polkit_policy_in_files = org.gnome.settings-daemon.plugins.power.policy.in
+polkit_policy_DATA = $(polkit_policy_in_files:.policy.in=.policy)
+
+libexec_PROGRAMS =					\
+	gsd-backlight-helper
+
+gsd_backlight_helper_SOURCES =				\
+	gsd-backlight-helper.c
+
+gsd_backlight_helper_LDFLAGS =				\
+	$(BACKLIGHT_HELPER_LIBS)				\
+	-lm
+
+gsd_backlight_helper_CFLAGS =				\
+	$(BACKLIGHT_HELPER_CFLAGS)
+
 EXTRA_DIST = 						\
+	org.gnome.settings-daemon.plugins.power.policy.in.in \
 	$(plugin_in_files)
 
 clean-local:
 	rm -f *~
 
 CLEANFILES = 						\
-	$(plugin_DATA)
-
-DISTCLEANFILES =					\
-	$(plugin_DATA)
+	$(plugin_DATA)					\
+	org.gnome.settings-daemon.plugins.power.policy	\
+	org.gnome.settings-daemon.plugins.power.policy.in
 
 @GSD_INTLTOOL_PLUGIN_RULE@
diff --git a/plugins/power/gsd-backlight-helper.c b/plugins/power/gsd-backlight-helper.c
new file mode 100644
index 0000000..5ea7943
--- /dev/null
+++ b/plugins/power/gsd-backlight-helper.c
@@ -0,0 +1,271 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010-2011 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <unistd.h>
+#include <glib-object.h>
+#include <locale.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+
+#define GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS			0
+#define GSD_BACKLIGHT_HELPER_EXIT_CODE_FAILED			1
+#define GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID	3
+#define GSD_BACKLIGHT_HELPER_EXIT_CODE_INVALID_USER		4
+
+#define GSD_BACKLIGHT_HELPER_SYSFS_LOCATION			"/sys/class/backlight"
+
+static gchar *
+gsd_backlight_helper_get_best_backlight ()
+{
+	gchar *filename;
+	guint i;
+	gboolean ret;
+	GDir *dir = NULL;
+	GError *error = NULL;
+	const gchar *first_device;
+
+	/* available kernel interfaces in priority order */
+	static const gchar *backlight_interfaces[] = {
+		"nv_backlight",
+		"asus_laptop",
+		"toshiba",
+		"eeepc",
+		"thinkpad_screen",
+		"acpi_video1",
+		"mbp_backlight",
+		"acpi_video0",
+		"fujitsu-laptop",
+		"sony",
+		"samsung",
+		NULL,
+	};
+
+	/* search each one */
+	for (i=0; backlight_interfaces[i] != NULL; i++) {
+		filename = g_build_filename (GSD_BACKLIGHT_HELPER_SYSFS_LOCATION,
+					     backlight_interfaces[i], NULL);
+		ret = g_file_test (filename, G_FILE_TEST_EXISTS);
+		if (ret)
+			goto out;
+		g_free (filename);
+	}
+
+	/* nothing found in the ordered list */
+	filename = NULL;
+
+	/* find any random ones */
+	dir = g_dir_open (GSD_BACKLIGHT_HELPER_SYSFS_LOCATION, 0, &error);
+	if (dir == NULL) {
+		g_warning ("failed to find any devices: %s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* get first device if any */
+	first_device = g_dir_read_name (dir);
+	if (first_device != NULL) {
+		filename = g_build_filename (GSD_BACKLIGHT_HELPER_SYSFS_LOCATION,
+					     first_device, NULL);
+	}
+out:
+	if (dir != NULL)
+		g_dir_close (dir);
+	return filename;
+}
+
+static gboolean
+gsd_backlight_helper_write (const gchar *filename, gint value, GError **error)
+{
+	gchar *text = NULL;
+	gint retval;
+	gint length;
+	gint fd = -1;
+	gboolean ret = TRUE;
+
+	fd = open (filename, O_WRONLY);
+	if (fd < 0) {
+		ret = FALSE;
+		g_set_error (error, 1, 0, "failed to open filename: %s", filename);
+		goto out;
+	}
+
+	/* convert to text */
+	text = g_strdup_printf ("%i", value);
+	length = strlen (text);
+
+	/* write to device file */
+	retval = write (fd, text, length);
+	if (retval != length) {
+		ret = FALSE;
+		g_set_error (error, 1, 0, "writing '%s' to %s failed", text, filename);
+		goto out;
+	}
+out:
+	if (fd >= 0)
+		close (fd);
+	g_free (text);
+	return ret;
+}
+
+int
+main (int argc, char *argv[])
+{
+	GOptionContext *context;
+	gint uid;
+	gint euid;
+	guint retval = 0;
+	const gchar *pkexec_uid_str;
+	GError *error = NULL;
+	gboolean ret = FALSE;
+	gint set_brightness = -1;
+	gboolean get_brightness = FALSE;
+	gboolean get_max_brightness = FALSE;
+	gchar *filename = NULL;
+	gchar *filename_file = NULL;
+	gchar *contents = NULL;
+
+	const GOptionEntry options[] = {
+		{ "set-brightness", '\0', 0, G_OPTION_ARG_INT, &set_brightness,
+		   /* command line argument */
+		  "Set the current brightness", NULL },
+		{ "get-brightness", '\0', 0, G_OPTION_ARG_NONE, &get_brightness,
+		   /* command line argument */
+		  "Get the current brightness", NULL },
+		{ "get-max-brightness", '\0', 0, G_OPTION_ARG_NONE, &get_max_brightness,
+		   /* command line argument */
+		  "Get the number of brightness levels supported", NULL },
+		{ NULL}
+	};
+
+	/* setup type system */
+	g_type_init ();
+
+	context = g_option_context_new (NULL);
+	g_option_context_set_summary (context, "GNOME Settings Daemon Backlight Helper");
+	g_option_context_add_main_entries (context, options, NULL);
+	g_option_context_parse (context, &argc, &argv, NULL);
+	g_option_context_free (context);
+
+#ifndef __linux__
+	/* the g-s-d plugin should only call this helper on linux */
+	g_critical ("Attempting to call gsb-backlight-helper on non-Linux");
+	g_assert_not_reached ();
+#endif
+
+	/* no input */
+	if (set_brightness == -1 && !get_brightness && !get_max_brightness) {
+		g_print ("%s\n", "No valid option was specified");
+		retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
+		goto out;
+	}
+
+	/* find device */
+	filename = gsd_backlight_helper_get_best_backlight ();
+	if (filename == NULL) {
+		g_print ("%s\n", "No backlights were found on your system");
+		retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_INVALID_USER;
+		goto out;
+	}
+
+	/* GetBrightness */
+	if (get_brightness) {
+		filename_file = g_build_filename (filename, "brightness", NULL);
+		ret = g_file_get_contents (filename_file, &contents, NULL, &error);
+		if (!ret) {
+			g_print ("%s: %s\n",
+				 "Could not get the value of the backlight",
+				 error->message);
+			g_error_free (error);
+			retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
+			goto out;
+		}
+
+		/* just print the contents to stdout */
+		g_print ("%s", contents);
+		retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS;
+		goto out;
+	}
+
+	/* GetSteps */
+	if (get_max_brightness) {
+		filename_file = g_build_filename (filename, "max_brightness", NULL);
+		ret = g_file_get_contents (filename_file, &contents, NULL, &error);
+		if (!ret) {
+			g_print ("%s: %s\n",
+				 "Could not get the maximum value of the backlight",
+				 error->message);
+			g_error_free (error);
+			retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
+			goto out;
+		}
+
+		/* just print the contents to stdout */
+		g_print ("%s", contents);
+		retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS;
+		goto out;
+	}
+
+	/* get calling process */
+	uid = getuid ();
+	euid = geteuid ();
+	if (uid != 0 || euid != 0) {
+		g_print ("%s\n",
+			 "This program can only be used by the root user");
+		retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
+		goto out;
+	}
+
+	/* check we're not being spoofed */
+	pkexec_uid_str = g_getenv ("PKEXEC_UID");
+	if (pkexec_uid_str == NULL) {
+		g_print ("%s\n",
+			 "This program must only be run through pkexec");
+		retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_INVALID_USER;
+		goto out;
+	}
+
+	/* SetBrightness */
+	if (set_brightness != -1) {
+		filename_file = g_build_filename (filename, "brightness", NULL);
+		ret = gsd_backlight_helper_write (filename_file, set_brightness, &error);
+		if (!ret) {
+			g_print ("%s: %s\n",
+				 "Could not set the value of the backlight",
+				 error->message);
+			g_error_free (error);
+			retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
+			goto out;
+		}
+	}
+
+	/* success */
+	retval = GSD_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS;
+out:
+	g_free (filename);
+	g_free (filename_file);
+	g_free (contents);
+	return retval;
+}
+
diff --git a/plugins/power/org.gnome.settings-daemon.plugins.power.policy.in.in b/plugins/power/org.gnome.settings-daemon.plugins.power.policy.in.in
new file mode 100644
index 0000000..5adbc41
--- /dev/null
+++ b/plugins/power/org.gnome.settings-daemon.plugins.power.policy.in.in
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd";>
+<policyconfig>
+
+  <!--
+    Policy definitions for gnome-settings-daemon system-wide actions.
+    Copyright (c) 2010-2011 Richard Hughes <richard hughsie com>
+  -->
+
+  <vendor>GNOME Settings Daemon</vendor>
+  <vendor_url>http://git.gnome.org/browse/gnome-settings-daemon</vendor_url>
+  <icon_name>battery</icon_name>
+
+  <action id="org.gnome.settings-daemon.plugins.power.backlight-helper">
+    <!-- SECURITY:
+          - A normal active user on the local machine does not need permission
+            to change the backlight brightness.
+     -->
+    <_description>Modify the laptop brightness</_description>
+    <_message>Authentication is required to modify the laptop brightness</_message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>yes</allow_active>
+    </defaults>
+    <annotate key="org.freedesktop.policykit.exec.path">@libexecdir@/gsd-backlight-helper</annotate>
+  </action>
+
+</policyconfig>
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f76e230..ef38253 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -31,6 +31,7 @@ plugins/color/gsd-color-manager.c
 [type: gettext/ini]plugins/power/power.gnome-settings-plugin.in
 plugins/power/gpm-common.c
 plugins/power/gsd-power-manager.c
+plugins/power/org.gnome.settings-daemon.plugins.power.policy.in.in
 plugins/housekeeping/gsd-disk-space.c
 plugins/housekeeping/gsd-ldsm-dialog.c
 plugins/keybindings/gsd-keybindings-manager.c
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index dda31a6..a4e8c91 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -22,3 +22,4 @@ data/org.gnome.settings-daemon.plugins.power.gschema.xml.in
 data/org.gnome.settings-daemon.peripherals.wacom.gschema.xml.in
 data/org.gnome.settings-daemon.plugins.color.gschema.xml.in
 plugins/automount/gnome-fallback-mount-helper.desktop.in
+plugins/power/org.gnome.settings-daemon.plugins.power.policy.in



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]