[Xfce4-commits] [xfce/xfce4-session] 07/10: Use pkexec for xfsm-shutdown (Bug 9952)

noreply at xfce.org noreply at xfce.org
Thu Aug 28 17:53:08 CEST 2014


This is an automated email from the git hooks/post-receive script.

eric pushed a commit to branch master
in repository xfce/xfce4-session.

commit 29d87f559aadba51e7bd6afcf4aeeb615ecb2145
Author: Eric Koegel <eric.koegel at gmail.com>
Date:   Sun Aug 10 19:16:17 2014 +0300

    Use pkexec for xfsm-shutdown (Bug 9952)
    
    Instead of using the sudo helper, this patch calls xfsm-shutdown
    using pkexec. This way users can use things like fingerprint
    readers for authentication. Also this patch provides suspend/resume
    support since UPower 0.99 dropped it.
---
 configure.ac.in                           |   41 +-
 po/POTFILES.in                            |    2 +-
 xfce4-session/Makefile.am                 |   38 +-
 xfce4-session/org.xfce.session.policy.in2 |   34 ++
 xfce4-session/xfsm-logout-dialog.c        |  155 +-----
 xfce4-session/xfsm-shutdown.c             |  800 +++++++++++------------------
 xfce4-session/xfsm-upower.c               |   12 +-
 xfce4-session/xfsm-upower.h               |    4 +
 xfsm-shutdown-helper/main.c               |  124 ++++-
 9 files changed, 536 insertions(+), 674 deletions(-)

diff --git a/configure.ac.in b/configure.ac.in
index d61b59c..5279667 100644
--- a/configure.ac.in
+++ b/configure.ac.in
@@ -96,9 +96,13 @@ XDT_CHECK_PACKAGE([DBUS], [dbus-1], [1.1.0])
 XDT_CHECK_PACKAGE([DBUS_GLIB], [dbus-glib-1], [0.84])
 XDT_CHECK_PACKAGE([XFCONF], [libxfconf-0], [4.9.0])
 
-dnl Check for polkit / systemd integration
-XDT_CHECK_OPTIONAL_PACKAGE([SYSTEMD], [polkit-gobject-1], [0.102],
-                           [systemd], [Systemd support (through polkit)])
+dnl Check for Polkit/PolicyKit
+XDT_CHECK_OPTIONAL_PACKAGE([POLKIT], [polkit-gobject-1], [0.102],
+                           [polkit], [Polkit support])
+
+dnl Check for Upower
+XDT_CHECK_OPTIONAL_PACKAGE([UPOWER],[upower-glib], [0.9.7],
+			   [upower],[Upower support])
 
 dnl Check for debugging support
 XDT_FEATURE_DEBUG([xfsm_debug_default])
@@ -157,6 +161,31 @@ if test "x$linux_ioprio_works" = "xyes"; then
             [Defined if linux/ioprio.h not only exists, but works properly])
 fi
 
+dnl Compile time default choice of backend
+AC_ARG_WITH([backend],
+	    AS_HELP_STRING([--with-backend=<option>],
+			   [Default backend to use linux, freebsd, openbsd]))
+# default to a sane option
+AC_CANONICAL_HOST
+if test x$with_backend = x; then
+	AS_CASE([$host],
+		[*-linux*],   [with_backend=linux],
+		[*-*freebsd*], [with_backend=freebsd],
+		[*-openbsd*], [with_backend=openbsd])
+fi
+AC_DEFINE_UNQUOTED(BACKEND, "$with_backend", [backend])
+AC_SUBST(BACKEND, "$with_backend")
+
+if test x$with_backend = xlinux; then
+    AC_DEFINE(BACKEND_TYPE_LINUX, 1, [Linux suspend/hibernate backend])
+fi
+if test x$with_backend = xfreebsd; then
+    AC_DEFINE(BACKEND_TYPE_FREEBSD, 1, [FreeBSD suspend/hibernate backend])
+fi
+if test x$with_backend = xopenbsd; then
+    AC_DEFINE(BACKEND_TYPE_OPENBSD, 1, [OpenBSD suspend/hibernate backend])
+fi
+
 dnl check for location Xfce glade files were installed to
 XFCE_GLADE_CATALOG_PATH="`pkg-config --variable glade_catalogdir libxfce4ui-1`"
 XFCE_GLADE_PIXMAP_PATH="`pkg-config --variable glade_pixmapdir libxfce4ui-1`"
@@ -202,10 +231,6 @@ echo " * Legacy session management:      yes"
 else
 echo " * Legacy session management:      no"
 fi
-if test x"$SYSTEMD_FOUND" = x"yes"; then
-echo " * Systemd support (through polkit):          yes"
-else
-echo " * Systemd support (through polkit):          no"
-fi
+echo " * Backend:                        ${with_backend}"
 
 echo
diff --git a/po/POTFILES.in b/po/POTFILES.in
index d9c62a5..bbedcc9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -26,7 +26,7 @@ xfce4-session/xfsm-shutdown.c
 xfce4-session/xfsm-upower.c
 xfce4-session-logout/main.c
 xfce4-session-logout/xfce4-session-logout.desktop.in
-
+xfce4-session/org.xfce.session.policy.in2
 
 # files added by intltool-prepare.
 settings/xfce-session-settings.desktop.in
diff --git a/xfce4-session/Makefile.am b/xfce4-session/Makefile.am
index ea706fd..47df3f4 100644
--- a/xfce4-session/Makefile.am
+++ b/xfce4-session/Makefile.am
@@ -63,13 +63,10 @@ xfce4_session_SOURCES =							\
 	xfsm-startup.c							\
 	xfsm-startup.h							\
 	xfsm-upower.c							\
-	xfsm-upower.h
-
-if HAVE_SYSTEMD
-xfce4_session_SOURCES +=						\
+	xfsm-upower.h							\
 	xfsm-systemd.c							\
 	xfsm-systemd.h
-endif
+
 
 xfce4_session_CFLAGS =							\
 	$(LIBSM_CFLAGS)							\
@@ -78,10 +75,11 @@ xfce4_session_CFLAGS =							\
 	$(DBUS_CFLAGS)							\
 	$(DBUS_GLIB_CFLAGS)						\
 	$(LIBWNCK_CFLAGS)						\
-	$(SYSTEMD_CFLAGS)						\
+	$(POLKIT_CFLAGS)						\
 	$(XFCONF_CFLAGS)						\
 	$(GMODULE_CFLAGS)						\
-	$(PLATFORM_CFLAGS)
+	$(PLATFORM_CFLAGS)						\
+	$(UPOWER_CFLAGS)
 
 xfce4_session_LDFLAGS =							\
 	-no-undefined							\
@@ -98,13 +96,26 @@ xfce4_session_LDADD =							\
 	$(DBUS_LIBS)							\
 	$(DBUS_GLIB_LIBS)						\
 	$(LIBWNCK_LIBS)							\
-	$(SYSTEMD_LIBS)							\
+	$(POLKIT_LIBS)							\
 	$(XFCONF_LIBS)							\
+	$(UPOWER_LIBS)							\
 	-lm
 
 xfce4_session_DEPENDENCIES =						\
 	$(top_builddir)/libxfsm/libxfsm-4.6.la
 
