summaryrefslogtreecommitdiff
path: root/src/gpm-backlight-helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpm-backlight-helper.c')
-rw-r--r--src/gpm-backlight-helper.c280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/gpm-backlight-helper.c b/src/gpm-backlight-helper.c
new file mode 100644
index 0000000..4868446
--- /dev/null
+++ b/src/gpm-backlight-helper.c
@@ -0,0 +1,280 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Richard Hughes <[email protected]>
+ *
+ * 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
+
+#define GCM_BACKLIGHT_HELPER_SYSFS_LOCATION "/sys/class/backlight"
+
+/**
+ * gcm_backlight_helper_get_best_backlight:
+ **/
+static gchar *
+gcm_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 (GCM_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 (GCM_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 (GCM_BACKLIGHT_HELPER_SYSFS_LOCATION,
+ first_device, NULL);
+ }
+out:
+ if (dir != NULL)
+ g_dir_close (dir);
+ return filename;
+}
+
+/**
+ * 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, MATELOCALEDIR);
+ 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, _("MATE 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;
+ }
+
+ /* 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);
+ retval = GCM_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) {
+ /* 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);
+ retval = GCM_BACKLIGHT_HELPER_EXIT_CODE_SUCCESS;
+ 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;
+ }
+
+ /* 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;
+}
+