From ae28aef315a7a6b90f1649ce6d1f30b842791cbf Mon Sep 17 00:00:00 2001 From: Nick Schermer Date: Sun, 04 Nov 2012 20:23:36 +0000 Subject: Add shutdown/reboot functionality for systemd (bug #8729). Based on patch by Christian Hesse and Evangelos Foutras. --- diff --git a/configure.in.in b/configure.in.in index 9aa4f8f..134d0f7 100644 --- a/configure.in +++ b/configure.in @@ -96,6 +96,10 @@ 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.100], + [systemd], [Systemd support (through polit)]) + dnl Check for debugging support XDT_FEATURE_DEBUG([xfsm_debug_default]) diff --git a/xfce4-session/Makefile.am b/xfce4-session/Makefile.am index c015154..f748b2b 100644 --- a/xfce4-session/Makefile.am +++ b/xfce4-session/Makefile.am @@ -38,8 +38,6 @@ xfce4_session_SOURCES = \ xfsm-compat-gnome.h \ xfsm-compat-kde.c \ xfsm-compat-kde.h \ - xfsm-consolekit.c \ - xfsm-consolekit.h \ xfsm-dns.c \ xfsm-dns.h \ xfsm-error.c \ @@ -65,6 +63,16 @@ xfce4_session_SOURCES = \ xfsm-upower.c \ xfsm-upower.h +if HAVE_SYSTEMD +xfce4_session_SOURCES += \ + xfsm-systemd.c \ + xfsm-systemd.h +else +xfce4_session_SOURCES += \ + xfsm-consolekit.c \ + xfsm-consolekit.h +endif + xfce4_session_CFLAGS = \ $(LIBSM_CFLAGS) \ $(LIBX11_CFLAGS) \ @@ -72,6 +80,7 @@ xfce4_session_CFLAGS = \ $(DBUS_CFLAGS) \ $(DBUS_GLIB_CFLAGS) \ $(LIBWNCK_CFLAGS) \ + $(SYSTEMD_CFLAGS) \ $(XFCONF_CFLAGS) \ $(GMODULE_CFLAGS) \ $(PLATFORM_CFLAGS) @@ -91,6 +100,7 @@ xfce4_session_LDADD = \ $(DBUS_LIBS) \ $(DBUS_GLIB_LIBS) \ $(LIBWNCK_LIBS) \ + $(SYSTEMD_LIBS) \ $(XFCONF_LIBS) \ -lm diff --git a/xfce4-session/xfsm-shutdown.c b/xfce4-session/xfsm-shutdown.c index d8757a8..4c483a7 100644 --- a/xfce4-session/xfsm-shutdown.c +++ b/xfce4-session/xfsm-shutdown.c @@ -66,10 +66,13 @@ #include #include #include -#include #include - +#ifdef HAVE_SYSTEMD +#include +#else +#include +#endif static void xfsm_shutdown_finalize (GObject *object); static void xfsm_shutdown_sudo_free (XfsmShutdown *shutdown); @@ -93,7 +96,11 @@ struct _XfsmShutdown { GObject __parent__; +#ifdef HAVE_SYSTEMD + XfsmSystemd *systemd; +#else XfsmConsolekit *consolekit; +#endif XfsmUPower *upower; /* kiosk settings */ @@ -131,7 +138,11 @@ xfsm_shutdown_init (XfsmShutdown *shutdown) { XfceKiosk *kiosk; +#ifdef HAVE_SYSTEMD + shutdown->systemd = xfsm_systemd_get (); +#else shutdown->consolekit = xfsm_consolekit_get (); +#endif shutdown->upower = xfsm_upower_get (); shutdown->helper_state = SUDO_NOT_INITIAZED; shutdown->helper_require_password = FALSE; @@ -150,7 +161,11 @@ xfsm_shutdown_finalize (GObject *object) { XfsmShutdown *shutdown = XFSM_SHUTDOWN (object); +#ifdef HAVE_SYSTEMD + g_object_unref (G_OBJECT (shutdown->systemd)); +#else g_object_unref (G_OBJECT (shutdown->consolekit)); +#endif g_object_unref (G_OBJECT (shutdown->upower)); /* close down helper */ @@ -641,7 +656,11 @@ xfsm_shutdown_try_restart (XfsmShutdown *shutdown, if (shutdown->helper_state == SUDO_AVAILABLE) return xfsm_shutdown_sudo_try_action (shutdown, XFSM_SHUTDOWN_RESTART, error); else +#ifdef HAVE_SYSTEMD + return xfsm_systemd_try_restart (shutdown->systemd, error); +#else return xfsm_consolekit_try_restart (shutdown->consolekit, error); +#endif } @@ -658,7 +677,11 @@ xfsm_shutdown_try_shutdown (XfsmShutdown *shutdown, if (shutdown->helper_state == SUDO_AVAILABLE) return xfsm_shutdown_sudo_try_action (shutdown, XFSM_SHUTDOWN_SHUTDOWN, error); else +#ifdef HAVE_SYSTEMD + return xfsm_systemd_try_shutdown (shutdown->systemd, error); +#else return xfsm_consolekit_try_shutdown (shutdown->consolekit, error); +#endif } @@ -698,7 +721,11 @@ xfsm_shutdown_can_restart (XfsmShutdown *shutdown, return TRUE; } +#ifdef HAVE_SYSTEMD + if (xfsm_systemd_can_restart (shutdown->systemd, can_restart, error)) +#else if (xfsm_consolekit_can_restart (shutdown->consolekit, can_restart, error)) +#endif return TRUE; if (xfsm_shutdown_sudo_init (shutdown, error)) @@ -725,7 +752,11 @@ xfsm_shutdown_can_shutdown (XfsmShutdown *shutdown, return TRUE; } +#ifdef HAVE_SYSTEMD + if (xfsm_systemd_can_shutdown (shutdown->systemd, can_shutdown, error)) +#else if (xfsm_consolekit_can_shutdown (shutdown->consolekit, can_shutdown, error)) +#endif return TRUE; if (xfsm_shutdown_sudo_init (shutdown, error)) diff --git a/xfce4-session/xfsm-systemd.c b/xfce4-session/xfsm-systemd.c new file mode 100644 index 0000000..7bdd39d --- /dev/null +++ b/xfce4-session/xfsm-systemd.c @@ -0,0 +1,229 @@ +/*- + * Copyright (C) 2012 Christian Hesse + * + * 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., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA. + */ + +#include + +#include +#include +#include +#include + +#include + + + +#define SYSTEMD_DBUS_NAME "org.freedesktop.login1" +#define SYSTEMD_DBUS_PATH "/org/freedesktop/login1" +#define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager" +#define SYSTEMD_REBOOT_ACTION "Reboot" +#define SYSTEMD_POWEROFF_ACTION "PowerOff" +#define SYSTEMD_REBOOT_TEST "org.freedesktop.login1.reboot" +#define SYSTEMD_POWEROFF_TEST "org.freedesktop.login1.power-off" + + + +static void xfsm_systemd_finalize (GObject *object); + + + +struct _XfsmSystemdClass +{ + GObjectClass __parent__; +}; + +struct _XfsmSystemd +{ + GObject __parent__; + + PolkitAuthority *authority; + PolkitSubject *subject; +}; + + + +G_DEFINE_TYPE (XfsmSystemd, xfsm_systemd, G_TYPE_OBJECT) + + + +static void +xfsm_systemd_class_init (XfsmSystemdClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = xfsm_systemd_finalize; +} + + + +static void +xfsm_systemd_init (XfsmSystemd *systemd) +{ + systemd->authority = polkit_authority_get_sync (NULL, NULL); + systemd->subject = polkit_unix_process_new (getpid()); +} + + + +static void +xfsm_systemd_finalize (GObject *object) +{ + XfsmSystemd *systemd = XFSM_SYSTEMD (object); + + g_object_unref (G_OBJECT (systemd->authority)); + g_object_unref (G_OBJECT (systemd->subject)); + + (*G_OBJECT_CLASS (xfsm_systemd_parent_class)->finalize) (object); +} + + +static gboolean +xfsm_systemd_can_method (XfsmSystemd *systemd, + gboolean *can_method, + const gchar *method, + GError **error) +{ + PolkitAuthorizationResult *res; + GError *local_error = NULL; + + *can_method = FALSE; + + res = polkit_authority_check_authorization_sync (systemd->authority, + systemd->subject, + method, + NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE, + NULL, + &local_error); + + if (res == NULL) + { + g_propagate_error (error, local_error); + return FALSE; + } + + *can_method = polkit_authorization_result_get_is_authorized (res) + || polkit_authorization_result_get_is_challenge (res); + + g_object_unref (G_OBJECT (res)); + + return TRUE; +} + + + +static gboolean +xfsm_systemd_try_method (XfsmSystemd *systemd, + const gchar *method, + GError **error) +{ + GDBusConnection *bus; + GError *local_error = NULL; + + bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); + if (G_UNLIKELY (bus == NULL)) + return FALSE; + + g_dbus_connection_call_sync (bus, + SYSTEMD_DBUS_NAME, + SYSTEMD_DBUS_PATH, + SYSTEMD_DBUS_INTERFACE, + method, + g_variant_new ("(b)", TRUE), + NULL, 0, G_MAXINT, NULL, + &local_error); + + g_object_unref (G_OBJECT (bus)); + + if (local_error != NULL) + { + g_propagate_error (error, local_error); + return FALSE; + } + + return TRUE; +} + + + +XfsmSystemd * +xfsm_systemd_get (void) +{ + static XfsmSystemd *object = NULL; + + if (G_LIKELY (object != NULL)) + { + g_object_ref (G_OBJECT (object)); + } + else + { + object = g_object_new (XFSM_TYPE_SYSTEMD, NULL); + g_object_add_weak_pointer (G_OBJECT (object), (gpointer) &object); + } + + return object; +} + + + +gboolean +xfsm_systemd_try_restart (XfsmSystemd *systemd, + GError **error) +{ + return xfsm_systemd_try_method (systemd, + SYSTEMD_REBOOT_ACTION, + error); +} + + + +gboolean +xfsm_systemd_try_shutdown (XfsmSystemd *systemd, + GError **error) +{ + return xfsm_systemd_try_method (systemd, + SYSTEMD_POWEROFF_ACTION, + error); +} + + + +gboolean +xfsm_systemd_can_restart (XfsmSystemd *systemd, + gboolean *can_restart, + GError **error) +{ + return xfsm_systemd_can_method (systemd, + can_restart, + SYSTEMD_REBOOT_TEST, + error); +} + + + +gboolean +xfsm_systemd_can_shutdown (XfsmSystemd *systemd, + gboolean *can_shutdown, + GError **error) +{ + return xfsm_systemd_can_method (systemd, + can_shutdown, + SYSTEMD_POWEROFF_TEST, + error); +} diff --git a/xfce4-session/xfsm-systemd.h b/xfce4-session/xfsm-systemd.h new file mode 100644 index 0000000..8223622 --- /dev/null +++ b/xfce4-session/xfsm-systemd.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2012 Christian Hesse + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __XFSM_SYSTEMD_H__ +#define __XFSM_SYSTEMD_H__ + +typedef struct _XfsmSystemdClass XfsmSystemdClass; +typedef struct _XfsmSystemd XfsmSystemd; + +#define XFSM_TYPE_SYSTEMD (xfsm_systemd_get_type ()) +#define XFSM_SYSTEMD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFSM_TYPE_SYSTEMD, XfsmSystemd)) +#define XFSM_SYSTEMD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XFSM_TYPE_SYSTEMD, XfsmSystemdClass)) +#define XFSM_IS_SYSTEMD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFSM_TYPE_SYSTEMD)) +#define XFSM_IS_SYSTEMD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFSM_TYPE_SYSTEMD)) +#define XFSM_SYSTEMD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XFSM_TYPE_SYSTEMD, XfsmSystemdClass)) + +GType xfsm_systemd_get_type (void) G_GNUC_CONST; + +XfsmSystemd *xfsm_systemd_get (void); + +gboolean xfsm_systemd_try_restart (XfsmSystemd *systemd, + GError **error); + +gboolean xfsm_systemd_try_shutdown (XfsmSystemd *systemd, + GError **error); + +gboolean xfsm_systemd_can_restart (XfsmSystemd *systemd, + gboolean *can_restart, + GError **error); + +gboolean xfsm_systemd_can_shutdown (XfsmSystemd *systemd, + gboolean *can_shutdown, + GError **error); + +G_END_DECLS + +#endif /* __XFSM_SYSTEMD_H__ */ -- cgit v0.9.1