+if HAVE_POLKIT
+
+ at INTLTOOL_POLICY_RULE@
+
+polkit_policydir = $(datadir)/polkit-1/actions
+polkit_policy_DATA =					\
+	org.xfce.session.policy
+.in2.in:
+	sed "s|[@]HELPER_PATH_PREFIX@|${HELPER_PATH_PREFIX}|" $< > $@
+
+endif
+
 if MAINTAINER_MODE
 
 xfsm-chooser-icon.h: $(srcdir)/xfsm-chooser-icon.png
@@ -123,9 +134,6 @@ xfsm-manager-dbus.h: $(srcdir)/xfsm-manager-dbus.xml
 xfsm-client-dbus.h: $(srcdir)/xfsm-client-dbus.xml
 	$(AM_V_GEN) dbus-binding-tool --mode=glib-server --prefix=xfsm_client $< > $@
 
-DISTCLEANFILES =							\
-	$(xfce4_session_built_sources)
-
 BUILT_SOURCES =								\
 	$(xfce4_session_built_sources)
 
@@ -136,6 +144,12 @@ EXTRA_DIST =								\
 	xfsm-chooser-icon.png						\
 	xfsm-marshal.list						\
 	xfsm-client-dbus.xml						\
-	xfsm-manager-dbus.xml
+	xfsm-manager-dbus.xml					\
+	org.xfce.session.policy.in2
+
+DISTCLEANFILES =							\
+	$(xfce4_session_built_sources)			\
+	org.xfce.session.policy					\
+	org.xfce.session.policy.in
 
 # vi:set ts=8 sw=8 noet ai nocindent syntax=automake:
diff --git a/xfce4-session/org.xfce.session.policy.in2 b/xfce4-session/org.xfce.session.policy.in2
new file mode 100644
index 0000000..7f7c5ae
--- /dev/null
+++ b/xfce4-session/org.xfce.session.policy.in2
@@ -0,0 +1,34 @@
+<?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 XFCE Session Manager system-wide actions.
+    Copyright (c) 2014 Eric Koegel <eric at xfce.org>
+    Based on the XFCE Power Manager policy file.
+  -->
+
+  <vendor>XFCE Session Manager</vendor>
+  <vendor_url>http://xfce.org/</vendor_url>
+  <icon_name>xfce4-session</icon_name>
+
+
+  <action id="org.xfce.session.xfsm-shutdown-helper">
+    <!-- SECURITY:
+          - A normal active user on the local machine does not need permission
+            to suspend or hibernate their system.
+     -->
+    <_description>Shutdown, restart, suspend, or hibernate the system</_description>
+    <_message>Authentication is required to shutdown, restart, suspend, or hibernate the system.</_message>
+    <defaults>
+      <allow_any>auth_admin</allow_any>
+      <allow_inactive>auth_admin</allow_inactive>
+      <allow_active>yes</allow_active>
+    </defaults>
+    <annotate key="org.freedesktop.policykit.exec.path">@HELPER_PATH_PREFIX@/xfce4/session/xfsm-shutdown-helper</annotate>
+  </action>
+
+</policyconfig>
+
diff --git a/xfce4-session/xfsm-logout-dialog.c b/xfce4-session/xfsm-logout-dialog.c
index 549eca6..5374551 100644
--- a/xfce4-session/xfsm-logout-dialog.c
+++ b/xfce4-session/xfsm-logout-dialog.c
@@ -72,14 +72,12 @@ static GtkWidget *xfsm_logout_dialog_button   (const gchar      *title,
                                                const gchar      *icon_name_fallback,
                                                XfsmShutdownType  type,
                                                XfsmLogoutDialog *dialog);
-static void       xfsm_logout_dialog_activate (XfsmLogoutDialog *dialog);
 
 
 
 enum
 {
   MODE_LOGOUT_BUTTONS,
-  MODE_ASK_PASSWORD,
   MODE_SHOW_ERROR,
   N_MODES
 };
@@ -107,9 +105,6 @@ struct _XfsmLogoutDialog
   GtkWidget        *button_ok;
   GtkWidget        *button_close;
 
-  /* password entry */
-  GtkWidget        *password_entry;
-
   /* error label */
   GtkWidget        *error_label;
 
@@ -155,7 +150,6 @@ xfsm_logout_dialog_init (XfsmLogoutDialog *dialog)
   gboolean       auth_hibernate = FALSE;
   GError        *error = NULL;
   XfconfChannel *channel;
-  GtkWidget     *entry;
   GtkWidget     *image;
   GtkWidget     *separator;
   gboolean       upower_not_found = FALSE;
@@ -215,22 +209,6 @@ xfsm_logout_dialog_init (XfsmLogoutDialog *dialog)
                                                  GTK_STOCK_CANCEL,
                                                  GTK_RESPONSE_CANCEL);
 
-  /**
-   * Ok, for password mode
-   **/
-  dialog->button_ok = gtk_dialog_add_button (GTK_DIALOG (dialog),
-                                             GTK_STOCK_OK,
-                                             GTK_RESPONSE_OK);
-  gtk_widget_hide (dialog->button_ok);
-
-  /**
-   * Close, for password error
-   **/
-  dialog->button_close = gtk_dialog_add_button (GTK_DIALOG (dialog),
-                                                GTK_STOCK_CLOSE,
-                                                GTK_RESPONSE_CANCEL);
-  gtk_widget_hide (dialog->button_close);
-
   button_vbox = gtk_vbox_new (TRUE, BORDER);
   gtk_box_pack_start (GTK_BOX (vbox), button_vbox, FALSE, TRUE, 0);
   gtk_widget_show (button_vbox);
@@ -374,37 +352,6 @@ xfsm_logout_dialog_init (XfsmLogoutDialog *dialog)
   attrs = pango_attr_list_new ();
   pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
 
