summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Šimerda <psimerda@redhat.com>2013-07-30 23:09:52 +0200
committerThomas Haller <thaller@redhat.com>2014-05-23 16:11:24 +0200
commitb6a52b5e5ec846f0a7eab991d112ff350a66554e (patch)
treecbd5b6defa014d287696bd662ea8ef005efe147e
parent258e3cfdf419e1e9b506ebe1839bb373c72a00f1 (diff)
downloadNetworkManager-b6a52b5e5ec846f0a7eab991d112ff350a66554e.tar.gz
core: runtime detect systemd-logind and fallback to ConsoleKit (bgo #686997)
Merged all session tracking modules into one source file and simplified it substantially. Now systemd-logind is used for session tracking if available and fallback to consolekit is supported. The setup can be further tweaked at build time using the new flexible configure options as well as the old ones for compatibility. https://bugzilla.gnome.org/show_bug.cgi?id=686997 Based-on-patch-by: Fabio Erculiani <lxnay@sabayon.org> Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--configure.ac53
-rw-r--r--src/Makefile.am16
-rw-r--r--src/nm-session-monitor-null.c168
-rw-r--r--src/nm-session-monitor-systemd.c267
-rw-r--r--src/nm-session-monitor.c (renamed from src/nm-session-monitor-ck.c)501
-rw-r--r--src/nm-session-monitor.h1
-rw-r--r--src/nm-session-utils.c79
-rw-r--r--src/nm-session-utils.h41
8 files changed, 392 insertions, 734 deletions
diff --git a/configure.ac b/configure.ac
index cfccfc2e00..51f59a1530 100644
--- a/configure.ac
+++ b/configure.ac
@@ -312,29 +312,44 @@ fi
PKG_CHECK_MODULES(SYSTEMD_200, [systemd >= 200], [have_systemd_200=yes],[have_systemd_200=no])
AM_CONDITIONAL(HAVE_SYSTEMD_200, test "${have_systemd_200}" = "yes")
-# session tracking support
-AC_MSG_CHECKING([Session tracking support])
-AC_ARG_WITH(session-tracking, AS_HELP_STRING([--with-session-tracking=systemd|consolekit|no],
- [Select session tracking support (default: consolekit)]))
-# default to consolekit
-AS_IF([test -z "$with_session_tracking"], with_session_tracking=consolekit)
-AS_IF([test "$with_session_tracking" = "ck"], with_session_tracking=consolekit)
-AS_IF([test "$with_session_tracking" = "none"], with_session_tracking=no)
-# check value
-AS_IF([! (echo "$with_session_tracking" | grep -q -E "^(systemd|consolekit|no)$")],
- AC_MSG_ERROR([--with-session-tracking must be systemd/consolekit/no, not $with_session_tracking]))
-# add conditionals and subtitutions
-AM_CONDITIONAL(SESSION_TRACKING_CK, test "$with_session_tracking" = "consolekit")
-AM_CONDITIONAL(SESSION_TRACKING_SYSTEMD, test "$with_session_tracking" = "systemd")
-if test "$with_session_tracking" = "systemd"; then
+# Session tracking support
+AC_ARG_WITH(systemd-logind, AS_HELP_STRING([--with-systemd-logind=yes|no],
+ [Support systemd session tracking]))
+AC_ARG_WITH(consolekit, AS_HELP_STRING([--with-consolekit=yes|no],
+ [Support consolekit session tracking]))
+AC_ARG_WITH(fake-session, AS_HELP_STRING([--with-fake-session=yes|no],
+ [Any user is assumed to have a session]))
+# defaults
+AS_IF([test -z "$with_systemd_logind"], [with_systemd_logind="yes"])
+AS_IF([test -z "$with_consolekit"], [with_consolekit="yes"])
+AS_IF([test -z "$with_fake_session"], [with_fake_session="no"])
+# backwards compatibility
+AS_IF([test "$with_session_tracking" = "ck"], [with_consolekit="yes" with_systemd_login="no"])
+AS_IF([test "$with_session_tracking" = "consolekit"], [with_consolekit="yes" with_systemd_login="no"])
+AS_IF([test "$with_session_tracking" = "systemd"], [with_consolekit="no" with_systemd_login="yes"])
+AS_IF([test "$with_session_tracking" = "none"], [with_fake_session="yes"])
+AS_IF([test "$with_session_tracking" = "no"], [with_fake_session="yes"])
+# consistency
+AS_IF([test "$with_fake_session" = "yes"], [with_consolekit="no" with_systemd_login="no"])
+# output
+session_tracking=
+if test "$with_systemd_logind" = "yes"; then
PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd-login])
AC_SUBST(SYSTEMD_LOGIN_CFLAGS)
AC_SUBST(SYSTEMD_LOGIN_LIBS)
+ AC_DEFINE([SESSION_TRACKING_SYSTEMD], 1, [Define to 1 if libsystemd-login is available])
+ session_tracking="$session_tracking, systemd-logind"
fi
-if test "$with_session_tracking" = "consolekit"; then
- AC_SUBST(CKDB_PATH, /var/run/ConsoleKit/database)
+if test "$with_consolekit" = "yes"; then
+ AC_DEFINE([SESSION_TRACKING_CONSOLEKIT], 1, [Define to 1 if ConsoleKit is available])
+ AC_DEFINE([CKDB_PATH], "/var/run/ConsoleKit/database", [Path to ConsoleKit database])
+ session_tracking="$session_tracking, consolekit"
fi
-AC_MSG_RESULT($with_session_tracking)
+if test "$with_fake_session" = "yes"; then
+ AC_DEFINE([SESSION_TRACKING_FAKE], 1, [Define to 1 if fake session tracking is used])
+ session_tracking="$session_tracking, fake"
+fi
+session_tracking=${session_tracking:2}
AC_ARG_WITH(suspend-resume, AS_HELP_STRING([--with-suspend-resume=upower|systemd], [Build NetworkManager with specific suspend/resume support]))
if test "z$with_suspend_resume" = "z"; then
@@ -874,7 +889,7 @@ echo " nmrundir: $nmrundir"
echo
echo "Platform:"
-echo " session tracking: $with_session_tracking"
+echo " session tracking: $session_tracking"
echo " suspend/resume: $with_suspend_resume"
if test "${enable_polkit}" = "yes"; then
if test "${enable_modify_system}" = "yes"; then
diff --git a/src/Makefile.am b/src/Makefile.am
index 53fc35c1fb..dae20c9390 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -234,22 +234,12 @@ nm_sources = \
nm-rfkill-manager.c \
nm-rfkill-manager.h \
nm-session-monitor.h \
- nm-session-utils.c \
- nm-session-utils.h \
+ nm-session-monitor.c \
nm-sleep-monitor.h \
nm-types.h \
NetworkManagerUtils.c \
NetworkManagerUtils.h
-if SESSION_TRACKING_SYSTEMD
-nm_sources += nm-session-monitor-systemd.c
-else
-if SESSION_TRACKING_CK
-nm_sources += nm-session-monitor-ck.c
-else
-nm_sources += nm-session-monitor-null.c
-endif
-endif
if SUSPEND_RESUME_SYSTEMD
nm_sources += nm-sleep-monitor-systemd.c
@@ -341,10 +331,6 @@ AM_CPPFLAGS += \
\
$(NULL)
-if SESSION_TRACKING_CK
-AM_CPPFLAGS += -DCKDB_PATH=\"${CKDB_PATH}\"
-endif
-
if WITH_TEAMDCTL
AM_CPPFLAGS += ${LIBTEAMDCTL_CFLAGS}
endif
diff --git a/src/nm-session-monitor-null.c b/src/nm-session-monitor-null.c
deleted file mode 100644
index 5d8ecaaf1a..0000000000
--- a/src/nm-session-monitor-null.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* 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.
- *
- * (C) Copyright 2008 - 2010 Red Hat, Inc.
- * Author: David Zeuthen <davidz@redhat.com>
- * Author: Dan Williams <dcbw@redhat.com>
- */
-
-#include "config.h"
-#include <string.h>
-#include "nm-logging.h"
-
-#include "nm-session-utils.h"
-#include "nm-session-monitor.h"
-
-/* <internal>
- * SECTION:nm-session-monitor
- * @title: NMSessionMonitor
- * @short_description: Monitor sessions
- *
- * The #NMSessionMonitor class is a utility class to track and monitor sessions.
- */
-
-struct _NMSessionMonitor {
- GObject parent_instance;
-};
-
-struct _NMSessionMonitorClass {
- GObjectClass parent_class;
-
- void (*changed) (NMSessionMonitor *monitor);
-};
-
-
-enum {
- CHANGED,
- LAST_SIGNAL,
-};
-static guint signals[LAST_SIGNAL] = {0};
-
-G_DEFINE_TYPE (NMSessionMonitor, nm_session_monitor, G_TYPE_OBJECT);
-
-/********************************************************************/
-
-static void
-nm_session_monitor_init (NMSessionMonitor *self)
-{
-}
-
-static void
-nm_session_monitor_class_init (NMSessionMonitorClass *klass)
-{
- /**
- * NMSessionMonitor::changed:
- * @monitor: A #NMSessionMonitor
- *
- * Emitted when something changes.
- */
- signals[CHANGED] = g_signal_new (NM_SESSION_MONITOR_CHANGED,
- NM_TYPE_SESSION_MONITOR,
- G_SIGNAL_RUN_LAST,
- 0, NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-NMSessionMonitor *
-nm_session_monitor_get (void)
-{
- static NMSessionMonitor *singleton = NULL;
-
- if (!singleton)
- singleton = g_object_new (NM_TYPE_SESSION_MONITOR, NULL);
- return singleton;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-/**
- * nm_session_monitor_user_has_session:
- * @monitor: A #NMSessionMonitor.
- * @username: A username.
- * @error: Return location for error.
- *
- * Checks whether the given @username is logged into a session or not.
- *
- * Returns: %FALSE if @error is set otherwise %TRUE if the given @username is
- * currently logged into a session.
- */
-gboolean
-nm_session_monitor_user_has_session (NMSessionMonitor *monitor,
- const char *username,
- uid_t *out_uid,
- GError **error)
-{
- return nm_session_user_to_uid (username, out_uid, error);
-}
-
-/**
- * nm_session_monitor_uid_has_session:
- * @monitor: A #NMSessionMonitor.
- * @uid: A user ID.
- * @error: Return location for error.
- *
- * Checks whether the given @uid is logged into a session or not.
- *
- * Returns: %FALSE if @error is set otherwise %TRUE if the given @uid is
- * currently logged into a session.
- */
-gboolean
-nm_session_monitor_uid_has_session (NMSessionMonitor *monitor,
- uid_t uid,
- const char **out_user,
- GError **error)
-{
- return nm_session_uid_to_user (uid, out_user, error);
-}
-
-/**
- * nm_session_monitor_user_active:
- * @monitor: A #NMSessionMonitor.
- * @username: A username.
- * @error: Return location for error.
- *
- * Checks whether the given @username is logged into a active session or not.
- *
- * Returns: %FALSE if @error is set otherwise %TRUE if the given @username is
- * logged into an active session.
- */
-gboolean
-nm_session_monitor_user_active (NMSessionMonitor *monitor,
- const char *username,
- GError **error)
-{
- return TRUE;
-}
-
-/**
- * nm_session_monitor_uid_active:
- * @monitor: A #NMSessionMonitor.
- * @uid: A user ID.
- * @error: Return location for error.
- *
- * Checks whether the given @uid is logged into a active session or not.
- *
- * Returns: %FALSE if @error is set otherwise %TRUE if the given @uid is
- * logged into an active session.
- */
-gboolean
-nm_session_monitor_uid_active (NMSessionMonitor *monitor,
- uid_t uid,
- GError **error)
-{
- return TRUE;
-}
-
diff --git a/src/nm-session-monitor-systemd.c b/src/nm-session-monitor-systemd.c
deleted file mode 100644
index f195c1e775..0000000000
--- a/src/nm-session-monitor-systemd.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- * Author: Matthias Clasen
- */
-
-#include "config.h"
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <string.h>
-#include <glib/gstdio.h>
-#include <systemd/sd-login.h>
-#include <stdlib.h>
-
-#include "nm-session-utils.h"
-#include "nm-session-monitor.h"
-#include "nm-logging.h"
-
-/********************************************************************/
-
-typedef struct {
- GSource source;
- GPollFD pollfd;
- sd_login_monitor *monitor;
-} SdSource;
-
-static gboolean
-sd_source_prepare (GSource *source, gint *timeout)
-{
- *timeout = -1;
- return FALSE;
-}
-
-static gboolean
-sd_source_check (GSource *source)
-{
- SdSource *sd_source = (SdSource *) source;
-
- return sd_source->pollfd.revents != 0;
-}
-
-static gboolean
-sd_source_dispatch (GSource *source,
- GSourceFunc callback,
- gpointer user_data)
-
-{
- SdSource *sd_source = (SdSource *)source;
- gboolean ret;
-
- g_warn_if_fail (callback != NULL);
- ret = (*callback) (user_data);
- sd_login_monitor_flush (sd_source->monitor);
- return ret;
-}
-
-static void
-sd_source_finalize (GSource *source)
-{
- SdSource *sd_source = (SdSource*) source;
-
- sd_login_monitor_unref (sd_source->monitor);
-}
-
-static GSourceFuncs sd_source_funcs = {
- sd_source_prepare,
- sd_source_check,
- sd_source_dispatch,
- sd_source_finalize
-};
-
-static GSource *
-sd_source_new (void)
-{
- GSource *source;
- SdSource *sd_source;
- int ret;
-
- source = g_source_new (&sd_source_funcs, sizeof (SdSource));
- sd_source = (SdSource *)source;
-
- ret = sd_login_monitor_new (NULL, &sd_source->monitor);
- if (ret < 0)
- g_printerr ("Error getting login monitor: %d", ret);
- else {
- sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor);
- sd_source->pollfd.events = G_IO_IN;
- g_source_add_poll (source, &sd_source->pollfd);
- }
-
- return source;
-}
-
-struct _NMSessionMonitor {
- GObject parent_instance;
-
- GSource *sd_source;
-};
-
-struct _NMSessionMonitorClass {
- GObjectClass parent_class;
-
- void (*changed) (NMSessionMonitor *monitor);
-};
-
-
-enum {
- CHANGED_SIGNAL,
- LAST_SIGNAL,
-};
-static guint signals[LAST_SIGNAL] = {0};
-
-G_DEFINE_TYPE (NMSessionMonitor, nm_session_monitor, G_TYPE_OBJECT);
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static gboolean
-sessions_changed (gpointer user_data)
-{
- NMSessionMonitor *monitor = NM_SESSION_MONITOR (user_data);
-
- g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
- return TRUE;
-}
-
-
-static void
-nm_session_monitor_init (NMSessionMonitor *monitor)
-{
- monitor->sd_source = sd_source_new ();
- g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL);
- g_source_attach (monitor->sd_source, NULL);
-}
-
-static void
-nm_session_monitor_finalize (GObject *object)
-{
- NMSessionMonitor *monitor = NM_SESSION_MONITOR (object);
-
- if (monitor->sd_source != NULL) {
- g_source_destroy (monitor->sd_source);
- g_source_unref (monitor->sd_source);
- }
-
- if (G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize != NULL)
- G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize (object);
-}
-
-static void
-nm_session_monitor_class_init (NMSessionMonitorClass *klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gobject_class->finalize = nm_session_monitor_finalize;
-
- /**
- * NMSessionMonitor::changed:
- * @monitor: A #NMSessionMonitor
- *
- * Emitted when something changes.
- */
- signals[CHANGED_SIGNAL] = g_signal_new ("changed",
- NM_TYPE_SESSION_MONITOR,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (NMSessionMonitorClass, changed),
- NULL, /* accumulator */
- NULL, /* accumulator data */
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-}
-
-NMSessionMonitor *
-nm_session_monitor_get (void)
-{
- static NMSessionMonitor *singleton = NULL;
-
- if (!singleton)
- singleton = g_object_new (NM_TYPE_SESSION_MONITOR, NULL);
- return singleton;
-}
-
-gboolean
-nm_session_monitor_user_has_session (NMSessionMonitor *monitor,
- const char *username,
- uid_t *out_uid,
- GError **error)
-{
- uid_t uid;
-
- if (!nm_session_user_to_uid (username, &uid, error))
- return FALSE;
-
- if (out_uid)
- *out_uid = uid;
-
- return nm_session_monitor_uid_has_session (monitor, uid, NULL, error);
-}
-
-gboolean
-nm_session_monitor_user_active (NMSessionMonitor *monitor,
- const char *username,
- GError **error)
-{
- uid_t uid;
-
- if (!nm_session_user_to_uid (username, &uid, error))
- return FALSE;
-
- return nm_session_monitor_uid_active (monitor, uid, error);
-}
-
-gboolean
-nm_session_monitor_uid_has_session (NMSessionMonitor *monitor,
- uid_t uid,
- const char **out_user,
- GError **error)
-{
- int num_sessions;
-
- if (!nm_session_uid_to_user (uid, out_user, error))
- return FALSE;
-
- /* Get all sessions (including inactive ones) for the user */
- num_sessions = sd_uid_get_sessions (uid, 0, NULL);
- if (num_sessions < 0) {
- nm_log_warn (LOGD_CORE, "Failed to get systemd sessions for uid %d: %d",
- uid, num_sessions);
- return FALSE;
- }
- return num_sessions > 0;
-}
-
-gboolean
-nm_session_monitor_uid_active (NMSessionMonitor *monitor,
- uid_t uid,
- GError **error)
-{
- int num_sessions;
-
- /* Get active sessions for the user */
- num_sessions = sd_uid_get_sessions (uid, 1, NULL);
- if (num_sessions < 0) {
- nm_log_warn (LOGD_CORE, "Failed to get active systemd sessions for uid %d: %d",
- uid, num_sessions);
- return FALSE;
- }
- return num_sessions > 0;
-}
diff --git a/src/nm-session-monitor-ck.c b/src/nm-session-monitor.c
index 75e1c92728..d836c7f978 100644
--- a/src/nm-session-monitor-ck.c
+++ b/src/nm-session-monitor.c
@@ -13,20 +13,31 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * (C) Copyright 2008 - 2010 Red Hat, Inc.
+ * (C) Copyright 2008 - 2014 Red Hat, Inc.
* Author: David Zeuthen <davidz@redhat.com>
* Author: Dan Williams <dcbw@redhat.com>
+ * Author: Matthias Clasen
+ * Author: Pavel Šimerda <psimerda@redhat.com>
*/
-
#include "config.h"
+
#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
#include <string.h>
#include <sys/stat.h>
+#include <glib/gstdio.h>
#include <gio/gio.h>
-#include "nm-logging.h"
+#include <stdlib.h>
+
+#ifdef SESSION_TRACKING_SYSTEMD
+#include <systemd/sd-login.h>
+#endif
-#include "nm-session-utils.h"
#include "nm-session-monitor.h"
+#include "nm-logging.h"
+
+/********************************************************************/
/* <internal>
* SECTION:nm-session-monitor
@@ -44,6 +55,8 @@ struct _NMSessionMonitor {
time_t database_mtime;
GHashTable *sessions_by_uid;
GHashTable *sessions_by_user;
+
+ GSource *sd_source;
};
struct _NMSessionMonitorClass {
@@ -52,17 +65,202 @@ struct _NMSessionMonitorClass {
void (*changed) (NMSessionMonitor *monitor);
};
+G_DEFINE_TYPE (NMSessionMonitor, nm_session_monitor, G_TYPE_OBJECT);
enum {
CHANGED,
LAST_SIGNAL,
};
+
static guint signals[LAST_SIGNAL] = {0};
-G_DEFINE_TYPE (NMSessionMonitor, nm_session_monitor, G_TYPE_OBJECT);
+#define NM_SESSION_MONITOR_ERROR (nm_session_monitor_error_quark ())
+GType nm_session_monitor_error_get_type (void) G_GNUC_CONST;
+
+typedef enum {
+ NM_SESSION_MONITOR_ERROR_IO_ERROR = 0, /*< nick=IOError >*/
+ NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE, /*< nick=MalformedDatabase >*/
+ NM_SESSION_MONITOR_ERROR_UNKNOWN_USER, /*< nick=UnknownUser >*/
+ NM_SESSION_MONITOR_ERROR_NO_DATABASE, /*< nick=NoDatabase >*/
+} NMSessionMonitorError;
+
+static GQuark
+nm_session_monitor_error_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (G_UNLIKELY (quark == 0))
+ quark = g_quark_from_static_string ("nm-session-monitor-error");
+
+ return quark;
+}
/********************************************************************/
+static gboolean
+nm_session_monitor_uid_to_user (uid_t uid, const char **out_user, GError **error)
+{
+ struct passwd *pw;
+
+ pw = getpwuid (uid);
+ if (!pw) {
+ g_set_error (error,
+ NM_SESSION_MONITOR_ERROR,
+ NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
+ "Could not get username for UID %d",
+ uid);
+ return FALSE;
+ }
+
+ if (out_user)
+ *out_user = pw->pw_name;
+ return TRUE;
+}
+
+static gboolean
+nm_session_monitor_user_to_uid (const char *user, uid_t *out_uid, GError **error)
+{
+ struct passwd *pw;
+
+ pw = getpwnam (user);
+ if (!pw) {
+ g_set_error (error,
+ NM_SESSION_MONITOR_ERROR,
+ NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
+ "Could not get UID for username '%s'",
+ user);
+ return FALSE;
+ }
+
+ if (out_uid)
+ *out_uid = pw->pw_uid;
+ return TRUE;
+}
+
+/********************************************************************/
+
+#ifdef SESSION_TRACKING_SYSTEMD
+typedef struct {
+ GSource source;
+ GPollFD pollfd;
+ sd_login_monitor *monitor;
+} SdSource;
+
+static gboolean
+sd_source_prepare (GSource *source, gint *timeout)
+{
+ *timeout = -1;
+ return FALSE;
+}
+
+static gboolean
+sd_source_check (GSource *source)
+{
+ SdSource *sd_source = (SdSource *) source;
+
+ return sd_source->pollfd.revents != 0;
+}
+
+static gboolean
+sd_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+
+{
+ SdSource *sd_source = (SdSource *)source;
+ gboolean ret;
+
+ g_warn_if_fail (callback != NULL);
+ ret = (*callback) (user_data);
+ sd_login_monitor_flush (sd_source->monitor);
+ return ret;
+}
+
+static void
+sd_source_finalize (GSource *source)
+{
+ SdSource *sd_source = (SdSource*) source;
+
+ sd_login_monitor_unref (sd_source->monitor);
+}
+
+static GSourceFuncs sd_source_funcs = {
+ sd_source_prepare,
+ sd_source_check,
+ sd_source_dispatch,
+ sd_source_finalize
+};
+
+static GSource *
+sd_source_new (void)
+{
+ GSource *source;
+ SdSource *sd_source;
+ int ret;
+
+ source = g_source_new (&sd_source_funcs, sizeof (SdSource));
+ sd_source = (SdSource *)source;
+
+ ret = sd_login_monitor_new (NULL, &sd_source->monitor);
+ if (ret < 0)
+ g_printerr ("Error getting login monitor: %d", ret);
+ else {
+ sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor);
+ sd_source->pollfd.events = G_IO_IN;
+ g_source_add_poll (source, &sd_source->pollfd);
+ }
+
+ return source;
+}
+
+static gboolean
+sessions_changed (gpointer user_data)
+{
+ NMSessionMonitor *monitor = NM_SESSION_MONITOR (user_data);
+
+ g_signal_emit (monitor, signals[CHANGED], 0);
+ return TRUE;
+}
+
+static gboolean
+nm_session_monitor_lookup_systemd (uid_t uid, gboolean active, GError **error)
+{
+ int status;
+
+ status = sd_uid_get_sessions (uid, active, NULL) > 0;
+ if (status < 0) {
+ nm_log_warn (LOGD_CORE, "Failed to get systemd sessions for uid %d: %d",
+ uid, status);
+ return FALSE;
+ }
+ return status > 0 ? TRUE : FALSE;
+}
+
+static void
+nm_session_monitor_init_systemd (NMSessionMonitor *monitor)
+{
+ if (access("/run/systemd/seats/", F_OK) < 0)
+ return;
+
+ monitor->sd_source = sd_source_new ();
+ g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL);
+ g_source_attach (monitor->sd_source, NULL);
+}
+
+static void
+nm_session_monitor_finalize_systemd (NMSessionMonitor *monitor)
+{
+ if (!monitor->sd_source)
+ return;
+
+ g_source_destroy (monitor->sd_source);
+ g_source_unref (monitor->sd_source);
+}
+#endif /* SESSION_TRACKING_SYSTEMD */
+
+/********************************************************************/
+
+#ifdef SESSION_TRACKING_CONSOLEKIT
typedef struct {
char *user;
uid_t uid;
@@ -71,11 +269,11 @@ typedef struct {
} Session;
static void
-session_free (Session *s)
+session_free (Session *session)
{
- g_free (s->user);
- memset (s, 0, sizeof (Session));
- g_free (s);
+ g_free (session->user);
+ memset (session, 0, sizeof (Session));
+ g_free (session);
}
static gboolean
@@ -86,10 +284,10 @@ check_key (GKeyFile *keyfile, const char *group, const char *key, GError **error
if (!error) {
g_set_error (error,
- NM_SESSION_MONITOR_ERROR,
- NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE,
- "ConsoleKit database " CKDB_PATH " group '%s' had no '%s' key",
- group, key);
+ NM_SESSION_MONITOR_ERROR,
+ NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE,
+ "ConsoleKit database " CKDB_PATH " group '%s' had no '%s' key",
+ group, key);
}
return FALSE;
}
@@ -98,39 +296,39 @@ static Session *
session_new (GKeyFile *keyfile, const char *group, GError **error)
{
GError *local = NULL;
- Session *s;
+ Session *session;
const char *uname = NULL;
- s = g_new0 (Session, 1);
- g_assert (s);
+ session = g_new0 (Session, 1);
+ g_assert (session);
- s->uid = G_MAXUINT; /* paranoia */
+ session->uid = G_MAXUINT; /* paranoia */
if (!check_key (keyfile, group, "uid", &local))
goto error;
- s->uid = (uid_t) g_key_file_get_integer (keyfile, group, "uid", &local);
+ session->uid = (uid_t) g_key_file_get_integer (keyfile, group, "uid", &local);
if (local)
goto error;
if (!check_key (keyfile, group, "is_active", &local))
goto error;
- s->active = g_key_file_get_boolean (keyfile, group, "is_active", &local);
+ session->active = g_key_file_get_boolean (keyfile, group, "is_active", &local);
if (local)
goto error;
if (!check_key (keyfile, group, "is_local", &local))
goto error;
- s->local = g_key_file_get_boolean (keyfile, group, "is_local", &local);
+ session->local = g_key_file_get_boolean (keyfile, group, "is_local", &local);
if (local)
goto error;
- if (!nm_session_uid_to_user (s->uid, &uname, error))
+ if (!nm_session_monitor_uid_to_user (session->uid, &uname, error))
return FALSE;
- s->user = g_strdup (uname);
+ session->user = g_strdup (uname);
- return s;
+ return session;
error:
- session_free (s);
+ session_free (session);
g_propagate_error (error, local);
return NULL;
}
@@ -148,8 +346,6 @@ session_merge (Session *src, Session *dest)
dest->active = (dest->active || src->active);
}
-/********************************************************************/
-
static void
free_database (NMSessionMonitor *self)
{
@@ -168,7 +364,7 @@ reload_database (NMSessionMonitor *self, GError **error)
struct stat statbuf;
char **groups = NULL;
gsize len = 0, i;
- Session *s;
+ Session *session;
free_database (self);
@@ -202,18 +398,18 @@ reload_database (NMSessionMonitor *self, GError **error)
if (!g_str_has_prefix (groups[i], "Session "))
continue;
- s = session_new (self->database, groups[i], error);
- if (!s)
+ session = session_new (self->database, groups[i], error);
+ if (!session)
goto error;
- found = g_hash_table_lookup (self->sessions_by_user, (gpointer) s->user);
+ found = g_hash_table_lookup (self->sessions_by_user, (gpointer) session->user);
if (found) {
- session_merge (s, found);
- session_free (s);
+ session_merge (session, found);
+ session_free (session);
} else {
/* Entirely new user */
- g_hash_table_insert (self->sessions_by_user, (gpointer) s->user, s);
- g_hash_table_insert (self->sessions_by_uid, GUINT_TO_POINTER (s->uid), s);
+ g_hash_table_insert (self->sessions_by_user, (gpointer) session->user, session);
+ g_hash_table_insert (self->sessions_by_uid, GUINT_TO_POINTER (session->uid), session);
}
}
@@ -272,95 +468,94 @@ on_file_monitor_changed (GFileMonitor * file_monitor,
g_signal_emit (self, signals[CHANGED], 0);
}
+static gboolean
+nm_session_monitor_lookup_consolekit (NMSessionMonitor *monitor, uid_t uid, gboolean active, GError **error)
+{
+ Session *session;
+
+ if (!ensure_database (monitor, error))
+ return FALSE;
+
+ session = g_hash_table_lookup (monitor->sessions_by_uid, GUINT_TO_POINTER (uid));
+ if (!session) {
+ g_set_error (error,
+ NM_SESSION_MONITOR_ERROR,
+ NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
+ "No session found for uid %d",
+ uid);
+ return FALSE;
+ }
+
+ if (active && !session->active)
+ return FALSE;
+
+ return TRUE;
+}
+
static void
-nm_session_monitor_init (NMSessionMonitor *self)
+nm_session_monitor_init_consolekit (NMSessionMonitor *monitor)
{
GError *error = NULL;
GFile *file;
/* Sessions-by-user is responsible for destroying the Session objects */
- self->sessions_by_user = g_hash_table_new_full (g_str_hash, g_str_equal,
- NULL, (GDestroyNotify) session_free);
- self->sessions_by_uid = g_hash_table_new (g_direct_hash, g_direct_equal);
-
+ monitor->sessions_by_user = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL, (GDestroyNotify) session_free);
+ monitor->sessions_by_uid = g_hash_table_new (g_direct_hash, g_direct_equal);
- error = NULL;
- if (!ensure_database (self, &error)) {
+ if (!ensure_database (monitor, &error)) {
/* Ignore the first error if the CK database isn't found yet */
if (g_error_matches (error,
NM_SESSION_MONITOR_ERROR,
NM_SESSION_MONITOR_ERROR_NO_DATABASE) == FALSE) {
nm_log_err (LOGD_CORE, "Error loading " CKDB_PATH ": %s", error->message);
}
- g_error_free (error);
+ g_clear_error (&error);
}
- error = NULL;
file = g_file_new_for_path (CKDB_PATH);
- self->database_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
+ monitor->database_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
g_object_unref (file);
- if (self->database_monitor == NULL) {
+ if (monitor->database_monitor == NULL) {
nm_log_err (LOGD_CORE, "Error monitoring " CKDB_PATH ": %s", error->message);
- g_error_free (error);
+ g_clear_error (&error);
} else {
- g_signal_connect (self->database_monitor,
+ g_signal_connect (monitor->database_monitor,
"changed",
G_CALLBACK (on_file_monitor_changed),
- self);
+ monitor);
}
}
static void
-finalize (GObject *object)
+nm_session_monitor_finalize_consolekit (NMSessionMonitor *monitor)
{
- NMSessionMonitor *self = NM_SESSION_MONITOR (object);
-
- if (self->database_monitor != NULL)
- g_object_unref (self->database_monitor);
-
- free_database (self);
-
- if (G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize != NULL)
- G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize (object);
+ g_object_unref (monitor->database_monitor);
+ free_database (monitor);
}
+#endif /* SESSION_TRACKING_CONSOLEKIT */
-static void
-nm_session_monitor_class_init (NMSessionMonitorClass *klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
+/********************************************************************/
- gobject_class->finalize = finalize;
+static gboolean
+nm_session_monitor_lookup (NMSessionMonitor *monitor, uid_t uid, gboolean active, GError **error)
+{
+#ifdef SESSION_TRACKING_SYSTEMD
+ if (monitor->sd_source)
+ return nm_session_monitor_lookup_systemd (uid, active, error);
+#endif
- /**
- * NMSessionMonitor::changed:
- * @monitor: A #NMSessionMonitor
- *
- * Emitted when something changes.
- */
- signals[CHANGED] = g_signal_new (NM_SESSION_MONITOR_CHANGED,
- NM_TYPE_SESSION_MONITOR,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (NMSessionMonitorClass, changed),
- NULL, /* accumulator */
- NULL, /* accumulator data */
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
+#ifdef SESSION_TRACKING_CONSOLEKIT
+ return nm_session_monitor_lookup_consolekit (monitor, uid, active, error);
+#endif
-NMSessionMonitor *
-nm_session_monitor_get (void)
-{
- static NMSessionMonitor *singleton = NULL;
+#ifdef SESSION_TRACKING_FAKE
+ return TRUE;
+#endif
- if (!singleton)
- singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL));
- return singleton;
+ return FALSE;
}
-/* ---------------------------------------------------------------------------------------------------- */
-
/**
* nm_session_monitor_user_has_session:
* @monitor: A #NMSessionMonitor.
@@ -378,24 +573,15 @@ nm_session_monitor_user_has_session (NMSessionMonitor *monitor,
uid_t *out_uid,
GError **error)
{
- Session *s;
-
- if (!ensure_database (monitor, error))
- return FALSE;
+ uid_t uid;
- s = g_hash_table_lookup (monitor->sessions_by_user, (gpointer) username);
- if (!s) {
- g_set_error (error,
- NM_SESSION_MONITOR_ERROR,
- NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
- "No session found for user '%s'",
- username);
+ if (!nm_session_monitor_user_to_uid (username, &uid, error))
return FALSE;
- }
if (out_uid)
- *out_uid = s->uid;
- return TRUE;
+ *out_uid = uid;
+
+ return nm_session_monitor_lookup (monitor, uid, FALSE, error);
}
/**
@@ -415,24 +601,10 @@ nm_session_monitor_uid_has_session (NMSessionMonitor *monitor,
const char **out_user,
GError **error)
{
- Session *s;
-
- if (!ensure_database (monitor, error))
+ if (out_user && !nm_session_monitor_uid_to_user (uid, out_user, error))
return FALSE;
- s = g_hash_table_lookup (monitor->sessions_by_uid, GUINT_TO_POINTER (uid));
- if (!s) {
- g_set_error (error,
- NM_SESSION_MONITOR_ERROR,
- NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
- "No session found for uid %d",
- uid);
- return FALSE;
- }
-
- if (out_user)
- *out_user = s->user;
- return TRUE;
+ return nm_session_monitor_lookup (monitor, uid, FALSE, error);
}
/**
@@ -451,22 +623,12 @@ nm_session_monitor_user_active (NMSessionMonitor *monitor,
const char *username,
GError **error)
{
- Session *s;
-
- if (!ensure_database (monitor, error))
- return FALSE;
+ uid_t uid;
- s = g_hash_table_lookup (monitor->sessions_by_user, (gpointer) username);
- if (!s) {
- g_set_error (error,
- NM_SESSION_MONITOR_ERROR,
- NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
- "No session found for user '%s'",
- username);
+ if (!nm_session_monitor_user_to_uid (username, &uid, error))
return FALSE;
- }
- return s->active;
+ return nm_session_monitor_lookup (monitor, uid, TRUE, error);
}
/**
@@ -485,21 +647,70 @@ nm_session_monitor_uid_active (NMSessionMonitor *monitor,
uid_t uid,
GError **error)
{
- Session *s;
+ return nm_session_monitor_lookup (monitor, uid, TRUE, error);
+}
- if (!ensure_database (monitor, error))
- return FALSE;
+/********************************************************************/
- s = g_hash_table_lookup (monitor->sessions_by_uid, GUINT_TO_POINTER (uid));
- if (!s) {
- g_set_error (error,
- NM_SESSION_MONITOR_ERROR,
- NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
- "No session found for uid '%d'",
- uid);
- return FALSE;
- }
+NMSessionMonitor *
+nm_session_monitor_get (void)
+{
+ static NMSessionMonitor *singleton = NULL;
+
+ if (!singleton)
+ singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL));
+ g_assert (singleton);
+
+ return singleton;
+}
+
+static void
+nm_session_monitor_init (NMSessionMonitor *monitor)
+{
+#ifdef SESSION_TRACKING_SYSTEMD
+ nm_session_monitor_init_systemd (monitor);
+#endif
- return s->active;
+#ifdef SESSION_TRACKING_CONSOLEKIT
+ nm_session_monitor_init_consolekit (monitor);
+#endif
+}
+
+static void
+nm_session_monitor_finalize (GObject *object)
+{
+#ifdef SESSION_TRACKING_SYSTEMD
+ nm_session_monitor_finalize_systemd (NM_SESSION_MONITOR (object));
+#endif
+
+#ifdef SESSION_TRACKING_CONSOLEKIT
+ nm_session_monitor_finalize_consolekit (NM_SESSION_MONITOR (object));
+#endif
+
+ if (G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize (object);
}
+static void
+nm_session_monitor_class_init (NMSessionMonitorClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = nm_session_monitor_finalize;
+
+ /**
+ * NMSessionMonitor::changed:
+ * @monitor: A #NMSessionMonitor
+ *
+ * Emitted when something changes.
+ */
+ signals[CHANGED] = g_signal_new (NM_SESSION_MONITOR_CHANGED,
+ NM_TYPE_SESSION_MONITOR,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (NMSessionMonitorClass, changed),
+ NULL, /* accumulator */
+ NULL, /* accumulator data */
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
diff --git a/src/nm-session-monitor.h b/src/nm-session-monitor.h
index 77ea9a0364..1643bc58e4 100644
--- a/src/nm-session-monitor.h
+++ b/src/nm-session-monitor.h
@@ -21,6 +21,7 @@
#ifndef NM_SESSION_MONITOR_H
#define NM_SESSION_MONITOR_H
+#include <unistd.h>
#include <glib-object.h>
G_BEGIN_DECLS
diff --git a/src/nm-session-utils.c b/src/nm-session-utils.c
deleted file mode 100644
index 269e2f81cf..0000000000
--- a/src/nm-session-utils.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* 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.
- *
- * Copyright (C) 2012 Red Hat, Inc.
- * Author: Dan Williams <dcbw@redhat.com>
- */
-
-#include <pwd.h>
-#include <sys/types.h>
-
-#include "nm-session-utils.h"
-
-/********************************************************************/
-
-GQuark
-nm_session_monitor_error_quark (void)
-{
- static GQuark ret = 0;
-
- if (G_UNLIKELY (ret == 0))
- ret = g_quark_from_static_string ("nm-session-monitor-error");
- return ret;
-}
-
-/********************************************************************/
-
-gboolean
-nm_session_uid_to_user (uid_t uid, const char **out_user, GError **error)
-{
- struct passwd *pw;
-
- pw = getpwuid (uid);
- if (!pw) {
- g_set_error (error,
- NM_SESSION_MONITOR_ERROR,
- NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
- "Could not get username for UID %d",
- uid);
- return FALSE;
- }
-
- if (out_user)
- *out_user = pw->pw_name;
- return TRUE;
-}
-
-gboolean
-nm_session_user_to_uid (const char *user, uid_t *out_uid, GError **error)
-{
- struct passwd *pw;
-
- pw = getpwnam (user);
- if (!pw) {
- g_set_error (error,
- NM_SESSION_MONITOR_ERROR,
- NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
- "Could not get UID for username '%s'",
- user);
- return FALSE;
- }
-
- /* Ugly, but hey, use ConsoleKit */
- if (out_uid)
- *out_uid = pw->pw_uid;
- return TRUE;
-}
-
diff --git a/src/nm-session-utils.h b/src/nm-session-utils.h
deleted file mode 100644
index 54b6d4c43a..0000000000
--- a/src/nm-session-utils.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* 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.
- *
- * Copyright (C) 2012 Red Hat, Inc.
- * Author: Dan Williams <dcbw@redhat.com>
- */
-
-#ifndef NM_SESSION_UTILS_H
-#define NM_SESSION_UTILS_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#define NM_SESSION_MONITOR_ERROR (nm_session_monitor_error_quark ())
-GQuark nm_session_monitor_error_quark (void) G_GNUC_CONST;
-GType nm_session_monitor_error_get_type (void) G_GNUC_CONST;
-
-typedef enum {
- NM_SESSION_MONITOR_ERROR_IO_ERROR = 0, /*< nick=IOError >*/
- NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE, /*< nick=MalformedDatabase >*/
- NM_SESSION_MONITOR_ERROR_UNKNOWN_USER, /*< nick=UnknownUser >*/
- NM_SESSION_MONITOR_ERROR_NO_DATABASE, /*< nick=NoDatabase >*/
-} NMSessionMonitorError;
-
-gboolean nm_session_uid_to_user (uid_t uid, const char **out_user, GError **error);
-
-gboolean nm_session_user_to_uid (const char *user, uid_t *out_uid, GError **error);
-
-#endif /* NM_SESSION_UTILS_H */