diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | README | 11 | ||||
-rw-r--r-- | configure.in.in | 56 | ||||
-rw-r--r-- | xfce4-session/Makefile.am | 37 | ||||
-rw-r--r-- | xfce4-session/xfsm-shutdown-helper-hal.c | 124 | ||||
-rw-r--r-- | xfce4-session/xfsm-shutdown-helper-none.c | 71 | ||||
-rw-r--r-- | xfce4-session/xfsm-shutdown-helper-redhat.c | 186 | ||||
-rw-r--r-- | xfce4-session/xfsm-shutdown-helper-sudo.c | 326 | ||||
-rw-r--r-- | xfce4-session/xfsm-shutdown-helper.c | 451 |
9 files changed, 479 insertions, 789 deletions
@@ -1,3 +1,9 @@ +2006-09-09 Benedikt Meurer <benny@xfce.org> + + * README, configure.in.in, xfce4-session/: Merge the sudo and the HAL + shutdown helpers into a single shutdown helper, which tries to use + HAL first, and falls back to sudo. + 2006-09-02 Benedikt Meurer <benny@xfce.org> * configure.in.in: Post-release version bump. @@ -17,12 +17,11 @@ that file): myuser myhost=/usr/local/libexec/xfsm-shutdown-helper -Starting with xfce4-session 4.3.90.3 it is also possible to use HAL to -shutdown/reboot the computer. Therefore pass --with-shutdown-style=hal -to configure/autogen.sh and be sure to have D-BUS 0.34 or above (including -the development files) installed and hald running. You will also need to -allow users to shutdown the computer using HAL (see your system documentation -for details here). +Starting with xfce4-session 4.3.99.2 xfce4-session will first try to use +HAL (if built with D-Bus support) and fallback to the sudo method described +above. So if you have HAL installed on your system, and your account is +allowed to shutdown/reboot the computer using HAL, you don't need to setup +sudo at all. Legacy session management: diff --git a/configure.in.in b/configure.in.in index cc44cfca..af5381b4 100644 --- a/configure.in.in +++ b/configure.in.in @@ -75,6 +75,10 @@ XDT_CHECK_PACKAGE([LIBXFCEGUI4], [libxfcegui4-1.0], [4.3.99.1]) dnl Configure the MCS plugins XDT_XFCE_MCS_PLUGIN([XFCE_MCS_MANAGER], [4.3.99.1]) +dnl Check for D-Bus support (for HAL shutdown support) +XDT_CHECK_OPTIONAL_PACKAGE([DBUS], [dbus-1], [0.34], [dbus], + [Hal shutdown support], [yes]) + dnl Check for gnome support XDT_CHECK_OPTIONAL_PACKAGE([GNOME], [gconf-2.0], [2.4.0], [gnome], [Assistive technologies support], [no]) @@ -121,58 +125,6 @@ else AC_MSG_RESULT([yes]) fi -dnl Check for shutdown method -AC_ARG_WITH([shutdown-style], -AC_HELP_STRING([--with-shutdown-style=auto/none/hal/sudo], [Shutdown style]), - [with_shutdown=$withval], [with_shutdown=auto]) -AC_MSG_CHECKING([what shutdown style should be used]) -if test x"$with_shutdown" != x"sudo" -a x"$with_shutdown" != x"hal" -a x"$with_shutdown" != x"none"; then - with_shutdown="sudo" -fi -AC_DEFINE_UNQUOTED([XFSM_SHUTDOWN_HELPER_IMPL_C], - [<xfce4-session/xfsm-shutdown-helper-$with_shutdown.c>], - [Shutdown helper implementation]) -AC_MSG_RESULT([$with_shutdown]) - -dnl Check for dbus for hal support -if test x"$with_shutdown" = x"hal"; then - XDT_CHECK_PACKAGE([DBUS], [dbus-1], [0.34]) -fi - -dnl -dnl arguments to set shutdown commands -dnl - -dnl AC_MSG_CHECKING([for custom 'poweroff' command]) -dnl AC_ARG_WITH([poweroff], -dnl AC_HELP_STRING([--with-poweroff=cmd], [command used to power down (full path with arguments)]), -dnl [with_poweroff="$withval"], -dnl [with_poweroff="no"]) -dnl if test "x$with_poweroff" != "xno"; then -dnl AC_DEFINE_UNQUOTED(POWEROFF_CMD, "$with_poweroff", [poweroff command]) -dnl fi -dnl AC_MSG_RESULT([$with_poweroff]) -dnl -dnl AC_MSG_CHECKING([for custom 'halt' command]) -dnl AC_ARG_WITH([halt], -dnl AC_HELP_STRING([--with-halt=cmd], [command used to halt (full path with arguments)]), -dnl [with_halt="$withval"], -dnl [with_halt="no"]) -dnl if test "x$with_halt" != "xno"; then -dnl AC_DEFINE_UNQUOTED(HALT_CMD, "$with_halt", [halt command]) -dnl fi -dnl AC_MSG_RESULT([$with_halt]) -dnl -dnl AC_MSG_CHECKING([for custom 'reboot' command]) -dnl AC_ARG_WITH([reboot], -dnl AC_HELP_STRING([--with-reboot=cmd], [command used to reboot (full path with arguments)]), -dnl [with_reboot="$withval"], -dnl [with_reboot="no"]) -dnl if test "x$with_reboot" != "xno"; then -dnl AC_DEFINE_UNQUOTED(REBOOT_CMD, "$with_reboot", [reboot command]) -dnl fi -dnl AC_MSG_RESULT([$with_reboot]) - AC_OUTPUT([ Makefile xfce4-session.spec diff --git a/xfce4-session/Makefile.am b/xfce4-session/Makefile.am index 2cfe604f..bb4cee8e 100644 --- a/xfce4-session/Makefile.am +++ b/xfce4-session/Makefile.am @@ -1,4 +1,7 @@ +# $Id$ + INCLUDES = \ + -I$(top_builddir) \ -I$(top_srcdir) man_MANS = xfce4-session.1 @@ -42,12 +45,12 @@ xfce4_session_SOURCES = \ xfsm-startup.h xfce4_session_CFLAGS = \ - @GNOME_CFLAGS@ \ - @LIBSM_CFLAGS@ \ - @LIBX11_CFLAGS@ \ - @LIBXFCE4MCS_CLIENT_CFLAGS@ \ - @LIBXFCEGUI4_CFLAGS@ \ - @DBUS_CFLAGS@ \ + $(GNOME_CFLAGS) \ + $(LIBSM_CFLAGS) \ + $(LIBX11_CFLAGS) \ + $(LIBXFCE4MCS_CLIENT_CFLAGS) \ + $(LIBXFCEGUI4_CFLAGS) \ + $(DBUS_CFLAGS) \ -DDBUS_API_SUBJECT_TO_CHANGE \ -DLIBDIR=\"$(libdir)\" \ -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \ @@ -56,14 +59,14 @@ xfce4_session_CFLAGS = \ xfce4_session_LDADD = \ $(top_builddir)/libxfsm/libxfsm-4.2.la \ - @LIBSM_LDFLAGS@ \ - @LIBSM_LIBS@ \ - @LIBX11_LDFLAGS@ \ - @LIBX11_LIBS@ \ - @LIBXFCE4MCS_CLIENT_LIBS@ \ - @LIBXFCEGUI4_LIBS@ \ - @DBUS_LIBS@ \ - @GNOME_LIBS@ + $(LIBSM_LDFLAGS) \ + $(LIBSM_LIBS) \ + $(LIBX11_LDFLAGS) \ + $(LIBX11_LIBS) \ + $(LIBXFCE4MCS_CLIENT_LIBS) \ + $(LIBXFCEGUI4_LIBS) \ + $(DBUS_LIBS) \ + $(GNOME_LIBS) xfce4_session_DEPENDENCIES = \ $(top_builddir)/libxfsm/libxfsm-4.2.la @@ -75,9 +78,5 @@ chooser-icon.h: $(srcdir)/chooser-icon.png EXTRA_DIST = \ $(man_MANS) \ - chooser-icon.png \ - xfsm-shutdown-helper-none.c \ - xfsm-shutdown-helper-redhat.c \ - xfsm-shutdown-helper-hal.c \ - xfsm-shutdown-helper-sudo.c + chooser-icon.png diff --git a/xfce4-session/xfsm-shutdown-helper-hal.c b/xfce4-session/xfsm-shutdown-helper-hal.c deleted file mode 100644 index e885a843..00000000 --- a/xfce4-session/xfsm-shutdown-helper-hal.c +++ /dev/null @@ -1,124 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2006 Jani Monoses <jani@ubuntu.com> - * All rights reserved. - * - * 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, 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., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#include <dbus/dbus.h> - -#include <xfce4-session/xfsm-shutdown-helper.h> - - - -#define HAL_DBUS_SERVICE "org.freedesktop.Hal" -#define HAL_ROOT_COMPUTER "/org/freedesktop/Hal/devices/computer" -#define HAL_DBUS_INTERFACE_POWER "org.freedesktop.Hal.Device.SystemPowerManagement" - - - -struct _XfsmShutdownHelper -{ - gint dummy; -}; - - -XfsmShutdownHelper* -xfsm_shutdown_helper_spawn (void) -{ - return g_new0 (XfsmShutdownHelper, 1); -} - - -gboolean -xfsm_shutdown_helper_need_password (const XfsmShutdownHelper *helper) -{ - return FALSE; -} - - -gboolean -xfsm_shutdown_helper_send_password (XfsmShutdownHelper *helper, - const gchar *password) -{ - return TRUE; -} - - -static gboolean -hal_dbus_power_command(XfsmShutdownCommand command) -{ - DBusConnection *connection; - DBusMessage *method; - DBusMessage *result; - const gchar *methodname; - DBusError derror; - - if (command == XFSM_SHUTDOWN_REBOOT) - methodname = "Reboot"; - else - methodname = "Shutdown"; - - dbus_error_init (&derror); - connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror); - if (connection == NULL) - { - dbus_error_free (&derror); - return FALSE; - } - - method = dbus_message_new_method_call (HAL_DBUS_SERVICE, - HAL_ROOT_COMPUTER, - HAL_DBUS_INTERFACE_POWER, - methodname); - result = dbus_connection_send_with_reply_and_block (connection, method, 2000, &derror); - dbus_message_unref (method); - - if (result == NULL) - { - dbus_error_free (&derror); - return FALSE; - } - - dbus_message_unref (result); - return TRUE; -} - - -gboolean -xfsm_shutdown_helper_send_command (XfsmShutdownHelper *helper, - XfsmShutdownCommand command) -{ - return hal_dbus_power_command (command); -} - - -void -xfsm_shutdown_helper_destroy (XfsmShutdownHelper *helper) -{ - g_free (helper); -} - - diff --git a/xfce4-session/xfsm-shutdown-helper-none.c b/xfce4-session/xfsm-shutdown-helper-none.c deleted file mode 100644 index 1abbade2..00000000 --- a/xfce4-session/xfsm-shutdown-helper-none.c +++ /dev/null @@ -1,71 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2003-2004 Benedikt Meurer <benny@xfce.org> - * All rights reserved. - * - * 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, 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., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - - -#include <xfce4-session/xfsm-shutdown-helper.h> - - -struct _XfmShutdownHelper -{ - gint dummy; -}; - - -XfsmShutdownHelper* -xfsm_shutdown_helper_spawn (void) -{ - return NULL; -} - - -gboolean -xfsm_shutdown_helper_need_password (const XfsmShutdownHelper *helper) -{ - return FALSE; -} - - -gboolean -xfsm_shutdown_helper_send_password (XfsmShutdownHelper *helper, - const gchar *password) -{ - return TRUE; -} - - -gboolean -xfsm_shutdown_helper_send_command (XfsmShutdownHelper *helper, - XfsmShutdownCommand command) -{ - return FALSE; -} - - -void -xfsm_shutdown_helper_destroy (XfsmShutdownHelper *helper) -{ -} - - diff --git a/xfce4-session/xfsm-shutdown-helper-redhat.c b/xfce4-session/xfsm-shutdown-helper-redhat.c deleted file mode 100644 index 212e55a8..00000000 --- a/xfce4-session/xfsm-shutdown-helper-redhat.c +++ /dev/null @@ -1,186 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2003-2004 Benedikt Meurer <benny@xfce.org> - * All rights reserved. - * - * 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, 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., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * The permission check was taken from gnome-session/logout.c, originally - * written by Owen Taylor <otaylor@redhat.com>. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef HAVE_SYS_RESOURCE_H -#include <sys/resource.h> -#endif - -#ifdef HAVE_ERRNO_H -#include <errno.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#ifdef HAVE_SIGNAL_H -#include <signal.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <xfce4-session/xfsm-shutdown-helper.h> - - -struct _XfsmShutdownHelper -{ - gint dummy; -}; - - -static char *halt_command[] = { "/usr/bin/halt", "halt", NULL }; -static char *reboot_command[] = { "/usr/bin/reboot", "reboot", NULL }; - - -XfsmShutdownHelper* -xfsm_shutdown_helper_spawn (void) -{ - XfsmShutdownHelper *helper = NULL; - gchar *s; - gchar *t; - - s = g_build_filename ("/var/lock/console", g_get_user_name (), NULL); - t = g_build_filename ("/var/run/console", g_get_user_name (), NULL); - - if (((geteuid () == 0) - || g_file_test (s, G_FILE_TEST_EXISTS) - || g_file_test (t, G_FILE_TEST_EXISTS)) - && access (halt_command[0], X_OK) == 0) - { - helper = g_new0 (XfsmShutdownHelper, 1); - } - - g_free (s); - g_free (t); - - return helper; -} - - -gboolean -xfsm_shutdown_helper_need_password (const XfsmShutdownHelper *helper) -{ - return FALSE; -} - - -gboolean -xfsm_shutdown_helper_send_password (XfsmShutdownHelper *helper, - const gchar *password) -{ - return TRUE; -} - - -gboolean -xfsm_shutdown_helper_send_command (XfsmShutdownHelper *helper, - XfsmShutdownCommand command) -{ -#ifdef HAVE_SIGPROCMASK - sigset_t sigset; -#endif - struct rlimit rlp; - int result; - int status; - int fd; - char **argv; - pid_t pid; - - if (command == XFSM_SHUTDOWN_POWEROFF) - argv = halt_command; - else - argv = reboot_command; - - pid = fork (); - if (pid < 0) - { - return FALSE; - } - else if (pid == 0) - { -#ifdef HAVE_SETSID - setsid (); -#endif - -#ifdef HAVE_SIGPROCMASK - sigemptyset (&sigset); - sigaddset (&sigset, SIGHUP); - sigaddset (&sigset, SIGINT); - sigaddset (&sigset, SIGPIPE); - sigprocmask (SIG_BLOCK, &sigset, NULL); -#endif - - /* setup the 3 standard file handles */ - fd = open ("/dev/null", O_RDWR, 0); - if (fd >= 0) - { - dup2 (fd, STDIN_FILENO); - dup2 (fd, STDOUT_FILENO); - dup2 (fd, STDERR_FILENO); - close (fd); - } - - /* Close all other file handles */ - getrlimit (RLIMIT_NOFILE, &rlp); - for (fd = 0; fd < (int) rlp.rlim_cur; ++fd) - { - if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO) - close (fd); - } - - execv (argv[0], argv + 1); - _exit (127); - } - - /* check if the shutdown command failed */ - result = waitpid (pid, &status, 0); - if ((result == pid && status != 0) || (result < 0 && errno == ECHILD)) - return FALSE; - - return TRUE; -} - - -void -xfsm_shutdown_helper_destroy (XfsmShutdownHelper *helper) -{ - g_free (helper); -} - - diff --git a/xfce4-session/xfsm-shutdown-helper-sudo.c b/xfce4-session/xfsm-shutdown-helper-sudo.c deleted file mode 100644 index 60a0f01c..00000000 --- a/xfce4-session/xfsm-shutdown-helper-sudo.c +++ /dev/null @@ -1,326 +0,0 @@ -/* $Id$ */ -/*- - * Copyright (c) 2003-2004 Benedikt Meurer <benny@xfce.org> - * All rights reserved. - * - * 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, 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., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef HAVE_SYS_RESOURCE_H -#include <sys/resource.h> -#endif -#ifdef HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif - -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif -#include <stdio.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_SIGNAL_H -#include <signal.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <libxfce4util/libxfce4util.h> - -#include <xfce4-session/xfsm-shutdown-helper.h> - - -struct _XfsmShutdownHelper -{ - gchar *sudo; - pid_t pid; - FILE *infile; - FILE *outfile; - gboolean need_password; -}; - - -XfsmShutdownHelper* -xfsm_shutdown_helper_spawn (void) -{ - XfsmShutdownHelper *helper; - struct rlimit rlp; - char *sudo; - char buf[15]; - int parent_pipe[2]; - int child_pipe[2]; - int result; - int n; - - sudo = g_find_program_in_path ("sudo"); - if (G_UNLIKELY (sudo == NULL)) - { - g_warning ("sudo was not found. You will not be able to shutdown your " - "system from within Xfce."); - return NULL; - } - - helper = g_new0 (XfsmShutdownHelper, 1); - helper->sudo = sudo; - - result = pipe (parent_pipe); - if (result < 0) - goto error0; - - result = pipe (child_pipe); - if (result < 0) - goto error1; - - helper->pid = fork (); - if (helper->pid < 0) - { - goto error2; - } - else if (helper->pid == 0) - { - /* setup signals */ - signal (SIGPIPE, SIG_IGN); - - /* setup environment */ - xfce_setenv ("LC_ALL", "C", TRUE); - xfce_setenv ("LANG", "C", TRUE); - xfce_setenv ("LANGUAGE", "C", TRUE); - - /* setup the 3 standard file handles */ - dup2 (child_pipe[0], STDIN_FILENO); - dup2 (parent_pipe[1], STDOUT_FILENO); - dup2 (parent_pipe[1], STDERR_FILENO); - - /* Close all other file handles */ - getrlimit (RLIMIT_NOFILE, &rlp); - for (n = 0; n < (int) rlp.rlim_cur; ++n) - { - if (n != STDIN_FILENO && n != STDOUT_FILENO && n != STDERR_FILENO) - close (n); - } - - /* execute sudo with the helper */ - execl (helper->sudo, "sudo", "-H", "-S", "-p", - "XFSM_SUDO_PASS ", "--", XFSM_SHUTDOWN_HELPER, NULL); - _exit (127); - } - - close (parent_pipe[1]); - - /* read sudo/helper answer */ - n = read (parent_pipe[0], buf, 15); - if (n < 15) - goto error2; - - helper->infile = fdopen (parent_pipe[0], "r"); - if (helper->infile == NULL) - goto error2; - - helper->outfile = fdopen (child_pipe[1], "w"); - if (helper->outfile == NULL) - goto error3; - - if (memcmp (buf, "XFSM_SUDO_PASS ", 15) == 0) - { - helper->need_password = TRUE; - } - else if (memcmp (buf, "XFSM_SUDO_DONE ", 15) == 0) - { - helper->need_password = FALSE; - } - else - goto error3; - - close (parent_pipe[1]); - close (child_pipe[0]); - - return helper; - -error3: - if (helper->infile != NULL) - fclose (helper->infile); - if (helper->outfile != NULL) - fclose (helper->outfile); - -error2: - close (child_pipe[0]); - close (child_pipe[1]); - -error1: - close (parent_pipe[0]); - close (parent_pipe[1]); - -error0: - g_free (helper); - return NULL; -} - - -gboolean -xfsm_shutdown_helper_need_password (const XfsmShutdownHelper *helper) -{ - return helper->need_password; -} - - -gboolean -xfsm_shutdown_helper_send_password (XfsmShutdownHelper *helper, - const gchar *password) -{ - char buffer[1024]; - ssize_t result; - size_t failed; - size_t length; - size_t bytes; - int fd; - - g_return_val_if_fail (helper != NULL, FALSE); - g_return_val_if_fail (password != NULL, FALSE); - g_return_val_if_fail (helper->need_password, FALSE); - - g_snprintf (buffer, 1024, "%s\n", password); - length = strlen (buffer); - bytes = fwrite (buffer, 1, length, helper->outfile); - fflush (helper->outfile); - bzero (buffer, length); - - if (bytes != length) - { - fprintf (stderr, "Failed to write password (bytes=%u, length=%u)\n", - bytes, length); - return FALSE; - } - - if (ferror (helper->outfile)) - { - fprintf (stderr, "Pipe error\n"); - return FALSE; - } - - fd = fileno (helper->infile); - - for (failed = length = 0;;) - { - result = read (fd, buffer + length, 256 - length); - - if (result < 0) - { - perror ("read"); - return FALSE; - } - else if (result == 0) - { - if (++failed > 20) - return FALSE; - continue; - } - else if (result + length >= 1024) - { - fprintf (stderr, "Too much output from sudo!\n"); - return FALSE; - } - - length += result; - buffer[length] = 0; - - if (length >= 15) - { - if (strncmp (buffer + (length - 15), "XFSM_SUDO_PASS ", 15) == 0) - { - return FALSE; - } - else if (strncmp (buffer + (length - 15), "XFSM_SUDO_DONE ", 15) == 0) - { - helper->need_password = FALSE; - break; - } - } - } - - return TRUE; -} - - -gboolean -xfsm_shutdown_helper_send_command (XfsmShutdownHelper *helper, - XfsmShutdownCommand command) -{ - static char *command_table[] = { "POWEROFF", "REBOOT" }; - char response[256]; - - g_return_val_if_fail (helper != NULL, FALSE); - g_return_val_if_fail (!helper->need_password, FALSE); - - fprintf (helper->outfile, "%s\n", command_table[command]); - fflush (helper->outfile); - - if (ferror (helper->outfile)) - { - fprintf (stderr, "Error sending command to helper\n"); - return FALSE; - } - - if (fgets (response, 256, helper->infile) == NULL) - { - fprintf (stderr, "No response from helper\n"); - return FALSE; - } - - if (strncmp (response, "SUCCEED", 7) != 0) - { - fprintf (stderr, "Command failed\n"); - return FALSE; - } - - return TRUE; -} - - -void -xfsm_shutdown_helper_destroy (XfsmShutdownHelper *helper) -{ - int status; - - g_return_if_fail (helper != NULL); - - if (helper->infile != NULL) - fclose (helper->infile); - if (helper->outfile != NULL) - fclose (helper->outfile); - - if (helper->pid > 0) - waitpid (helper->pid, &status, 0); - - g_free (helper->sudo); - g_free (helper); -} - - diff --git a/xfce4-session/xfsm-shutdown-helper.c b/xfce4-session/xfsm-shutdown-helper.c index 1af9124f..b998ee24 100644 --- a/xfce4-session/xfsm-shutdown-helper.c +++ b/xfce4-session/xfsm-shutdown-helper.c @@ -1,6 +1,6 @@ /* $Id$ */ /*- - * Copyright (c) 2003-2004 Benedikt Meurer <benny@xfce.org> + * Copyright (c) 2003-2006 Benedikt Meurer <benny@xfce.org> * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -17,15 +17,456 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. - * - * The permission check was taken from gnome-session/logout.c, originally - * written by Owen Taylor <otaylor@redhat.com>. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#ifdef HAVE_MEMORY_H +#include <memory.h> +#endif +#include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_DBUS +#include <dbus/dbus.h> +#endif + +#include <libxfce4util/libxfce4util.h> + +#include <xfce4-session/xfsm-shutdown-helper.h> + + + +struct _XfsmShutdownHelper +{ + gchar *sudo; + pid_t pid; + FILE *infile; + FILE *outfile; + gboolean use_hal; + gboolean need_password; +}; + + + +static gboolean +xfsm_shutdown_helper_hal_check (XfsmShutdownHelper *helper) +{ +#ifdef HAVE_DBUS + DBusConnection *connection; + DBusMessage *message; + DBusMessage *result; + DBusError error; + + /* initialize the error */ + dbus_error_init (&error); + + /* connect to the system message bus */ + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (G_UNLIKELY (connection == NULL)) + { + g_warning (G_STRLOC ": Failed to connect to the system message bus: %s", error.message); + dbus_error_free (&error); + return FALSE; + } + + /* this is a simple trick to check whether we are allowed to + * use the org.freedesktop.Hal.Device.SystemPowerManagement + * interface without shutting down/rebooting now. + */ + message = dbus_message_new_method_call ("org.freedesktop.Hal", + "/org/freedesktop/Hal/devices/computer", + "org.freedesktop.Hal.Device.SystemPowerManagement", + "ThisMethodMustNotExistInHal"); + result = dbus_connection_send_with_reply_and_block (connection, message, 2000, &error); + dbus_message_unref (message); + + /* translate error results appropriately */ + if (result != NULL && dbus_set_error_from_message (&error, result)) + { + /* release and reset the result */ + dbus_message_unref (result); + result = NULL; + } + else if (G_UNLIKELY (result != NULL)) + { + /* we received a valid message return?! HAL must be on crack! */ + dbus_message_unref (result); + return FALSE; + } + + /* if we receive org.freedesktop.DBus.Error.UnknownMethod, then + * we are allowed to shutdown/reboot the computer via HAL. + */ + if (strcmp (error.name, "org.freedesktop.DBus.Error.UnknownMethod") == 0) + { + dbus_error_free (&error); + return TRUE; + } + + /* otherwise, we failed for some reason */ + g_warning (G_STRLOC ": Failed to contact HAL: %s", error.message); + dbus_error_free (&error); +#endif + + return FALSE; +} + + + +static gboolean +xfsm_shutdown_helper_hal_send (XfsmShutdownHelper *helper, + XfsmShutdownCommand command) +{ +#ifdef HAVE_DBUS + DBusConnection *connection; + DBusMessage *message; + DBusMessage *result; + DBusError error; + + /* initialize the error */ + dbus_error_init (&error); + + /* connect to the system message bus */ + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (G_UNLIKELY (connection == NULL)) + { + g_warning (G_STRLOC ": Failed to connect to the system message bus: %s", error.message); + dbus_error_free (&error); + return FALSE; + } + + /* send the appropriate message to HAL, telling it to shutdown or reboot the system */ + message = dbus_message_new_method_call ("org.freedesktop.Hal", + "/org/freedesktop/Hal/devices/computer", + "org.freedesktop.Hal.Device.SystemPowerManagement", + (command == XFSM_SHUTDOWN_REBOOT) ? "Reboot" : "Shutdown"); + result = dbus_connection_send_with_reply_and_block (connection, message, 2000, &error); + dbus_message_unref (message); + + /* check if we received a result */ + if (G_UNLIKELY (result == NULL)) + { + g_warning (G_STRLOC ": Failed to contact HAL: %s", error.message); + dbus_error_free (&error); + return FALSE; + } + + /* pretend that we succeed */ + dbus_message_unref (result); + return TRUE; +#else + return FALSE; +#endif +} + + + +XfsmShutdownHelper* +xfsm_shutdown_helper_spawn (void) +{ + XfsmShutdownHelper *helper; + struct rlimit rlp; + gchar buf[15]; + gint parent_pipe[2]; + gint child_pipe[2]; + gint result; + gint n; + + /* allocate a new helper */ + helper = g_new0 (XfsmShutdownHelper, 1); + + /* check if we can use HAL to shutdown the computer */ + if (xfsm_shutdown_helper_hal_check (helper)) + { + /* well that's it then */ + g_message (G_STRLOC ": Using HAL to shutdown/reboot the computer."); + helper->use_hal = TRUE; + return helper; + } + + /* no HAL, but maybe sudo will do */ + g_message (G_STRLOC ": HAL not available or does not permit to shutdown/reboot the computer, trying sudo fallback instead."); + + /* make sure sudo is installed, and in $PATH */ + helper->sudo = g_find_program_in_path ("sudo"); + if (G_UNLIKELY (helper->sudo == NULL)) + { + g_warning ("sudo was not found. You will not be able to shutdown your system from within Xfce."); + g_free (helper); + return NULL; + } + + result = pipe (parent_pipe); + if (result < 0) + goto error0; + + result = pipe (child_pipe); + if (result < 0) + goto error1; + + helper->pid = fork (); + if (helper->pid < 0) + { + goto error2; + } + else if (helper->pid == 0) + { + /* setup signals */ + signal (SIGPIPE, SIG_IGN); + + /* setup environment */ + xfce_setenv ("LC_ALL", "C", TRUE); + xfce_setenv ("LANG", "C", TRUE); + xfce_setenv ("LANGUAGE", "C", TRUE); + + /* setup the 3 standard file handles */ + dup2 (child_pipe[0], STDIN_FILENO); + dup2 (parent_pipe[1], STDOUT_FILENO); + dup2 (parent_pipe[1], STDERR_FILENO); + + /* Close all other file handles */ + getrlimit (RLIMIT_NOFILE, &rlp); + for (n = 0; n < (gint) rlp.rlim_cur; ++n) + { + if (n != STDIN_FILENO && n != STDOUT_FILENO && n != STDERR_FILENO) + close (n); + } + + /* execute sudo with the helper */ + execl (helper->sudo, "sudo", "-H", "-S", "-p", + "XFSM_SUDO_PASS ", "--", XFSM_SHUTDOWN_HELPER, NULL); + _exit (127); + } + + close (parent_pipe[1]); + + /* read sudo/helper answer */ + n = read (parent_pipe[0], buf, 15); + if (n < 15) + goto error2; + + helper->infile = fdopen (parent_pipe[0], "r"); + if (helper->infile == NULL) + goto error2; + + helper->outfile = fdopen (child_pipe[1], "w"); + if (helper->outfile == NULL) + goto error3; + + if (memcmp (buf, "XFSM_SUDO_PASS ", 15) == 0) + { + helper->need_password = TRUE; + } + else if (memcmp (buf, "XFSM_SUDO_DONE ", 15) == 0) + { + helper->need_password = FALSE; + } + else + goto error3; + + close (parent_pipe[1]); + close (child_pipe[0]); + + return helper; + +error3: + if (helper->infile != NULL) + fclose (helper->infile); + if (helper->outfile != NULL) + fclose (helper->outfile); + +error2: + close (child_pipe[0]); + close (child_pipe[1]); + +error1: + close (parent_pipe[0]); + close (parent_pipe[1]); + +error0: + g_free (helper); + return NULL; +} + + + +gboolean +xfsm_shutdown_helper_need_password (const XfsmShutdownHelper *helper) +{ + return helper->need_password; +} + + + +gboolean +xfsm_shutdown_helper_send_password (XfsmShutdownHelper *helper, + const gchar *password) +{ + gssize result; + gchar buffer[1024]; + gsize failed; + gsize length; + gsize bytes; + gint fd; + + g_return_val_if_fail (helper != NULL, FALSE); + g_return_val_if_fail (password != NULL, FALSE); + g_return_val_if_fail (!helper->use_hal, FALSE); + g_return_val_if_fail (helper->need_password, FALSE); + + g_snprintf (buffer, 1024, "%s\n", password); + length = strlen (buffer); + bytes = fwrite (buffer, 1, length, helper->outfile); + fflush (helper->outfile); + bzero (buffer, length); + + if (bytes != length) + { + fprintf (stderr, "Failed to write password (bytes=%u, length=%u)\n", bytes, length); + return FALSE; + } + + if (ferror (helper->outfile)) + { + fprintf (stderr, "Pipe error\n"); + return FALSE; + } + + fd = fileno (helper->infile); + + for (failed = length = 0;;) + { + result = read (fd, buffer + length, 256 - length); + + if (result < 0) + { + perror ("read"); + return FALSE; + } + else if (result == 0) + { + if (++failed > 20) + return FALSE; + continue; + } + else if (result + length >= 1024) + { + fprintf (stderr, "Too much output from sudo!\n"); + return FALSE; + } + + length += result; + buffer[length] = 0; + + if (length >= 15) + { + if (strncmp (buffer + (length - 15), "XFSM_SUDO_PASS ", 15) == 0) + { + return FALSE; + } + else if (strncmp (buffer + (length - 15), "XFSM_SUDO_DONE ", 15) == 0) + { + helper->need_password = FALSE; + break; + } + } + } + + return TRUE; +} + + + +gboolean +xfsm_shutdown_helper_send_command (XfsmShutdownHelper *helper, + XfsmShutdownCommand command) +{ + static gchar *command_table[] = { "POWEROFF", "REBOOT" }; + gchar response[256]; + + g_return_val_if_fail (helper != NULL, FALSE); + g_return_val_if_fail (!helper->need_password, FALSE); + + /* check if we can use HAL to perform the requested action */ + if (G_LIKELY (helper->use_hal)) + { + /* well, send the command to HAL then */ + return xfsm_shutdown_helper_hal_send (helper, command); + } + else + { + /* send it to our associated sudo'ed process */ + fprintf (helper->outfile, "%s\n", command_table[command]); + fflush (helper->outfile); + + if (ferror (helper->outfile)) + { + fprintf (stderr, "Error sending command to helper\n"); + return FALSE; + } + + if (fgets (response, 256, helper->infile) == NULL) + { + fprintf (stderr, "No response from helper\n"); + return FALSE; + } + + if (strncmp (response, "SUCCEED", 7) != 0) + { + fprintf (stderr, "Command failed\n"); + return FALSE; + } + } + + return TRUE; +} + + + +void +xfsm_shutdown_helper_destroy (XfsmShutdownHelper *helper) +{ + gint status; + + g_return_if_fail (helper != NULL); + + if (helper->infile != NULL) + fclose (helper->infile); + if (helper->outfile != NULL) + fclose (helper->outfile); + + if (helper->pid > 0) + waitpid (helper->pid, &status, 0); + + g_free (helper->sudo); + g_free (helper); +} -#include XFSM_SHUTDOWN_HELPER_IMPL_C |