-  /**
-   * Start mode MODE_ASK_PASSWORD
-   **/
-  dialog->box[MODE_ASK_PASSWORD] = vbox = gtk_vbox_new (FALSE, BORDER);
-  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, TRUE, TRUE, 0);
-
-  hbox = gtk_hbox_new (FALSE, BORDER * 2);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
-  gtk_widget_show (hbox);
-
-  image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_DIALOG);
-  gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
-  gtk_widget_show (image);
-
-  vbox = gtk_vbox_new (FALSE, BORDER);
-  gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
-  gtk_widget_show (vbox);
-
-  label = gtk_label_new (_("Please enter your password"));
-  gtk_misc_set_alignment (GTK_MISC (label), 0.00, 0.50);
-  gtk_label_set_attributes (GTK_LABEL (label), attrs);
-  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
-  gtk_widget_show (label);
-
-  dialog->password_entry = entry = gtk_entry_new ();
-  gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
-  gtk_entry_set_width_chars (GTK_ENTRY (entry), 30);
-  gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
-  g_signal_connect_swapped (G_OBJECT (entry), "activate",
-                            G_CALLBACK (xfsm_logout_dialog_activate), dialog);
-  gtk_widget_show (entry);
 
   /**
    * Start mode MODE_SHOW_ERROR
@@ -430,14 +377,6 @@ xfsm_logout_dialog_init (XfsmLogoutDialog *dialog)
   gtk_label_set_attributes (GTK_LABEL (label), attrs);
   gtk_widget_show (label);
 
-  label = gtk_label_new (_("Either the password you entered is "
-                           "invalid, or the system administrator "
-                           "disallows shutting down this computer "
-                           "with your user account."));
-  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-  gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
-  gtk_widget_show (label);
-
   pango_attr_list_unref (attrs);
 }
 
@@ -465,7 +404,6 @@ xfsm_logout_dialog_set_mode (XfsmLogoutDialog *dialog,
     gtk_widget_set_visible (dialog->box[i], i == mode);
 
   gtk_widget_set_visible (dialog->button_cancel, mode != MODE_SHOW_ERROR);
-  gtk_widget_set_visible (dialog->button_ok, mode == MODE_ASK_PASSWORD);
   gtk_widget_set_visible (dialog->button_close, mode == MODE_SHOW_ERROR);
 }
 
@@ -548,15 +486,6 @@ xfsm_logout_dialog_button (const gchar      *title,
 
 
 
-static void
-xfsm_logout_dialog_activate (XfsmLogoutDialog *dialog)
-{
-  g_return_if_fail (XFSM_IS_LOGOUT_DIALOG (dialog));
-  gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-}
-
-
-
 static GdkPixbuf *
 xfsm_logout_dialog_screenshot_new (GdkScreen *screen)
 {
@@ -723,8 +652,6 @@ xfsm_logout_dialog (const gchar      *session_name,
   XfsmLogoutDialog *xfsm_dialog;
   XfconfChannel    *channel = xfsm_open_config ();
   gboolean          autosave;
-  const gchar      *text;
-  XfsmPassState     state;
   XfsmShutdown     *shutdown;
 
   g_return_val_if_fail (return_type != NULL, FALSE);
@@ -816,80 +743,16 @@ xfsm_logout_dialog (const gchar      *session_name,
 
   if (result == GTK_RESPONSE_OK)
     {
-      /* check if the sudo helper needs a password */
-      if (xfsm_shutdown_password_require (xfsm_dialog->shutdown, xfsm_dialog->type_clicked))
-        {
-          /* switch mode */
-          xfsm_logout_dialog_set_mode (xfsm_dialog, MODE_ASK_PASSWORD);
-
-          /* don't leave artifacts on the background window */
-          xfsm_fadeout_clear (fadeout);
-
-          /* loop for sudo password tries */
-          for (;;)
-            {
-              gtk_widget_grab_focus (xfsm_dialog->password_entry);
-              gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-              result = xfsm_logout_dialog_run (GTK_DIALOG (dialog), !a11y);
-
-              if (result == GTK_RESPONSE_OK)
-                {
-                  /* bit of visual feedback we're processing the password */
-                  gtk_widget_set_sensitive (xfsm_dialog->button_cancel, FALSE);
-                  gtk_widget_set_sensitive (xfsm_dialog->button_ok, FALSE);
-
-                  /* update the widgets before we lock the loop */
-                  while (gtk_events_pending ())
-                    g_main_context_iteration (NULL, FALSE);
-
-                  /* send the password to the helper */
-                  text = gtk_entry_get_text (GTK_ENTRY (xfsm_dialog->password_entry));
-                  state = xfsm_shutdown_password_send (xfsm_dialog->shutdown, xfsm_dialog->type_clicked, text);
-                  gtk_entry_set_text (GTK_ENTRY (xfsm_dialog->password_entry), "");
-
-                  gtk_widget_set_sensitive (xfsm_dialog->button_cancel, TRUE);
-                  gtk_widget_set_sensitive (xfsm_dialog->button_ok, TRUE);
-
-                  if (state == PASSWORD_RETRY)
-                    continue;
-
-                  if (state == PASSWORD_FAILED)
-                    {
-                      gtk_widget_hide (dialog);
-
-                      xfsm_logout_dialog_set_mode (xfsm_dialog, MODE_SHOW_ERROR);
-                      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
-
-                      /* don't leave artifacts on the background window */
-                      xfsm_fadeout_clear (fadeout);
-
-                      /* show error */
-                      xfsm_logout_dialog_run (GTK_DIALOG (dialog), !a11y);
-
-                      result = GTK_RESPONSE_CANCEL;
-                    }
-                }
-
-              /* cancel clicked, succeeded or helper killed */
-              break;
-            }
-
-          gtk_widget_hide (dialog);
-        }
+      /* store autosave state */
+      if (autosave)
+        *return_save_session = TRUE;
+      else if (xfsm_dialog->save_session != NULL)
+        *return_save_session = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (xfsm_dialog->save_session));
+      else
+        *return_save_session = FALSE;
 
-      if (result == GTK_RESPONSE_OK)
-        {
-          /* store autosave state */
-          if (autosave)
-            *return_save_session = TRUE;
-          else if (xfsm_dialog->save_session != NULL)
-            *return_save_session = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (xfsm_dialog->save_session));
-          else
-            *return_save_session = FALSE;
-
-          /* return the clicked action */
-          *return_type = xfsm_dialog->type_clicked;
-        }
+      /* return the clicked action */
+      *return_type = xfsm_dialog->type_clicked;
     }
 
   if (fadeout != NULL)
diff --git a/xfce4-session/xfsm-shutdown.c b/xfce4-session/xfsm-shutdown.c
index 329c4f6..e32dedf 100644
--- a/xfce4-session/xfsm-shutdown.c
+++ b/xfce4-session/xfsm-shutdown.c
@@ -51,12 +51,20 @@
 #ifdef HAVE_SIGNAL_H
 #include <signal.h>
 #endif
-
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
 
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 #include <libxfce4util/libxfce4util.h>
 #include <gtk/gtk.h>
+#ifdef HAVE_UPOWER
+#include <upower.h>
+#endif
+#ifdef HAVE_POLKIT
+#include <polkit/polkit.h>
+#endif
 
 #include <libxfsm/xfsm-util.h>
 
@@ -68,13 +76,24 @@
 #include <xfce4-session/xfsm-global.h>
 #include <xfce4-session/xfsm-legacy.h>
 #include <xfce4-session/xfsm-upower.h>
-
-#ifdef HAVE_SYSTEMD
 #include <xfce4-session/xfsm-systemd.h>
-#endif
+
+
+
+#define POLKIT_AUTH_SHUTDOWN_XFSM  "org.xfce.session.xfsm-shutdown-helper"
+#define POLKIT_AUTH_RESTART_XFSM   "org.xfce.session.xfsm-shutdown-helper"
+#define POLKIT_AUTH_SUSPEND_XFSM   "org.xfce.session.xfsm-shutdown-helper"
+#define POLKIT_AUTH_HIBERNATE_XFSM "org.xfce.session.xfsm-shutdown-helper"
+
+
 
 static void xfsm_shutdown_finalize  (GObject      *object);
-static void xfsm_shutdown_sudo_free (XfsmShutdown *shutdown);
+static gboolean xfsm_shutdown_fallback_auth_shutdown  (void);
+static gboolean xfsm_shutdown_fallback_auth_restart   (void);
+static gboolean xfsm_shutdown_fallback_can_hibernate  (void);
+static gboolean xfsm_shutdown_fallback_can_suspend    (void);
+static gboolean xfsm_shutdown_fallback_auth_hibernate (void);
+static gboolean xfsm_shutdown_fallback_auth_suspend   (void);
 
 
 
@@ -83,35 +102,18 @@ struct _XfsmShutdownClass
   GObjectClass __parent__;
 };
 
-typedef enum
-{
-  SUDO_NOT_INITIAZED,
-  SUDO_AVAILABLE,
-  SUDO_FAILED
-}
-HelperState;
 
 struct _XfsmShutdown
 {
   GObject __parent__;
 
-#ifdef HAVE_SYSTEMD
   XfsmSystemd    *systemd;
-#endif
   XfsmConsolekit *consolekit;
   XfsmUPower     *upower;
 
   /* kiosk settings */
   gboolean        kiosk_can_shutdown;
   gboolean        kiosk_can_save_session;
-
-  /* sudo helper */
-  HelperState     helper_state;
-  pid_t           helper_pid;
-  FILE           *helper_infile;
-  FILE           *helper_outfile;
-  guint           helper_watchid;
-  gboolean        helper_require_password;
 };
 
 
@@ -136,18 +138,14 @@ xfsm_shutdown_init (XfsmShutdown *shutdown)
 {
   XfceKiosk *kiosk;
 
-#ifdef HAVE_SYSTEMD
   shutdown->consolekit = NULL;
   shutdown->systemd = NULL;
   if (LOGIND_RUNNING())
     shutdown->systemd = xfsm_systemd_get ();
   else
-#endif
-  shutdown->consolekit = xfsm_consolekit_get ();
+    shutdown->consolekit = xfsm_consolekit_get ();
 
   shutdown->upower = xfsm_upower_get ();
-  shutdown->helper_state = SUDO_NOT_INITIAZED;
-  shutdown->helper_require_password = FALSE;
 
   /* check kiosk */
   kiosk = xfce_kiosk_new ("xfce4-session");
@@ -163,392 +161,18 @@ xfsm_shutdown_finalize (GObject *object)
 {
   XfsmShutdown *shutdown = XFSM_SHUTDOWN (object);
 
-#ifdef HAVE_SYSTEMD
   if (shutdown->systemd != NULL)
     g_object_unref (G_OBJECT (shutdown->systemd));
-#endif
+
   if (shutdown->consolekit != NULL)
     g_object_unref (G_OBJECT (shutdown->consolekit));
   g_object_unref (G_OBJECT (shutdown->upower));
 
-  /* close down helper */
-  xfsm_shutdown_sudo_free (shutdown);
-
   (*G_OBJECT_CLASS (xfsm_shutdown_parent_class)->finalize) (object);
 }
 
 
 
-static void
-xfsm_shutdown_sudo_free (XfsmShutdown *shutdown)
-{
-  gint status;
-
-  /* close down helper */
-  if (shutdown->helper_infile != NULL)
-    {
-      fclose (shutdown->helper_infile);
-      shutdown->helper_infile = NULL;
-    }
-
-  if (shutdown->helper_outfile != NULL)
-    {
-      fclose (shutdown->helper_outfile);
-      shutdown->helper_outfile = NULL;
-    }
-
-  if (shutdown->helper_watchid > 0)
-    {
-      g_source_remove (shutdown->helper_watchid);
-      shutdown->helper_watchid = 0;
-    }
-
-  if (shutdown->helper_pid > 0)
-    {
-      waitpid (shutdown->helper_pid, &status, 0);
-      shutdown->helper_pid = 0;
-    }
-
-  /* reset state */
-  shutdown->helper_state = SUDO_NOT_INITIAZED;
-}
-
-
-
-static void
-xfsm_shutdown_sudo_childwatch (GPid     pid,
-                               gint     status,
-                               gpointer data)
-{
-  /* close down sudo stuff */
-  xfsm_shutdown_sudo_free (XFSM_SHUTDOWN (data));
-}
-
-
-
-static gboolean
-xfsm_shutdown_sudo_init (XfsmShutdown  *shutdown,
-                         GError       **error)
-{
-  gchar  *cmd;
-  struct  rlimit rlp;
-  gchar   buf[15];
-  gint    parent_pipe[2];
-  gint    child_pipe[2];
-  gint    n;
-
-  /* return state if we succeeded */
-  if (shutdown->helper_state != SUDO_NOT_INITIAZED)
-    return shutdown->helper_state == SUDO_AVAILABLE;
-
-  g_return_val_if_fail (shutdown->helper_infile == NULL, FALSE);
-  g_return_val_if_fail (shutdown->helper_outfile == NULL, FALSE);
-  g_return_val_if_fail (shutdown->helper_watchid == 0, FALSE);
-  g_return_val_if_fail (shutdown->helper_pid == 0, FALSE);
-
-  /* assume it won't work for now */
-  shutdown->helper_state = SUDO_FAILED;
-
-  cmd = g_find_program_in_path ("sudo");
-  if (G_UNLIKELY (cmd == NULL))
-    {
-      g_set_error_literal (error, 1, 0,
-                           "The program \"sudo\" was not found");
-      return FALSE;
-    }
-
-  if (pipe (parent_pipe) == -1)
-    {
-      g_set_error (error, 1, 0,
-                   "Unable to create parent pipe: %s",
-                   strerror (errno));
-      goto err0;
-    }
-
-  if (pipe (child_pipe) == -1)
-    {
-      g_set_error (error, 1, 0,
-                   "Unable to create child pipe: %s",
-                   strerror (errno));
-      goto err1;
-    }
-
-  shutdown->helper_pid = fork ();
-  if (shutdown->helper_pid < 0)
-    {
-      g_set_error (error, 1, 0,
-                   "Unable to fork sudo helper: %s",
-                   strerror (errno));
-      goto err2;
-    }
-  else if (shutdown->helper_pid == 0)
-    {
-      /* setup signals */
-      signal (SIGPIPE, SIG_IGN);
-
-      /* setup environment */
-      g_setenv ("LC_ALL", "C", TRUE);
-      g_setenv ("LANG", "C", TRUE);
-      g_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 (cmd, "sudo", "-H", "-S", "-p",
-             "XFSM_SUDO_PASS ", "--",
-             XFSM_SHUTDOWN_HELPER_CMD, NULL);
-
-      g_free (cmd);
-      cmd = NULL;
-
-      _exit (127);
-    }
-  else
-    {
-      /* watch the sudo helper */
-      shutdown->helper_watchid = g_child_watch_add (shutdown->helper_pid,
-                                                    xfsm_shutdown_sudo_childwatch,
-                                                    shutdown);
-    }
-
-  /* read sudo/helper answer */
-  n = read (parent_pipe[0], buf, sizeof (buf));
-  if (n < 15)
-    {
-      g_set_error (error, 1, 0,
-                   "Unable to read response from sudo helper: %s",
-                   n < 0 ? strerror (errno) : "Unknown error");
-      goto err2;
-    }
-
-  /* open pipe to receive replies from sudo */
-  shutdown->helper_infile = fdopen (parent_pipe[0], "r");
-  if (shutdown->helper_infile == NULL)
-    {
-      g_set_error (error, 1, 0,
-                   "Unable to open parent pipe: %s",
-                   strerror (errno));
-      goto err2;
-    }
-  close (parent_pipe[1]);
-
-  /* open pipe to send passwords to sudo */
-  shutdown->helper_outfile = fdopen (child_pipe[1], "w");
-  if (shutdown->helper_outfile == NULL)
-    {
-      g_set_error (error, 1, 0,
-                   "Unable to open parent pipe: %s",
-                   strerror (errno));
-      goto err2;
-    }
-  close (child_pipe[0]);
-
-  /* check if NOPASSWD is set in /etc/sudoers */
-  if (memcmp (buf, "XFSM_SUDO_PASS ", 15) == 0)
-    {
-      shutdown->helper_require_password = TRUE;
-    }
-  else if (memcmp (buf, "XFSM_SUDO_DONE ", 15) == 0)
-    {
-      shutdown->helper_require_password = FALSE;
-    }
-  else
-    {
-      g_set_error (error, 1, 0,
-                   "Got unexpected reply from sudo shutdown helper");
-      goto err2;
-    }
-
-  /* if we try again */
-  shutdown->helper_state = SUDO_AVAILABLE;
-
-  return TRUE;
-
-err2:
-  xfsm_shutdown_sudo_free (shutdown);
-
-  close (child_pipe[0]);
-  close (child_pipe[1]);
-
-err1:
-  close (parent_pipe[0]);
-  close (parent_pipe[1]);
-
-err0:
-  g_free (cmd);
-
-  shutdown->helper_pid = 0;
-
-  return FALSE;
-}
-
-
-
-static gboolean
-xfsm_shutdown_sudo_try_action (XfsmShutdown      *shutdown,
-                               XfsmShutdownType   type,
-                               GError           **error)
-{
-  const gchar *action;
-  gchar        reply[256];
-
-  g_return_val_if_fail (shutdown->helper_state == SUDO_AVAILABLE, FALSE);
-  g_return_val_if_fail (shutdown->helper_outfile != NULL, FALSE);
-  g_return_val_if_fail (shutdown->helper_infile != NULL, FALSE);
-  g_return_val_if_fail (type == XFSM_SHUTDOWN_SHUTDOWN
-                        || type == XFSM_SHUTDOWN_RESTART, FALSE);
-
-  /* the command we send to sudo */
-  if (type == XFSM_SHUTDOWN_SHUTDOWN)
-    action = "POWEROFF";
-  else if (type == XFSM_SHUTDOWN_RESTART)
-    action = "REBOOT";
-  else
-    return FALSE;
-
-  /* write action to sudo helper */
-  if (fprintf (shutdown->helper_outfile, "%s\n", action) > 0)
-    fflush (shutdown->helper_outfile);
-
-  /* check if the write succeeded */
-  if (ferror (shutdown->helper_outfile) != 0)
-    {
-      /* probably succeeded but the helper got killed */
-      if (errno == EINTR)
-        return TRUE;
-
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                   _("Error sending command to shutdown helper: %s"),
-                   strerror (errno));
-      return FALSE;
-    }
-
-  /* get responce from sudo helper */
-  if (fgets (reply, sizeof (reply), shutdown->helper_infile) == NULL)
-    {
-      /* probably succeeded but the helper got killed */
-      if (errno == EINTR)
-        return TRUE;
-
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
-                   _("Error receiving response from shutdown helper: %s"),
-                   strerror (errno));
-      return FALSE;
-    }
-
-  if (strncmp (reply, "SUCCEED", 7) != 0)
-    {
-      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
-                   _("Shutdown command failed"));
-
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-
-
-static XfsmPassState
-xfsm_shutdown_sudo_send_password (XfsmShutdown  *shutdown,
-                                  const gchar   *password)
-{
-  gchar        buf[1024];
-  gsize        len_buf, len_send;
-  gint         fd;
-  gsize        len;
-  gssize       result;
-  gint         attempts;
-  const gchar *errmsg = NULL;
-
-  g_return_val_if_fail (shutdown->helper_state == SUDO_AVAILABLE, PASSWORD_FAILED);
-  g_return_val_if_fail (shutdown->helper_outfile != NULL, PASSWORD_FAILED);
-  g_return_val_if_fail (shutdown->helper_infile != NULL, PASSWORD_FAILED);
-  g_return_val_if_fail (shutdown->helper_require_password, PASSWORD_FAILED);
-  g_return_val_if_fail (password != NULL, PASSWORD_FAILED);
-
-  /* write password to sudo helper */
-  g_snprintf (buf, sizeof (buf), "%s\n", password);
-  len_buf = strlen (buf);
-  len_send = fwrite (buf, 1, len_buf, shutdown->helper_outfile);
-  fflush (shutdown->helper_outfile);
-  bzero (buf, len_buf);
-
-  if (len_send != len_buf
-      || ferror (shutdown->helper_outfile) != 0)
-    {
-      errmsg = "Failed to send password to sudo";
-      goto err1;
-    }
-
-  fd = fileno (shutdown->helper_infile);
-
-  for (len = 0, attempts = 0;;)
-    {
-      result = read (fd, buf + len, 256 - len);
-
-      if (result < 0)
-        {
-          errmsg = "Failed to read data from sudo";
-          goto err1;
-        }
-      else if (result == 0)
-        {
-          /* don't try too often */
-          if (++attempts > 20)
-            {
-              errmsg = "Too many password attempts";
-              goto err1;
-            }
-
-          continue;
-        }
-      else if (result + len >= sizeof (buf))
-        {
-          errmsg = "Received too much data from sudo";
-          goto err1;
-        }
-
-      len += result;
-      buf[len] = '\0';
-
-      if (len >= 15)
-        {
-          if (g_str_has_suffix (buf, "XFSM_SUDO_PASS "))
-            {
-              return PASSWORD_RETRY;
-            }
-          else if (g_str_has_suffix (buf, "XFSM_SUDO_DONE "))
-            {
-              /* sudo is unlocked, no further passwords required */
-              shutdown->helper_require_password = FALSE;
-
-              return PASSWORD_SUCCEED;
-            }
-        }
-    }
-
-  return PASSWORD_FAILED;
-
-  err1:
-
-  g_printerr (PACKAGE_NAME ": %s.\n\n", errmsg);
-  return PASSWORD_FAILED;
-}
-
-
-
 static gboolean
 xfsm_shutdown_kiosk_can_shutdown (XfsmShutdown  *shutdown,
                                   GError       **error)
@@ -585,38 +209,6 @@ xfsm_shutdown_get (void)
 
 
 gboolean
-xfsm_shutdown_password_require (XfsmShutdown     *shutdown,
-                                XfsmShutdownType  type)
-{
-  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
-
-  /* the helper only handled shutdown and restart */
-  if (type == XFSM_SHUTDOWN_SHUTDOWN || type == XFSM_SHUTDOWN_RESTART)
-    return shutdown->helper_require_password;
-
-  return FALSE;
-}
-
-
-
-XfsmPassState
-xfsm_shutdown_password_send (XfsmShutdown      *shutdown,
-                             XfsmShutdownType   type,
-                             const gchar       *password)
-{
-  g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), PASSWORD_FAILED);
-  g_return_val_if_fail (password != NULL, PASSWORD_FAILED);
-
-  if ((type == XFSM_SHUTDOWN_SHUTDOWN || type == XFSM_SHUTDOWN_RESTART)
-      && shutdown->helper_state == SUDO_AVAILABLE)
-    return xfsm_shutdown_sudo_send_password (shutdown, password);
-
-  return PASSWORD_FAILED;
-}
-
-
-
-gboolean
 xfsm_shutdown_try_type (XfsmShutdown      *shutdown,
                         XfsmShutdownType   type,
                         GError           **error)
