summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Šimerda <psimerda@redhat.com>2013-07-30 23:09:52 +0200
committerPavel Šimerda <psimerda@redhat.com>2015-01-05 18:39:46 +0100
commit0de60b300ed6cc0fc94c742396112b1274989371 (patch)
treedf7d7f4c06ccb698f481246ff6389c5f01bc6b8b
parenteb2eda4408667395ffb73ec94fc5a02f311b66f5 (diff)
downloadNetworkManager-0de60b300ed6cc0fc94c742396112b1274989371.tar.gz
session: merge nm-session-monitor-* modules
Merged all session tracking modules into one source file and simplified it substantially. Now systemd-logind and ConsoleKit support can be built in at the same time and both are detected at runtime. This is useful on source based as well as binary distributions. Original patch written by Fabio Erculiani <lxnay@sabayon.org>, modified by Pavel Šimerda <psimerda@redhat.com> and Thomas Haller <thaller@redhat.com>. https://bugzilla.gnome.org/show_bug.cgi?id=686997 Acked-By: Thomas Haller <thaller@redhat.com>
-rw-r--r--configure.ac48
-rw-r--r--src/Makefile.am13
-rw-r--r--src/nm-session-monitor-ck.c508
-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.c338
-rw-r--r--src/nm-session-monitor.h20
7 files changed, 362 insertions, 1000 deletions
diff --git a/configure.ac b/configure.ac
index 6739b23316..8d66ecdb44 100644
--- a/configure.ac
+++ b/configure.ac
@@ -332,30 +332,38 @@ 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])
+# 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(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
- PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd],,
- [PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd-login])])
+ [Compatibility option to choose one session tracking module]))
+# defaults
+AS_IF([test -z "$with_systemd_logind"], [with_systemd_logind="yes"])
+AS_IF([test -z "$with_consolekit"], [with_consolekit="yes"])
+# backwards compatibility
+AS_IF([test "$with_session_tracking" = "ck"], [with_consolekit="yes" with_systemd_logind="no"])
+AS_IF([test "$with_session_tracking" = "consolekit"], [with_consolekit="yes" with_systemd_logind="no"])
+AS_IF([test "$with_session_tracking" = "systemd"], [with_consolekit="no" with_systemd_logind="yes"])
+AS_IF([test "$with_session_tracking" = "no"], [with_consolekit="no" with_systemd_logind="no"])
+AS_IF([test "$with_session_tracking" = "none"], [with_consolekit="no" with_systemd_logind="no"])
+unset with_session_tracking
+# 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)
+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
@@ -1029,7 +1037,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 387d1caa70..e9cedd9d67 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -333,15 +333,6 @@ nm_sources = \
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
@@ -432,10 +423,6 @@ AM_CPPFLAGS += \
\
$(NULL)
-if SESSION_TRACKING_CK
-AM_CPPFLAGS += -DCKDB_PATH=\"${CKDB_PATH}\"
-endif
-
libNetworkManager_la_SOURCES = \
$(nm_sources) \
$(glue_sources)
diff --git a/src/nm-session-monitor-ck.c b/src/nm-session-monitor-ck.c
deleted file mode 100644
index 4d4c360e8c..0000000000
--- a/src/nm-session-monitor-ck.c
+++ /dev/null
@@ -1,508 +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 <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <gio/gio.h>
-#include "nm-logging.h"
-
-#include "nm-session-monitor.h"
-#include "nm-errors.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;
-
- GKeyFile *database;
- GFileMonitor *database_monitor;
- time_t database_mtime;
- GHashTable *sessions_by_uid;
- GHashTable *sessions_by_user;
-};
-
-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);
-
-/********************************************************************/
-
-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_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "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_monitor_uid_to_user (s->uid, &uname)) {
- g_set_error (error,
- NM_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "Could not get username for UID %d",
- s->uid);
- goto error;
- }
- 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_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "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_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "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_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "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], 0);
-}
-
-static void
-nm_session_monitor_init (NMSessionMonitor *self)
-{
- 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);
-
-
- if (!ensure_database (self, &error)) {
- nm_log_dbg (LOGD_CORE, "Error loading " CKDB_PATH ": %s", error->message);
-
- /* Ignore the first error, the CK database might not exist yet */
- g_error_free (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);
- g_object_unref (file);
- if (self->database_monitor == NULL) {
- nm_log_err (LOGD_CORE, "Error monitoring " CKDB_PATH ": %s", error->message);
- g_error_free (error);
- } else {
- g_signal_connect (self->database_monitor,
- "changed",
- G_CALLBACK (on_file_monitor_changed),
- self);
- }
-}
-
-static void
-finalize (GObject *object)
-{
- 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);
-}
-
-static void
-nm_session_monitor_class_init (NMSessionMonitorClass *klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->finalize = 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);
-}
-
-NMSessionMonitor *
-nm_session_monitor_get (void)
-{
- static NMSessionMonitor *singleton = NULL;
-
- if (!singleton)
- singleton = NM_SESSION_MONITOR (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)
-{
- 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_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "No session found for user '%s'",
- username);
- return FALSE;
- }
-
- if (out_uid)
- *out_uid = s->uid;
- return TRUE;
-}
-
-/**
- * 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)
-{
- 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_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "No session found for uid %d",
- uid);
- return FALSE;
- }
-
- if (out_user)
- *out_user = s->user;
- return TRUE;
-}
-
-/**
- * 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)
-{
- 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_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "No session found for user '%s'",
- username);
- return FALSE;
- }
-
- return s->active;
-}
-
-/**
- * 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)
-{
- 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_MANAGER_ERROR,
- NM_MANAGER_ERROR_FAILED,
- "No session found for uid '%d'",
- uid);
- return FALSE;
- }
-
- return s->active;
-}
-
diff --git a/src/nm-session-monitor-null.c b/src/nm-session-monitor-null.c
deleted file mode 100644
index 22d5dca0e2..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-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 6d4da4840c..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-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.c b/src/nm-session-monitor.c
index 6ba0bb92f8..36d40095e2 100644
--- a/src/nm-session-monitor.c
+++ b/src/nm-session-monitor.c
@@ -14,13 +14,279 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2008 - 2015 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 <pwd.h>
-#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <gio/gio.h>
#include "nm-session-monitor.h"
+#include "nm-logging.h"
+
+#ifdef SESSION_TRACKING_SYSTEMD
+#include <systemd/sd-login.h>
+#endif
+
+/********************************************************************/
+
+/* <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;
+
+#ifdef SESSION_TRACKING_SYSTEMD
+ struct {
+ sd_login_monitor *monitor;
+ guint watch;
+ } sd;
+#endif
+
+#ifdef SESSION_TRACKING_CONSOLEKIT
+ struct {
+ GFileMonitor *monitor;
+ GHashTable *cache;
+ time_t timestamp;
+ } ck;
+#endif
+};
+
+struct _NMSessionMonitorClass {
+ GObjectClass parent_class;
+
+ void (*changed) (NMSessionMonitor *monitor);
+};
+
+G_DEFINE_TYPE (NMSessionMonitor, nm_session_monitor, G_TYPE_OBJECT);
+
+enum {
+ CHANGED,
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/********************************************************************/
+
+#ifdef SESSION_TRACKING_SYSTEMD
+static gboolean
+sd_session_exists (NMSessionMonitor *monitor, uid_t uid, gboolean active)
+{
+ int status;
+
+ if (!monitor->sd.monitor)
+ return FALSE;
+
+ status = sd_uid_get_sessions (uid, active, NULL);
+
+ if (status < 0)
+ nm_log_err (LOGD_CORE, "Failed to get systemd sessions for uid %d: %d",
+ uid, status);
+
+ return status > 0;
+}
+
+static gboolean
+sd_changed (GIOChannel *stream, GIOCondition condition, gpointer user_data)
+{
+ NMSessionMonitor *monitor = user_data;
+
+ g_signal_emit (monitor, signals[CHANGED], 0);
+
+ sd_login_monitor_flush (monitor->sd.monitor);
+
+ return TRUE;
+}
+
+static void
+sd_init (NMSessionMonitor *monitor)
+{
+ int status;
+ GIOChannel *stream;
+
+ if (!g_file_test ("/run/systemd/seats/", G_FILE_TEST_EXISTS))
+ return;
+
+ if ((status = sd_login_monitor_new (NULL, &monitor->sd.monitor)) < 0) {
+ nm_log_err (LOGD_CORE, "Failed to create systemd login monitor: %d", status);
+ return;
+ }
+
+ stream = g_io_channel_unix_new (sd_login_monitor_get_fd (monitor->sd.monitor));
+ monitor->sd.watch = g_io_add_watch (stream, G_IO_IN, sd_changed, monitor);
+
+ g_io_channel_unref (stream);
+}
+
+static void
+sd_finalize (NMSessionMonitor *monitor)
+{
+ g_clear_pointer (&monitor->sd.monitor, sd_login_monitor_unref);
+ g_source_remove (monitor->sd.watch);
+}
+#endif /* SESSION_TRACKING_SYSTEMD */
+
+/********************************************************************/
+
+#ifdef SESSION_TRACKING_CONSOLEKIT
+typedef struct {
+ gboolean active;
+} CkSession;
+
+static gboolean
+ck_load_cache (GHashTable *cache)
+{
+ GKeyFile *keyfile = g_key_file_new ();
+ char **groups = NULL;
+ GError *error = NULL;
+ gsize i, len;
+ gboolean finished = FALSE;
+
+ if (!g_key_file_load_from_file (keyfile, CKDB_PATH, G_KEY_FILE_NONE, &error))
+ goto out;
+
+ if (!(groups = g_key_file_get_groups (keyfile, &len))) {
+ nm_log_err (LOGD_CORE, "Could not load groups from " CKDB_PATH);
+ goto out;
+ }
+
+ g_hash_table_remove_all (cache);
+
+ for (i = 0; i < len; i++) {
+ guint uid = G_MAXUINT;
+ CkSession session = { .active = FALSE };
+
+ if (!g_str_has_prefix (groups[i], "CkSession "))
+ continue;
+
+ uid = g_key_file_get_integer (keyfile, groups[i], "uid", &error);
+ if (error)
+ goto out;
+
+ session.active = g_key_file_get_boolean (keyfile, groups[i], "is_active", &error);
+ if (error)
+ goto out;
+
+ g_hash_table_insert (cache, GUINT_TO_POINTER (uid), g_memdup (&session, sizeof session));
+ }
+
+ finished = TRUE;
+out:
+ if (error)
+ nm_log_err (LOGD_CORE, "ConsoleKit: Failed to load database: %s", error->message);
+ g_clear_error (&error);
+ g_clear_pointer (&groups, g_strfreev);
+ g_clear_pointer (&keyfile, g_key_file_free);
+
+ return finished;
+}
+
+static gboolean
+ck_update_cache (NMSessionMonitor *monitor)
+{
+ struct stat statbuf;
+
+ if (!monitor->ck.cache)
+ return FALSE;
+
+ /* Check the database file */
+ if (stat (CKDB_PATH, &statbuf) != 0) {
+ nm_log_err (LOGD_CORE, "Failed to check ConsoleKit timestamp: %s", strerror (errno));
+ return FALSE;
+ }
+ if (statbuf.st_mtime == monitor->ck.timestamp)
+ return TRUE;
+
+ /* Update the cache */
+ if (!ck_load_cache (monitor->ck.cache))
+ return FALSE;
+
+ monitor->ck.timestamp = statbuf.st_mtime;
+
+ return TRUE;
+}
+
+static gboolean
+ck_session_exists (NMSessionMonitor *monitor, uid_t uid, gboolean active)
+{
+ CkSession *session;
+
+ if (!ck_update_cache (monitor))
+ return FALSE;
+
+ session = g_hash_table_lookup (monitor->ck.cache, GUINT_TO_POINTER (uid));
+
+ if (!session)
+ return FALSE;
+ if (active && !session->active)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+ck_changed (GFileMonitor * file_monitor,
+ GFile * file,
+ GFile * other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ g_signal_emit (user_data, signals[CHANGED], 0);
+}
+
+static void
+ck_init (NMSessionMonitor *monitor)
+{
+ GFile *file = g_file_new_for_path (CKDB_PATH);
+ GError *error = NULL;
+
+ if (g_file_query_exists (file, NULL)) {
+ if ((monitor->ck.monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error))) {
+ monitor->ck.cache = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+ g_signal_connect (monitor->ck.monitor,
+ "changed",
+ G_CALLBACK (ck_changed),
+ monitor);
+ } else {
+ nm_log_err (LOGD_CORE, "Error monitoring " CKDB_PATH ": %s", error->message);
+ g_clear_error (&error);
+ }
+ }
+
+ g_object_unref (file);
+}
+
+static void
+ck_finalize (NMSessionMonitor *monitor)
+{
+ g_clear_pointer (&monitor->ck.cache, g_hash_table_unref);
+ g_clear_object (&monitor->ck.monitor);
+}
+#endif /* SESSION_TRACKING_CONSOLEKIT */
+
+/********************************************************************/
+
+static NMSessionMonitor *
+nm_session_monitor_get (void)
+{
+ static NMSessionMonitor *singleton = NULL;
+
+ if (!singleton)
+ singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL));
+
+ return singleton;
+}
/**
* nm_session_monitor_connect:
@@ -112,8 +378,70 @@ nm_session_monitor_user_to_uid (const char *user, uid_t *out_uid)
gboolean
nm_session_monitor_session_exists (uid_t uid, gboolean active)
{
- if (active)
- return nm_session_monitor_uid_active (nm_session_monitor_get (), uid, NULL);
- else
- return nm_session_monitor_uid_has_session (nm_session_monitor_get (), uid, NULL, NULL);
+ NMSessionMonitor *monitor = nm_session_monitor_get ();
+
+#ifdef SESSION_TRACKING_SYSTEMD
+ if (sd_session_exists (monitor, uid, active))
+ return TRUE;
+#endif
+
+#ifdef SESSION_TRACKING_CONSOLEKIT
+ if (ck_session_exists (monitor, uid, active))
+ return TRUE;
+#endif
+
+ return FALSE;
+}
+
+/********************************************************************/
+
+static void
+nm_session_monitor_init (NMSessionMonitor *monitor)
+{
+#ifdef SESSION_TRACKING_SYSTEMD
+ sd_init (monitor);
+#endif
+
+#ifdef SESSION_TRACKING_CONSOLEKIT
+ ck_init (monitor);
+#endif
+}
+
+static void
+nm_session_monitor_finalize (GObject *object)
+{
+#ifdef SESSION_TRACKING_SYSTEMD
+ sd_finalize (NM_SESSION_MONITOR (object));
+#endif
+
+#ifdef SESSION_TRACKING_CONSOLEKIT
+ ck_finalize (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 9a38dc0eee..32f747f231 100644
--- a/src/nm-session-monitor.h
+++ b/src/nm-session-monitor.h
@@ -40,8 +40,7 @@ typedef struct _NMSessionMonitorClass NMSessionMonitorClass;
typedef void (*NMSessionCallback) (NMSessionMonitor *monitor, gpointer user_data);
-GType nm_session_monitor_get_type (void) G_GNUC_CONST;
-NMSessionMonitor *nm_session_monitor_get (void);
+GType nm_session_monitor_get_type (void) G_GNUC_CONST;
gulong nm_session_monitor_connect (NMSessionCallback callback, gpointer user_data);
void nm_session_monitor_disconnect (gulong handler_id);
@@ -50,23 +49,6 @@ gboolean nm_session_monitor_uid_to_user (uid_t uid, const char **out
gboolean nm_session_monitor_user_to_uid (const char *user, uid_t *out_uid);
gboolean nm_session_monitor_session_exists (uid_t uid, gboolean active);
-gboolean nm_session_monitor_user_has_session (NMSessionMonitor *monitor,
- const char *username,
- uid_t *out_uid,
- GError **error);
-
-gboolean nm_session_monitor_uid_has_session (NMSessionMonitor *monitor,
- uid_t uid,
- const char **out_user,
- GError **error);
-gboolean nm_session_monitor_user_active (NMSessionMonitor *monitor,
- const char *username,
- GError **error);
-
-gboolean nm_session_monitor_uid_active (NMSessionMonitor *monitor,
- uid_t uid,
- GError **error);
-
G_END_DECLS
#endif /* __NETWORKMANAGER_SESSION_MONITOR_H__ */