[PATCH 2/2] core: runtime detect logind and ConsoleKit
- From: Fabio Erculiani <lxnay sabayon org>
- To: NetworkManager-list gnome org
- Subject: [PATCH 2/2] core: runtime detect logind and ConsoleKit
- Date: Tue, 16 Apr 2013 07:05:56 +0100
If --with-session-tracking=systemd, but logind is not currently running, the code
now falls back to ConsoleKit. This is particularly useful for covering
the interim, while waiting for distros to abandon ConsoleKit completely.
---
configure.ac | 1 +
src/Makefile.am | 10 +-
src/nm-session-monitor-systemd.c | 268 ----------------
src/nm-session-monitor.c | 641 +++++++++++++++++++++++++++++++++++++++
src/nm-session-monitor.h | 6 +
5 files changed, 651 insertions(+), 275 deletions(-)
delete mode 100644 src/nm-session-monitor-systemd.c
create mode 100644 src/nm-session-monitor.c
diff --git a/configure.ac b/configure.ac
index a1f49c0..810c464 100644
--- a/configure.ac
+++ b/configure.ac
@@ -296,6 +296,7 @@ AS_IF([! (echo "$with_session_tracking" | grep -q -E "^(systemd|consolekit|no)$"
# add conditionals and subtitutions
AM_CONDITIONAL(SESSION_TRACKING_CK, test "$with_session_tracking" = "consolekit")
AM_CONDITIONAL(SESSION_TRACKING_SYSTEMD, test "$with_session_tracking" = "systemd")
+AM_CONDITIONAL(SESSION_TRACKING_NULL, test "$with_session_tracking" = "no")
if test "$with_session_tracking" = "systemd"; then
PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd-login])
AC_SUBST(SYSTEMD_LOGIN_CFLAGS)
diff --git a/src/Makefile.am b/src/Makefile.am
index 113b527..20246ff 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -205,14 +205,10 @@ if WITH_CONCHECK
NetworkManager_SOURCES += nm-connectivity.c nm-connectivity.h
endif
-if SESSION_TRACKING_SYSTEMD
-NetworkManager_SOURCES += nm-session-monitor-systemd.c
-else
-if SESSION_TRACKING_CK
-NetworkManager_SOURCES += nm-session-monitor-ck.c
-else
+if SESSION_TRACKING_NULL
NetworkManager_SOURCES += nm-session-monitor-null.c
-endif
+else
+NetworkManager_SOURCES += nm-session-monitor.c
endif
if SUSPEND_RESUME_SYSTEMD
diff --git a/src/nm-session-monitor-systemd.c b/src/nm-session-monitor-systemd.c
deleted file mode 100644
index f9fb075..0000000
--- a/src/nm-session-monitor-systemd.c
+++ /dev/null
@@ -1,268 +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)
- return g_object_ref (singleton);
-
- singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL));
- g_assert (singleton);
- 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 ret;
-
- if (!nm_session_uid_to_user (uid, out_user, error))
- return FALSE;
-
- ret = sd_uid_get_sessions (uid, FALSE, NULL) > 0;
- if (ret < 0) {
- nm_log_warn (LOGD_CORE, "Failed to get systemd sessions for uid %d: %d",
- uid, ret);
- return FALSE;
- }
- return ret > 0 ? TRUE : FALSE;
-}
-
-gboolean
-nm_session_monitor_uid_active (NMSessionMonitor *monitor,
- uid_t uid,
- GError **error)
-{
- int ret;
-
- ret = sd_uid_get_sessions (uid, TRUE, NULL) > 0;
- if (ret < 0) {
- nm_log_warn (LOGD_CORE, "Failed to get active systemd sessions for uid %d: %d",
- uid, ret);
- return FALSE;
- }
- return ret > 0 ? TRUE : FALSE;
-}
diff --git a/src/nm-session-monitor.c b/src/nm-session-monitor.c
new file mode 100644
index 0000000..26e66ce
--- /dev/null
+++ b/src/nm-session-monitor.c
@@ -0,0 +1,641 @@
+/* -*- 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 <sys/stat.h>
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+#ifdef SESSION_TRACKING_SYSTEMD
+#include <systemd/sd-login.h>
+#endif
+#include <stdlib.h>
+
+#include "nm-session-utils.h"
+#include "nm-session-monitor.h"
+#include "nm-logging.h"
+
+#define CKDB_PATH "/var/run/ConsoleKit/database"
+
+/********************************************************************/
+
+#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;
+}
+#endif /* SESSION_TRACKING_SYSTEMD */
+
+struct _NMSessionMonitor {
+ GObject parent_instance;
+
+ GKeyFile *database;
+ GFileMonitor *database_monitor;
+ time_t database_mtime;
+ GHashTable *sessions_by_uid;
+ GHashTable *sessions_by_user;
+
+ 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);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct {
+ char *user;
+ uid_t uid;
+ gboolean local;
+ gboolean active;
+} Session;
+
+static void
+session_free (Session *s)
+{
+ g_free (s->user);
+ memset (s, 0, sizeof (Session));
+ g_free (s);
+}
+
+static gboolean
+check_key (GKeyFile *keyfile, const char *group, const char *key, GError **error)
+{
+ if (g_key_file_has_key (keyfile, group, key, error))
+ return TRUE;
+
+ 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);
+ }
+ return FALSE;
+}
+
+static Session *
+session_new (GKeyFile *keyfile, const char *group, GError **error)
+{
+ GError *local = NULL;
+ Session *s;
+ const char *uname = NULL;
+
+ s = g_new0 (Session, 1);
+ g_assert (s);
+
+ s->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);
+ 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);
+ 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);
+ if (local)
+ goto error;
+
+ if (!nm_session_uid_to_user (s->uid, &uname, error))
+ return FALSE;
+ s->user = g_strdup (uname);
+
+ return s;
+
+error:
+ session_free (s);
+ g_propagate_error (error, local);
+ return NULL;
+}
+
+static void
+session_merge (Session *src, Session *dest)
+{
+ g_return_if_fail (src != NULL);
+ g_return_if_fail (dest != NULL);
+
+ g_warn_if_fail (g_strcmp0 (src->user, dest->user) == 0);
+ g_warn_if_fail (src->uid == dest->uid);
+
+ dest->local = (dest->local || src->local);
+ dest->active = (dest->active || src->active);
+}
+
+static void
+free_database (NMSessionMonitor *self)
+{
+ if (self->database != NULL) {
+ g_key_file_free (self->database);
+ self->database = NULL;
+ }
+
+ g_hash_table_remove_all (self->sessions_by_uid);
+ g_hash_table_remove_all (self->sessions_by_user);
+}
+
+static gboolean
+reload_database (NMSessionMonitor *self, GError **error)
+{
+ struct stat statbuf;
+ char **groups = NULL;
+ gsize len = 0, i;
+ Session *s;
+
+ free_database (self);
+
+ errno = 0;
+ if (stat (CKDB_PATH, &statbuf) != 0) {
+ g_set_error (error,
+ NM_SESSION_MONITOR_ERROR,
+ errno == ENOENT ? NM_SESSION_MONITOR_ERROR_NO_DATABASE :
NM_SESSION_MONITOR_ERROR_IO_ERROR,
+ "Error statting file " CKDB_PATH ": %s",
+ strerror (errno));
+ goto error;
+ }
+ self->database_mtime = statbuf.st_mtime;
+
+ self->database = g_key_file_new ();
+ if (!g_key_file_load_from_file (self->database, CKDB_PATH, G_KEY_FILE_NONE, error))
+ goto error;
+
+ groups = g_key_file_get_groups (self->database, &len);
+ if (!groups) {
+ g_set_error_literal (error,
+ NM_SESSION_MONITOR_ERROR,
+ NM_SESSION_MONITOR_ERROR_IO_ERROR,
+ "Could not load groups from " CKDB_PATH "");
+ goto error;
+ }
+
+ for (i = 0; i < len; i++) {
+ Session *found;
+
+ if (!g_str_has_prefix (groups[i], "Session "))
+ continue;
+
+ s = session_new (self->database, groups[i], error);
+ if (!s)
+ goto error;
+
+ found = g_hash_table_lookup (self->sessions_by_user, (gpointer) s->user);
+ if (found) {
+ session_merge (s, found);
+ session_free (s);
+ } 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_strfreev (groups);
+ return TRUE;
+
+error:
+ if (groups)
+ g_strfreev (groups);
+ free_database (self);
+ return FALSE;
+}
+
+static gboolean
+ensure_database (NMSessionMonitor *self, GError **error)
+{
+ gboolean ret = FALSE;
+
+ if (self->database != NULL) {
+ struct stat statbuf;
+
+ errno = 0;
+ if (stat (CKDB_PATH, &statbuf) != 0) {
+ g_set_error (error,
+ NM_SESSION_MONITOR_ERROR,
+ errno == ENOENT ? NM_SESSION_MONITOR_ERROR_NO_DATABASE :
NM_SESSION_MONITOR_ERROR_IO_ERROR,
+ "Error statting file " CKDB_PATH " to check timestamp: %s",
+ strerror (errno));
+ goto out;
+ }
+
+ if (statbuf.st_mtime == self->database_mtime) {
+ ret = TRUE;
+ goto out;
+ }
+ }
+
+ ret = reload_database (self, error);
+
+out:
+ return ret;
+}
+
+static void
+on_file_monitor_changed (GFileMonitor * file_monitor,
+ GFile * file,
+ GFile * other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ NMSessionMonitor *self = NM_SESSION_MONITOR (user_data);
+
+ /* throw away cache */
+ free_database (self);
+
+ g_signal_emit (self, signals[CHANGED_SIGNAL], 0);
+}
+
+#ifdef SESSION_TRACKING_SYSTEMD
+static gboolean
+sessions_changed (gpointer user_data)
+{
+ NMSessionMonitor *monitor = NM_SESSION_MONITOR (user_data);
+
+ g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
+ return TRUE;
+}
+#endif /* SESSION_TRACKING_SYSTEMD */
+
+
+static void
+nm_session_monitor_init (NMSessionMonitor *monitor)
+{
+ GError *error;
+ GFile *file;
+
+ monitor->sd_source = NULL;
+ monitor->database = NULL;
+ monitor->database_monitor = NULL;
+ monitor->sessions_by_uid = NULL;
+ monitor->sessions_by_user = NULL;
+
+#ifdef SESSION_TRACKING_SYSTEMD
+ if (LOGIND_RUNNING())
+ {
+ monitor->sd_source = sd_source_new ();
+ g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL);
+ g_source_attach (monitor->sd_source, NULL);
+ return;
+ }
+ /* fall through */
+#endif /* SESSION_TRACKING_SYSTEMD */
+
+ error = NULL;
+
+ /* Sessions-by-user is responsible for destroying the Session objects */
+ 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 (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);
+ }
+
+ error = NULL;
+ file = g_file_new_for_path (CKDB_PATH);
+ monitor->database_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
+ g_object_unref (file);
+ if (monitor->database_monitor == NULL) {
+ nm_log_err (LOGD_CORE, "Error monitoring " CKDB_PATH ": %s", error->message);
+ g_error_free (error);
+ } else {
+ g_signal_connect (monitor->database_monitor,
+ "changed",
+ G_CALLBACK (on_file_monitor_changed),
+ monitor);
+ }
+}
+
+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 (monitor->database_monitor != NULL)
+ g_object_unref (monitor->database_monitor);
+
+ free_database (monitor);
+
+ 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 (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);
+}
+
+NMSessionMonitor *
+nm_session_monitor_get (void)
+{
+ static NMSessionMonitor *singleton = NULL;
+
+ if (singleton)
+ return g_object_ref (singleton);
+
+ singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL));
+ g_assert (singleton);
+ return singleton;
+}
+
+gboolean
+nm_session_monitor_user_has_session (NMSessionMonitor *monitor,
+ const char *username,
+ uid_t *out_uid,
+ GError **error)
+{
+#ifdef SESSION_TRACKING_SYSTEMD
+ if (LOGIND_RUNNING())
+ {
+ 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);
+ }
+ /* fall through */
+#endif /* SESSION_TRACKING_SYSTEMD */
+
+ Session *s;
+
+ if (!ensure_database (monitor, error))
+ return FALSE;
+
+ 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);
+ return FALSE;
+ }
+
+ if (out_uid)
+ *out_uid = s->uid;
+ return TRUE;
+}
+
+gboolean
+nm_session_monitor_user_active (NMSessionMonitor *monitor,
+ const char *username,
+ GError **error)
+{
+#ifdef SESSION_TRACKING_SYSTEMD
+ if (LOGIND_RUNNING())
+ {
+ uid_t uid;
+
+ if (!nm_session_user_to_uid (username, &uid, error))
+ return FALSE;
+
+ return nm_session_monitor_uid_active (monitor, uid, error);
+ }
+ /* fall through */
+#endif
+
+ Session *s;
+
+ if (!ensure_database (monitor, error))
+ return FALSE;
+
+ 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);
+ return FALSE;
+ }
+
+ return s->active;
+}
+
+gboolean
+nm_session_monitor_uid_has_session (NMSessionMonitor *monitor,
+ uid_t uid,
+ const char **out_user,
+ GError **error)
+{
+#ifdef SESSION_TRACKING_SYSTEMD
+ if (LOGIND_RUNNING())
+ {
+ int ret;
+
+ if (!nm_session_uid_to_user (uid, out_user, error))
+ return FALSE;
+
+ ret = sd_uid_get_sessions (uid, FALSE, NULL) > 0;
+ if (ret < 0) {
+ nm_log_warn (LOGD_CORE, "Failed to get systemd sessions for uid %d: %d",
+ uid, ret);
+ return FALSE;
+ }
+ return ret > 0 ? TRUE : FALSE;
+ }
+ /* fall through */
+#endif
+
+ Session *s;
+
+ 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;
+ }
+
+ if (out_user)
+ *out_user = s->user;
+ return TRUE;
+}
+
+gboolean
+nm_session_monitor_uid_active (NMSessionMonitor *monitor,
+ uid_t uid,
+ GError **error)
+{
+#ifdef SESSION_TRACKING_SYSTEMD
+ if (LOGIND_RUNNING())
+ {
+ int ret;
+
+ ret = sd_uid_get_sessions (uid, TRUE, NULL) > 0;
+ if (ret < 0) {
+ nm_log_warn (LOGD_CORE, "Failed to get active systemd sessions for uid %d: %d",
+ uid, ret);
+ return FALSE;
+ }
+ return ret > 0 ? TRUE : FALSE;
+ }
+ /* fall through */
+#endif
+
+ Session *s;
+
+ 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;
+ }
+
+ return s->active;
+}
diff --git a/src/nm-session-monitor.h b/src/nm-session-monitor.h
index 77ea9a0..ac3dec5 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
@@ -34,6 +35,11 @@ G_BEGIN_DECLS
#define NM_SESSION_MONITOR_CHANGED "changed"
+/* check if logind is running
+ * thanks to: https://bugzilla.gnome.org/show_bug.cgi?id=696266
+ */
+#define LOGIND_RUNNING() (access("/run/systemd/seats/", F_OK) >= 0)
+
typedef struct _NMSessionMonitor NMSessionMonitor;
typedef struct _NMSessionMonitorClass NMSessionMonitorClass;
--
1.8.1.5
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]