@@ -647,6 +239,36 @@ xfsm_shutdown_try_type (XfsmShutdown      *shutdown,
 
 
 
+static gboolean
+xfsm_shutdown_fallback_try_action (XfsmShutdown      *shutdown,
+                                   XfsmShutdownType   type,
+                                   GError           **error)
+{
+  const gchar *action;
+  gboolean ret;
+  gint exit_status = 0;
+  gchar *command = NULL;
+
+  if (type == XFSM_SHUTDOWN_SHUTDOWN)
+    action = "shutdown";
+  if (type == XFSM_SHUTDOWN_RESTART)
+    action = "restart";
+  else if (type == XFSM_SHUTDOWN_SUSPEND)
+    action = "suspend";
+  else if (type == XFSM_SHUTDOWN_HIBERNATE)
+    action = "hibernate";
+  else
+      return FALSE;
+
+  command = g_strdup_printf ("pkexec " XFSM_SHUTDOWN_HELPER_CMD " --%s", action);
+  ret = g_spawn_command_line_sync (command, NULL, NULL, &exit_status, error);
+
+  g_free (command);
+  return ret;
+}
+
+
+
 gboolean
 xfsm_shutdown_try_restart (XfsmShutdown  *shutdown,
                            GError       **error)
@@ -656,15 +278,13 @@ xfsm_shutdown_try_restart (XfsmShutdown  *shutdown,
   if (!xfsm_shutdown_kiosk_can_shutdown (shutdown, error))
     return FALSE;
 
-  if (shutdown->helper_state == SUDO_AVAILABLE)
-    return xfsm_shutdown_sudo_try_action (shutdown, XFSM_SHUTDOWN_RESTART, error);
-  else
-#ifdef HAVE_SYSTEMD
-    if (shutdown->systemd != NULL)
-      return xfsm_systemd_try_restart (shutdown->systemd, error);
-    else
-#endif
+  if (shutdown->systemd != NULL)
+    return xfsm_systemd_try_restart (shutdown->systemd, error);
+
+  if (shutdown->consolekit != NULL)
     return xfsm_consolekit_try_restart (shutdown->consolekit, error);
+
+  return xfsm_shutdown_fallback_try_action (shutdown, XFSM_SHUTDOWN_RESTART, error);
 }
 
 
@@ -678,15 +298,13 @@ xfsm_shutdown_try_shutdown (XfsmShutdown  *shutdown,
   if (!xfsm_shutdown_kiosk_can_shutdown (shutdown, error))
     return FALSE;
 
-  if (shutdown->helper_state == SUDO_AVAILABLE)
-    return xfsm_shutdown_sudo_try_action (shutdown, XFSM_SHUTDOWN_SHUTDOWN, error);
-  else
-#ifdef HAVE_SYSTEMD
-    if (shutdown->systemd != NULL)
-      return xfsm_systemd_try_shutdown (shutdown->systemd, error);
-    else
-#endif
+  if (shutdown->systemd != NULL)
+    return xfsm_systemd_try_shutdown (shutdown->systemd, error);
+
+  if (shutdown->consolekit != NULL)
     return xfsm_consolekit_try_shutdown (shutdown->consolekit, error);
+
+  return xfsm_shutdown_fallback_try_action (shutdown, XFSM_SHUTDOWN_SHUTDOWN, error);
 }
 
 
@@ -697,12 +315,18 @@ xfsm_shutdown_try_suspend (XfsmShutdown  *shutdown,
 {
   g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
 
-#ifdef HAVE_SYSTEMD
   if (shutdown->systemd != NULL)
     return xfsm_systemd_try_suspend (shutdown->systemd, error);
-  else
-#endif
-  return xfsm_upower_try_suspend (shutdown->upower, error);
+
+#ifdef HAVE_UPOWER
+#if !UP_CHECK_VERSION(0, 99, 0)
+  if (shutdown->upower != NULL)
+    return xfsm_upower_try_suspend (shutdown->upower, error);
+#endif /* UP_CHECK_VERSION */
+#endif /* HAVE_UPOWER */
+
+  xfsm_upower_lock_screen (shutdown->upower, "Suspend", error);
+  return xfsm_shutdown_fallback_try_action (shutdown, XFSM_SHUTDOWN_SUSPEND, error);
 }
 
 
@@ -713,12 +337,18 @@ xfsm_shutdown_try_hibernate (XfsmShutdown  *shutdown,
 {
   g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
 
-#ifdef HAVE_SYSTEMD
   if (shutdown->systemd != NULL)
     return xfsm_systemd_try_hibernate (shutdown->systemd, error);
-  else
-#endif
-  return xfsm_upower_try_hibernate (shutdown->upower, error);
+
+#ifdef HAVE_UPOWER
+#if !UP_CHECK_VERSION(0, 99, 0)
+  if (shutdown->upower != NULL)
+    return xfsm_upower_try_hibernate (shutdown->upower, error);
+#endif /* UP_CHECK_VERSION */
+#endif /* HAVE_UPOWER */
+
+  xfsm_upower_lock_screen (shutdown->upower, "Hibernate", error);
+  return xfsm_shutdown_fallback_try_action (shutdown, XFSM_SHUTDOWN_HIBERNATE, error);
 }
 
 
@@ -736,24 +366,19 @@ xfsm_shutdown_can_restart (XfsmShutdown  *shutdown,
       return TRUE;
     }
 
-#ifdef HAVE_SYSTEMD
   if (shutdown->systemd != NULL)
     {
       if (xfsm_systemd_can_restart (shutdown->systemd, can_restart, error))
         return TRUE;
     }
-  else
-#endif
-  if (xfsm_consolekit_can_restart (shutdown->consolekit, can_restart, error))
-    return TRUE;
-
-  if (xfsm_shutdown_sudo_init (shutdown, error))
+  else if (shutdown->consolekit != NULL)
     {
-      *can_restart = TRUE;
-      return TRUE;
+      if (xfsm_consolekit_can_restart (shutdown->consolekit, can_restart, error))
+        return TRUE;
     }
 
-  return FALSE;
+  *can_restart = xfsm_shutdown_fallback_auth_restart ();
+  return TRUE;
 }
 
 
@@ -771,24 +396,20 @@ xfsm_shutdown_can_shutdown (XfsmShutdown  *shutdown,
       return TRUE;
     }
 
-#ifdef HAVE_SYSTEMD
   if (shutdown->systemd != NULL)
     {
       if (xfsm_systemd_can_shutdown (shutdown->systemd, can_shutdown, error))
         return TRUE;
     }
-  else
-#endif
-  if (xfsm_consolekit_can_shutdown (shutdown->consolekit, can_shutdown, error))
-    return TRUE;
 
-  if (xfsm_shutdown_sudo_init (shutdown, error))
+  if (shutdown->consolekit != NULL)
     {
-      *can_shutdown = TRUE;
-      return TRUE;
+      if (xfsm_consolekit_can_shutdown (shutdown->consolekit, can_shutdown, error))
+        return TRUE;
     }
 
-  return FALSE;
+  *can_shutdown = xfsm_shutdown_fallback_auth_shutdown ();
+  return TRUE;
 }
 
 
@@ -807,14 +428,21 @@ xfsm_shutdown_can_suspend (XfsmShutdown  *shutdown,
       return TRUE;
     }
 
-#ifdef HAVE_SYSTEMD
   if (shutdown->systemd != NULL)
     return xfsm_systemd_can_suspend (shutdown->systemd, can_suspend,
                                      auth_suspend, error);
-  else
-#endif
-  return xfsm_upower_can_suspend (shutdown->upower, can_suspend, 
-                                  auth_suspend, error);
+
+#ifdef HAVE_UPOWER
+#if !UP_CHECK_VERSION(0, 99, 0)
+  if (shutdown->upower)
+    return xfsm_upower_can_suspend (shutdown->upower, can_suspend,
+                                    auth_suspend, error);
+#endif /* UP_CHECK_VERSION */
+#endif /* HAVE_UPOWER */
+
+  *can_suspend = xfsm_shutdown_fallback_can_suspend ();
+  *auth_suspend = xfsm_shutdown_fallback_auth_suspend ();
+  return TRUE;
 }
 
 
@@ -833,14 +461,21 @@ xfsm_shutdown_can_hibernate (XfsmShutdown  *shutdown,
       return TRUE;
     }
 
-#ifdef HAVE_SYSTEMD
   if (shutdown->systemd != NULL)
     return xfsm_systemd_can_hibernate (shutdown->systemd, can_hibernate,
                                        auth_hibernate, error);
-  else
-#endif
-  return xfsm_upower_can_hibernate (shutdown->upower, can_hibernate,
-                                    auth_hibernate, error);
+
+#ifdef HAVE_UPOWER
+#if !UP_CHECK_VERSION(0, 99, 0)
+  if (shutdown->upower != NULL)
+    return xfsm_upower_can_hibernate (shutdown->upower, can_hibernate,
+                                      auth_hibernate, error);
+#endif /* UP_CHECK_VERSION */
+#endif /* HAVE_UPOWER */
+
+  *can_hibernate = xfsm_shutdown_fallback_can_hibernate ();
+  *auth_hibernate = xfsm_shutdown_fallback_auth_hibernate ();
+  return TRUE;
 }
 
 
@@ -851,3 +486,194 @@ xfsm_shutdown_can_save_session (XfsmShutdown *shutdown)
   g_return_val_if_fail (XFSM_IS_SHUTDOWN (shutdown), FALSE);
   return shutdown->kiosk_can_save_session;
 }
