[gnome-power-manager] Provide a pkexec helper for systems that do not have xbacklight capability
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-power-manager] Provide a pkexec helper for systems that do not have xbacklight capability
- Date: Thu, 6 May 2010 19:39:49 +0000 (UTC)
commit d3594664f59ef31278f7d95f9f73e2d52fe3a3f6
Author: Richard Hughes <richard hughsie com>
Date: Thu May 6 20:40:07 2010 +0100
Provide a pkexec helper for systems that do not have xbacklight capability
Makefile.am | 1 +
configure.ac | 1 +
po/POTFILES.in | 2 +
policy/.gitignore | 8 ++
policy/Makefile.am | 14 ++
policy/org.gnome.power.policy.in | 32 +++++
src/.gitignore | 1 +
src/Makefile.am | 19 +++
src/gpm-backlight-helper.c | 247 ++++++++++++++++++++++++++++++++++++++
src/gpm-brightness.c | 128 +++++++++++++++++++-
10 files changed, 446 insertions(+), 7 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 36f06a1..005b8a0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,6 +8,7 @@ SUBDIRS = \
man \
data \
help \
+ policy \
tools
if HAVE_APPLETS
diff --git a/configure.ac b/configure.ac
index 65a1f2d..0a38772 100644
--- a/configure.ac
+++ b/configure.ac
@@ -315,6 +315,7 @@ man/Makefile
help/Makefile
po/Makefile.in
tools/Makefile
+policy/Makefile
data/Makefile
data/gnome-power-manager.desktop.in
data/gnome-power-preferences.desktop.in
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 41e6ee0..dda8e2b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,7 +12,9 @@ data/gnome-power-statistics.desktop.in.in
[type: gettext/glade]data/gpm-feedback-widget.ui
[type: gettext/glade]data/gpm-statistics.ui
[type: gettext/glade]data/gpm-prefs.ui
+policy/org.gnome.power.policy.in
src/gpm-backlight.c
+src/gpm-backlight-helper.c
src/gpm-button.c
src/gpm-control.c
src/gpm-common.c
diff --git a/policy/.gitignore b/policy/.gitignore
new file mode 100644
index 0000000..c04f1d1
--- /dev/null
+++ b/policy/.gitignore
@@ -0,0 +1,8 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.o
+*~
+*.policy
+
diff --git a/policy/Makefile.am b/policy/Makefile.am
new file mode 100644
index 0000000..f7c03d1
--- /dev/null
+++ b/policy/Makefile.am
@@ -0,0 +1,14 @@
+polkit_policydir = $(datadir)/polkit-1/actions
+dist_polkit_policy_DATA = \
+ org.gnome.power.policy
+
+# You will need a recent intltool or the patch from this bug
+# http://bugzilla.gnome.org/show_bug.cgi?id=462312
+ INTLTOOL_POLICY_RULE@
+
+EXTRA_DIST = org.gnome.power.policy.in
+DISTCLEANFILES = org.gnome.power.policy
+
+clean-local :
+ rm -f *~
+
diff --git a/policy/org.gnome.power.policy.in b/policy/org.gnome.power.policy.in
new file mode 100644
index 0000000..2135ba8
--- /dev/null
+++ b/policy/org.gnome.power.policy.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 Power Manager system-wide actions.
+ Copyright (c) 2010 Richard Hughes <richard hughsie com>
+ -->
+
+ <vendor>GNOME Power Manager</vendor>
+ <vendor_url>http://www.gnome.org/projects/gnome-power-manager/</vendor_url>
+ <icon_name>battery</icon_name>
+
+ <action id="org.gnome.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">/usr/sbin/gnome-power-backlight-helper</annotate>
+ </action>
+
+</policyconfig>
+
diff --git a/src/.gitignore b/src/.gitignore
index 1aef318..eff119e 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -5,6 +5,7 @@ gnome-power-manager
gnome-power-preferences
gnome-power-statistics
gnome-power-self-test
+gnome-power-backlight-helper
gpm-marshal.c
gpm-marshal.h
org.gnome.PowerManager.Backlight.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 1e7f1f4..5aea83e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,6 +43,10 @@ bin_PROGRAMS = \
gnome-power-statistics \
$(NULL)
+sbin_PROGRAMS = \
+ gnome-power-backlight-helper \
+ $(NULL)
+
check_PROGRAMS = \
gnome-power-self-test
@@ -66,6 +70,8 @@ libgpmshared_a_SOURCES = \
egg-dbus-monitor.c \
egg-discrete.h \
egg-discrete.c \
+ egg-string.h \
+ egg-string.c \
egg-console-kit.h \
egg-console-kit.c \
gpm-common.h \
@@ -76,6 +82,19 @@ libgpmshared_a_SOURCES = \
gpm-upower.h \
$(NULL)
+gnome_power_backlight_helper_SOURCES = \
+ gpm-backlight-helper.c \
+ $(NULL)
+
+gnome_power_backlight_helper_LDADD = \
+ libgpmshared.a \
+ $(GLIB_LIBS) \
+ -lm
+
+gnome_power_backlight_helper_CFLAGS = \
+ $(WARNINGFLAGS) \
+ $(NULL)
+
gnome_power_statistics_SOURCES = \
gpm-statistics.c \
gpm-point-obj.c \
diff --git a/src/gpm-backlight-helper.c b/src/gpm-backlight-helper.c
new file mode 100644
index 0000000..2b7646c
--- /dev/null
+++ b/src/gpm-backlight-helper.c
@@ -0,0 +1,247 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 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 <glib/gi18n.h>
+#include <locale.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define GCM_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS 0
+#define GCM_BACKLIGHT_HELPER_EXIT_CODE_FAILED 1
+#define GCM_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID 3
+#define GCM_BACKLIGHT_HELPER_EXIT_CODE_INVALID_USER 4
+
+/**
+ * gcm_backlight_helper_get_best_backlight:
+ **/
+static gchar *
+gcm_backlight_helper_get_best_backlight ()
+{
+ gchar *filename = NULL;
+ guint i;
+ gboolean ret;
+
+ /* available kernel interfaces in priority order */
+ static const gchar *backlight_interfaces[] = {
+ "asus-laptop",
+ "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 ("/sys/class/backlight", backlight_interfaces[i], NULL);
+ ret = g_file_test (filename, G_FILE_TEST_EXISTS);
+ if (ret)
+ return filename;
+ g_free (filename);
+ }
+ return NULL;
+}
+
+/**
+ * gcm_backlight_helper_write:
+ **/
+static gboolean
+gcm_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;
+}
+
+/**
+ * main:
+ **/
+gint
+main (gint argc, gchar *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 translations */
+ setlocale (LC_ALL, "");
+ bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+
+ /* setup type system */
+ g_type_init ();
+
+ context = g_option_context_new (NULL);
+ /* TRANSLATORS: tool that is used when copying profiles system-wide */
+ g_option_context_set_summary (context, _("GNOME Power Manager Backlight Helper"));
+ g_option_context_add_main_entries (context, options, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ /* no input */
+ if (set_brightness == -1 && !get_brightness && !get_max_brightness) {
+ /* TRANSLATORS: user did not specify valid options */
+ g_print ("%s\n", _("No valid option was specified"));
+ retval = GCM_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
+ goto out;
+ }
+
+ /* get calling process */
+ uid = getuid ();
+ euid = geteuid ();
+ if (uid != 0 || euid != 0) {
+ /* TRANSLATORS: only able to install profiles as root */
+ g_print ("%s\n", _("This program can only be used by the root user"));
+ retval = GCM_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) {
+ /* TRANSLATORS: the program must never be directly run */
+ g_print ("%s\n", _("This program must only be run through pkexec"));
+ retval = GCM_BACKLIGHT_HELPER_EXIT_CODE_INVALID_USER;
+ goto out;
+ }
+
+ /* find device */
+ filename = gcm_backlight_helper_get_best_backlight ();
+ if (filename == NULL) {
+ /* TRANSLATORS: no backlights found */
+ g_print ("%s\n", _("No backlights were found on your system"));
+ retval = GCM_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) {
+ /* TRANSLATORS: failed to access backlight file */
+ g_print ("%s: %s\n", _("Could not get the value of the backlight"), error->message);
+ g_error_free (error);
+ retval = GCM_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
+ goto out;
+ }
+
+ /* just print the contents to stdout */
+ g_print ("%s", contents);
+ }
+
+ /* 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) {
+ /* TRANSLATORS: failed to access backlight file */
+ g_print ("%s: %s\n", _("Could not get the maximum value of the backlight"), error->message);
+ g_error_free (error);
+ retval = GCM_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
+ goto out;
+ }
+
+ /* just print the contents to stdout */
+ g_print ("%s", contents);
+ }
+
+ /* SetBrightness */
+ if (set_brightness != -1) {
+ filename_file = g_build_filename (filename, "brightness", NULL);
+ ret = gcm_backlight_helper_write (filename_file, set_brightness, &error);
+ if (!ret) {
+ /* TRANSLATORS: failed to access backlight file */
+ g_print ("%s: %s\n", _("Could not set the value of the backlight"), error->message);
+ g_error_free (error);
+ retval = GCM_BACKLIGHT_HELPER_EXIT_CODE_ARGUMENTS_INVALID;
+ goto out;
+ }
+ }
+
+ /* success */
+ retval = GCM_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS;
+out:
+ g_free (filename);
+ g_free (filename_file);
+ g_free (contents);
+ return retval;
+}
+
diff --git a/src/gpm-brightness.c b/src/gpm-brightness.c
index 5396966..c39cad9 100644
--- a/src/gpm-brightness.c
+++ b/src/gpm-brightness.c
@@ -42,6 +42,7 @@
#include "egg-discrete.h"
#include "egg-debug.h"
+#include "egg-string.h"
#include "gpm-brightness.h"
#include "gpm-common.h"
@@ -66,6 +67,8 @@ struct GpmBrightnessPrivate
gboolean hw_changed;
/* A cache of XRRScreenResources is used as XRRGetScreenResources is expensive */
GPtrArray *resources;
+ gint extension_levels;
+ gint extension_current;
};
enum {
@@ -85,6 +88,65 @@ static guint signals [LAST_SIGNAL] = { 0 };
static gpointer gpm_brightness_object = NULL;
/**
+ * gpm_brightness_helper_get_value:
+ **/
+static gint
+gpm_brightness_helper_get_value (const gchar *argument)
+{
+ gboolean ret;
+ GError *error = NULL;
+ gchar *stdout_data = NULL;
+ gint exit_status = 0;
+ gint value = -1;
+ gchar *command = NULL;
+
+ /* get the data */
+ command = g_strdup_printf ("pkexec /usr/sbin/gnome-power-backlight-helper --%s", argument);
+ ret = g_spawn_command_line_sync (command,
+ &stdout_data, NULL, &exit_status, &error);
+ if (!ret) {
+ egg_error ("failed to get value: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ egg_debug ("executing %s retval: %i", command, exit_status);
+
+ /* parse for a number */
+ ret = egg_strtoint (stdout_data, &value);
+ if (!ret)
+ goto out;
+out:
+ g_free (command);
+ g_free (stdout_data);
+ return value;
+}
+
+/**
+ * gpm_brightness_helper_set_value:
+ **/
+static gboolean
+gpm_brightness_helper_set_value (const gchar *argument, gint value)
+{
+ gboolean ret;
+ GError *error = NULL;
+ gint exit_status = 0;
+ gchar *command = NULL;
+
+ /* get the data */
+ command = g_strdup_printf ("pkexec /usr/sbin/gnome-power-backlight-helper --%s %i", argument, value);
+ ret = g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error);
+ if (!ret) {
+ egg_error ("failed to get value: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ egg_debug ("executing %s retval: %i", command, exit_status);
+out:
+ g_free (command);
+ return ret;
+}
+
+/**
* gpm_brightness_get_step:
* @levels: The number of levels supported
* Return value: the amount of hardware steps to do on each increment or decrement
@@ -456,6 +518,8 @@ gpm_brightness_foreach_screen (GpmBrightness *brightness, GpmXRandROp op)
g_return_val_if_fail (GPM_IS_BRIGHTNESS (brightness), FALSE);
+ return FALSE;
+
/* do for each screen */
length = brightness->priv->resources->len;
for (i=0; i<length; i++) {
@@ -523,6 +587,14 @@ gpm_brightness_set (GpmBrightness *brightness, guint percentage, gboolean *hw_ch
brightness->priv->hw_changed = FALSE;
ret = gpm_brightness_foreach_screen (brightness, ACTION_BACKLIGHT_SET);
+ /* legacy fallback */
+ if (!ret) {
+ if (brightness->priv->extension_levels < 0)
+ brightness->priv->extension_levels = gpm_brightness_helper_get_value ("get-max-brightness");
+ brightness->priv->extension_current = egg_discrete_from_percent (percentage, brightness->priv->extension_levels+1);
+ ret = gpm_brightness_helper_set_value ("set-brightness", brightness->priv->extension_current);
+ }
+
/* did the hardware have to be modified? */
if (ret && hw_changed != NULL)
*hw_changed = brightness->priv->hw_changed;
@@ -563,10 +635,19 @@ gpm_brightness_get (GpmBrightness *brightness, guint *percentage)
ret = gpm_brightness_foreach_screen (brightness, ACTION_BACKLIGHT_GET);
percentage_local = brightness->priv->shared_value;
+ /* legacy fallback */
+ if (!ret) {
+ if (brightness->priv->extension_levels < 0)
+ brightness->priv->extension_levels = gpm_brightness_helper_get_value ("get-max-brightness");
+ brightness->priv->extension_current = gpm_brightness_helper_get_value ("get-brightness");
+ percentage_local = egg_discrete_to_percent (brightness->priv->extension_current, brightness->priv->extension_levels+1);
+ ret = TRUE;
+ }
+
/* valid? */
if (percentage_local > 100) {
- egg_warning ("percentage value of %i will be ignored", percentage_local);
- ret = FALSE;
+ egg_warning ("percentage value of %i will be truncated", percentage_local);
+ percentage_local = 100;
}
/* a new value is always trusted if the method and checks succeed */
@@ -607,6 +688,19 @@ gpm_brightness_up (GpmBrightness *brightness, gboolean *hw_changed)
if (ret)
brightness->priv->cache_trusted = FALSE;
+ /* legacy fallback */
+ if (!ret) {
+ if (brightness->priv->extension_levels < 0)
+ brightness->priv->extension_levels = gpm_brightness_helper_get_value ("get-max-brightness");
+ brightness->priv->extension_current = gpm_brightness_helper_get_value ("get-brightness");
+ if (brightness->priv->extension_current < brightness->priv->extension_levels)
+ ret = gpm_brightness_helper_set_value ("set-brightness", ++brightness->priv->extension_current);
+ if (hw_changed != NULL)
+ *hw_changed = ret;
+ brightness->priv->cache_trusted = FALSE;
+ goto out;
+ }
+out:
return ret;
}
@@ -637,6 +731,17 @@ gpm_brightness_down (GpmBrightness *brightness, gboolean *hw_changed)
if (ret)
brightness->priv->cache_trusted = FALSE;
+ /* legacy fallback */
+ if (!ret) {
+ brightness->priv->extension_current = gpm_brightness_helper_get_value ("get-brightness");
+ if (brightness->priv->extension_current > 0)
+ ret = gpm_brightness_helper_set_value ("set-brightness", --brightness->priv->extension_current);
+ if (hw_changed != NULL)
+ *hw_changed = ret;
+ brightness->priv->cache_trusted = FALSE;
+ goto out;
+ }
+out:
return ret;
}
@@ -746,7 +851,17 @@ gboolean
gpm_brightness_has_hw (GpmBrightness *brightness)
{
g_return_val_if_fail (GPM_IS_BRIGHTNESS (brightness), FALSE);
- return brightness->priv->has_extension;
+
+ /* use XRandR first */
+ if (brightness->priv->has_extension)
+ return TRUE;
+
+ /* fallback to legacy access */
+ if (brightness->priv->extension_levels < 0)
+ brightness->priv->extension_levels = gpm_brightness_helper_get_value ("get-max-brightness");
+ if (brightness->priv->extension_levels > 0)
+ return TRUE;
+ return FALSE;
}
/**
@@ -801,6 +916,7 @@ gpm_brightness_init (GpmBrightness *brightness)
brightness->priv->has_changed_events = FALSE;
brightness->priv->cache_percentage = 0;
brightness->priv->hw_changed = FALSE;
+ brightness->priv->extension_levels = -1;
brightness->priv->resources = g_ptr_array_new_with_free_func ((GDestroyNotify) XRRFreeScreenResources);
/* can we do this */
@@ -808,10 +924,8 @@ gpm_brightness_init (GpmBrightness *brightness)
#ifdef HAVE_XRANDR_13
brightness->priv->has_randr13 = gpm_brightness_setup_version (brightness);
#endif
- if (brightness->priv->has_extension == FALSE) {
- egg_debug ("no XRANDR extension, so aborting init");
- return;
- }
+ if (brightness->priv->has_extension == FALSE)
+ egg_debug ("no XRANDR extension");
screen = gdk_screen_get_default ();
window = gdk_screen_get_root_window (screen);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]