Author: benny Date: 2006-09-08 23:39:43 +0000 (Fri, 08 Sep 2006) New Revision: 23113
Removed: xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper-hal.c xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper-none.c xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper-redhat.c xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper-sudo.c Modified: xfce4-session/trunk/ChangeLog xfce4-session/trunk/README xfce4-session/trunk/configure.in.in xfce4-session/trunk/xfce4-session/Makefile.am xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper.c Log: 2006-09-09 Benedikt Meurer <[EMAIL PROTECTED]> * 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. Modified: xfce4-session/trunk/ChangeLog =================================================================== --- xfce4-session/trunk/ChangeLog 2006-09-08 23:11:30 UTC (rev 23112) +++ xfce4-session/trunk/ChangeLog 2006-09-08 23:39:43 UTC (rev 23113) @@ -1,3 +1,9 @@ +2006-09-09 Benedikt Meurer <[EMAIL PROTECTED]> + + * 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 <[EMAIL PROTECTED]> * configure.in.in: Post-release version bump. Modified: xfce4-session/trunk/README =================================================================== --- xfce4-session/trunk/README 2006-09-08 23:11:30 UTC (rev 23112) +++ xfce4-session/trunk/README 2006-09-08 23:39:43 UTC (rev 23113) @@ -17,12 +17,11 @@ 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: Modified: xfce4-session/trunk/configure.in.in =================================================================== --- xfce4-session/trunk/configure.in.in 2006-09-08 23:11:30 UTC (rev 23112) +++ xfce4-session/trunk/configure.in.in 2006-09-08 23:39:43 UTC (rev 23113) @@ -75,6 +75,10 @@ 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 @@ 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 Modified: xfce4-session/trunk/xfce4-session/Makefile.am =================================================================== --- xfce4-session/trunk/xfce4-session/Makefile.am 2006-09-08 23:11:30 UTC (rev 23112) +++ xfce4-session/trunk/xfce4-session/Makefile.am 2006-09-08 23:39:43 UTC (rev 23113) @@ -1,4 +1,7 @@ +# $Id$ + INCLUDES = \ + -I$(top_builddir) \ -I$(top_srcdir) man_MANS = xfce4-session.1 @@ -42,12 +45,12 @@ 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_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 @@ 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 Deleted: xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper-hal.c Deleted: xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper-none.c Deleted: xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper-redhat.c Deleted: xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper-sudo.c Modified: xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper.c =================================================================== --- xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper.c 2006-09-08 23:11:30 UTC (rev 23112) +++ xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper.c 2006-09-08 23:39:43 UTC (rev 23113) @@ -1,6 +1,6 @@ /* $Id$ */ /*- - * Copyright (c) 2003-2004 Benedikt Meurer <[EMAIL PROTECTED]> + * Copyright (c) 2003-2006 Benedikt Meurer <[EMAIL PROTECTED]> * 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 <[EMAIL PROTECTED]>. */ #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 -#include XFSM_SHUTDOWN_HELPER_IMPL_C +#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); +} + + _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits