diff options
Diffstat (limited to 'src/gpm-backlight-helper.c')
-rw-r--r-- | src/gpm-backlight-helper.c | 280 |
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; +} + |