+
+
+
+#ifdef BACKEND_TYPE_FREEBSD
+static gchar *
+get_string_sysctl (GError **err, const gchar *format, ...)
+{
+        va_list args;
+        gchar *name;
+        size_t value_len;
+        gchar *str = NULL;
+
+        g_return_val_if_fail(format != NULL, FALSE);
+
+        va_start (args, format);
+        name = g_strdup_vprintf (format, args);
+        va_end (args);
+
+        if (sysctlbyname (name, NULL, &value_len, NULL, 0) == 0) {
+                str = g_new (char, value_len + 1);
+                if (sysctlbyname (name, str, &value_len, NULL, 0) == 0)
+                        str[value_len] = 0;
+                else {
+                        g_free (str);
+                        str = NULL;
+                }
+        }
+
+        if (!str)
+                g_set_error (err, 0, 0, "%s", g_strerror(errno));
+
+        g_free(name);
+        return str;
+}
+
+
+
+static gboolean
+freebsd_supports_sleep_state (const gchar *state)
+{
+  gboolean ret = FALSE;
+  gchar *sleep_states;
+
+  sleep_states = get_string_sysctl (NULL, "hw.acpi.supported_sleep_state");
+  if (sleep_states != NULL)
+    {
+      if (strstr (sleep_states, state) != NULL)
+          ret = TRUE;
+    }
+
+  g_free (sleep_states);
+
+  return ret;
+}
+#endif /* BACKEND_TYPE_FREEBSD */
+
+
+
+#ifdef BACKEND_TYPE_LINUX
+static gboolean
+linux_supports_sleep_state (const gchar *state)
+{
+  gboolean ret = FALSE;
+  gchar *command;
+  GError *error = NULL;
+  gint exit_status;
+
+  /* run script from pm-utils */
+  command = g_strdup_printf ("/usr/bin/pm-is-supported --%s", state);
+
+  ret = g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error);
+  if (!ret)
+    {
+      g_warning ("failed to run script: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+  ret = (WIFEXITED(exit_status) && (WEXITSTATUS(exit_status) == EXIT_SUCCESS));
+
+out:
+  g_free (command);
+
+  return ret;
+}
+#endif /* BACKEND_TYPE_LINUX */
+
+
+
+static gboolean
+xfsm_shutdown_fallback_can_suspend (void)
+{
+#ifdef BACKEND_TYPE_FREEBSD
+  return freebsd_supports_sleep_state ("S3");
+#endif
+#ifdef BACKEND_TYPE_LINUX
+  return linux_supports_sleep_state ("suspend");
+#endif
+#ifdef BACKEND_TYPE_OPENBSD
+  return TRUE;
+#endif
+
+  return FALSE;
+}
+
+
+
+static gboolean
+xfsm_shutdown_fallback_can_hibernate (void)
+{
+#ifdef BACKEND_TYPE_FREEBSD
+  return freebsd_supports_sleep_state ("S4");
+#endif
+#ifdef BACKEND_TYPE_LINUX
+  return linux_supports_sleep_state ("hibernate");
+#endif
+#ifdef BACKEND_TYPE_OPENBSD
+  return TRUE;
+#endif
+
+  return FALSE;
+}
+
+
+
+static gboolean
+xfsm_shutdown_fallback_check_auth (const gchar *action_id)
+{
+  gboolean auth_result = FALSE;
+#ifdef HAVE_POLKIT
+  GDBusConnection *bus;
+  PolkitAuthority *polkit;
+  PolkitAuthorizationResult *polkit_result;
+  PolkitSubject *polkit_subject;
+
+  bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+  polkit = polkit_authority_get_sync (NULL, NULL);
+  if (polkit != NULL && bus != NULL)
+    {
+      polkit_subject = polkit_system_bus_name_new (g_dbus_connection_get_unique_name (bus));
+      polkit_result = polkit_authority_check_authorization_sync (polkit,
+                                                                 polkit_subject,
+                                                                 action_id,
+                                                                 NULL,
+                                                                 POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
+                                                                 NULL,
+                                                                 NULL);
+      if (polkit_result != NULL)
+        {
+          auth_result = polkit_authorization_result_get_is_authorized (polkit_result);
+          g_object_unref (polkit_result);
+        }
+
+        g_object_unref (polkit);
+        g_object_unref (bus);
+      }
+#endif /* HAVE_POLKIT */
+
+  return auth_result;
+}
+
+
+
+static gboolean
+xfsm_shutdown_fallback_auth_shutdown (void)
+{
+  return xfsm_shutdown_fallback_check_auth (POLKIT_AUTH_SHUTDOWN_XFSM);
+}
+
+
+
+static gboolean
+xfsm_shutdown_fallback_auth_restart (void)
+{
+  return xfsm_shutdown_fallback_check_auth (POLKIT_AUTH_RESTART_XFSM);
+}
+
+
+
+static gboolean
+xfsm_shutdown_fallback_auth_suspend (void)
+{
+  return xfsm_shutdown_fallback_check_auth (POLKIT_AUTH_SUSPEND_XFSM);
+}
+
+
+
+static gboolean
+xfsm_shutdown_fallback_auth_hibernate (void)
+{
+  return xfsm_shutdown_fallback_check_auth (POLKIT_AUTH_HIBERNATE_XFSM);
+}
diff --git a/xfce4-session/xfsm-upower.c b/xfce4-session/xfsm-upower.c
index 57402ec..050872a 100644
--- a/xfce4-session/xfsm-upower.c
+++ b/xfce4-session/xfsm-upower.c
@@ -21,6 +21,9 @@
 
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
+#ifdef HAVE_UPOWER
+#include <upower.h>
+#endif /* HAVE_UPOWER */
 
 #include <libxfsm/xfsm-util.h>
 #include <xfce4-session/xfsm-upower.h>
@@ -283,14 +286,13 @@ xfsm_upower_try_method (XfsmUPower   *upower,
 
 
 
-static gboolean
+gboolean
 xfsm_upower_lock_screen (XfsmUPower   *upower,
                          const gchar  *sleep_kind,
                          GError      **error)
 {
   XfconfChannel *channel;
   gboolean       ret = TRUE;
-  GError        *err = NULL;
 
   g_return_val_if_fail (sleep_kind != NULL, FALSE);
 
@@ -299,6 +301,10 @@ xfsm_upower_lock_screen (XfsmUPower   *upower,
     {
       if (xfsm_upower_proxy_ensure (upower, error))
         {
+#ifdef HAVE_UPOWER
+#if !UP_CHECK_VERSION(0, 99, 0)
+          GError        *err = NULL;
+
           /* tell upower we're going to sleep, this saves some
            * time while we sleep 1 second if xflock4 is spawned */
           ret = dbus_g_proxy_call (upower->upower_proxy,
@@ -312,6 +318,8 @@ xfsm_upower_lock_screen (XfsmUPower   *upower,
               g_warning ("Couldn't sent that we were about to sleep: %s", err->message);
               g_error_free (err);
             }
+#endif /* UP_CHECK_VERSION */
+#endif /* HAVE_UPOWER */
         }
       else
         {
diff --git a/xfce4-session/xfsm-upower.h b/xfce4-session/xfsm-upower.h
index a492f7d..4e6a53b 100644
--- a/xfce4-session/xfsm-upower.h
+++ b/xfce4-session/xfsm-upower.h
@@ -51,4 +51,8 @@ gboolean        xfsm_upower_can_hibernate    (XfsmUPower      *upower,
                                               gboolean        *auth_hibernate,
                                               GError         **error);
 
+gboolean        xfsm_upower_lock_screen      (XfsmUPower      *upower,
+                                              const gchar     *sleep_kind,
+                                              GError         **error);
+
 #endif /* !__XFSM_UPOWER_HELPER_H__ */
diff --git a/xfsm-shutdown-helper/main.c b/xfsm-shutdown-helper/main.c
index 667f288..2c9bb1a 100644
--- a/xfsm-shutdown-helper/main.c
+++ b/xfsm-shutdown-helper/main.c
@@ -51,12 +51,23 @@
 #include <glib.h>
 
 /* XXX */
+#define EXIT_CODE_SUCCESS           0
+#define EXIT_CODE_FAILED            1
+#define EXIT_CODE_ARGUMENTS_INVALID 3
+#define EXIT_CODE_INVALID_USER      4
+
 #ifdef POWEROFF_CMD
 #undef POWEROFF_CMD
 #endif
 #ifdef REBOOT_CMD
 #undef REBOOT_CMD
 #endif
+#ifdef UP_BACKEND_SUSPEND_COMMAND
+#undef UP_BACKEND_SUSPEND_COMMAND
+#endif
+#ifdef UP_BACKEND_HIBERNATE_COMMAND
+#undef UP_BACKEND_HIBERNATE_COMMAND
+#endif
 
 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
 #define POWEROFF_CMD  "/sbin/shutdown -p now"
@@ -68,6 +79,18 @@
 #define POWEROFF_CMD  "/sbin/shutdown -h now"
 #define REBOOT_CMD    "/sbin/shutdown -r now"
 #endif
+#ifdef BACKEND_TYPE_FREEBSD
+#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/acpiconf -s 3"
+#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/acpiconf -s 4"
+#endif
+#if BACKEND_TYPE_LINUX
+#define UP_BACKEND_SUSPEND_COMMAND "/usr/sbin/pm-suspend"
+#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/pm-hibernate"
+#endif
+#ifdef BACKEND_TYPE_OPENBSD
+#define UP_BACKEND_SUSPEND_COMMAND	"/usr/sbin/zzz"
+#define UP_BACKEND_HIBERNATE_COMMAND "/usr/sbin/ZZZ"
+#endif
 
 
 static gboolean
@@ -122,36 +145,101 @@ run (const gchar *command)
 int
 main (int argc, char **argv)
 {
-  gboolean succeed = FALSE;
-  char action[1024];
+  GOptionContext *context;
+  gint uid;
+  gint euid;
+  const gchar *pkexec_uid_str;
+  gboolean shutdown = FALSE;
+  gboolean restart = FALSE;
+  gboolean suspend = FALSE;
+  gboolean hibernate = FALSE;
+
+  const GOptionEntry options[] = {
+    { "shutdown",  '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &shutdown, "Shutdown the system", NULL },
+    { "restart",   '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &restart, "Restart the system", NULL },
+    { "suspend",   '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &suspend, "Suspend the system", NULL },
+    { "hibernate", '\0', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &hibernate, "Hibernate the system", NULL },
+    { NULL }
+  };
+
+  context = g_option_context_new (NULL);
+  g_option_context_set_summary (context, "XFCE Session 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 (!shutdown && !restart && !suspend && !hibernate)
+    {
+      puts ("No valid option was specified");
+      return EXIT_CODE_ARGUMENTS_INVALID;
+    }
 
-  /* display banner */
-  fprintf (stdout, "XFSM_SUDO_DONE ");
-  fflush (stdout);
+  /* get calling process */
+  uid = getuid ();
+  euid = geteuid ();
+  if (uid != 0 || euid != 0)
+    {
+      puts ("This program can only be used by the root user");
+      return EXIT_CODE_ARGUMENTS_INVALID;
+    }
 
-  if (fgets (action, 1024, stdin) == NULL)
+  /* check we're not being spoofed */
+  pkexec_uid_str = g_getenv ("PKEXEC_UID");
+  if (pkexec_uid_str == NULL)
     {
-      fprintf (stdout, "FAILED\n");
-      return EXIT_FAILURE;
+      puts ("This program must only be run through pkexec");
+      return EXIT_CODE_INVALID_USER;
     }
 
-  if (strncasecmp (action, "POWEROFF", 8) == 0)
+  /* run the command */
+  if(shutdown)
     {
-      succeed = run (POWEROFF_CMD);
+      if (run (POWEROFF_CMD))
+          {
+            return EXIT_CODE_SUCCESS;
+          }
+        else
+          {
+            return EXIT_CODE_FAILED;
+          }
     }
-  else if (strncasecmp (action, "REBOOT", 6) == 0)
+  else if(restart)
     {
-      succeed = run (REBOOT_CMD);
+      if (run (REBOOT_CMD))
+          {
+            return EXIT_CODE_SUCCESS;
+          }
+        else
+          {
+            return EXIT_CODE_FAILED;
+          }
     }
-
-  if (succeed)
+  else if(suspend)
+    {
+      if (run (UP_BACKEND_SUSPEND_COMMAND))
+          {
+            return EXIT_CODE_SUCCESS;
+          }
+        else
+          {
+            return EXIT_CODE_FAILED;
+          }
+    }
+  else if(hibernate)
     {
-      fprintf (stdout, "SUCCEED\n");
-      return EXIT_SUCCESS;
+      if (run (UP_BACKEND_HIBERNATE_COMMAND))
+          {
+            return EXIT_CODE_SUCCESS;
+          }
+        else
+          {
+            return EXIT_CODE_FAILED;
+          }
     }
 
-  fprintf (stdout, "FAILED\n");
-  return EXIT_FAILURE;
+  /* how did we get here? */
+  return EXIT_CODE_FAILED;
 }
 
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list