summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2011-12-23 20:07:07 -0500
committerDan Williams <dcbw@redhat.com>2012-02-01 15:09:46 -0600
commit3b75a97ab0e34452b4b72b646ecb034027ef2080 (patch)
treef8fc59250da2da4c2287217a4c07d72ec91ae712
parentc09a59da4b2a4d91cde01f6faefae9c188c5c6e7 (diff)
downloadNetworkManager-3b75a97ab0e34452b4b72b646ecb034027ef2080.tar.gz
core: optionally use systemd for session tracking instead of ConsoleKit
When configured with --enable-systemd, this patch makes NetworkManager use systemd for session tracking instead of ConsoleKit.
-rw-r--r--configure.ac28
-rw-r--r--src/Makefile.am12
-rw-r--r--src/nm-session-monitor-systemd.c318
3 files changed, 350 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index 49ef52f484..a5fd5cfb11 100644
--- a/configure.ac
+++ b/configure.ac
@@ -322,6 +322,8 @@ if test "x$with_systemdsystemunitdir" != xno; then
fi
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
+SESSION_TRACKING=none
+
dnl
dnl Disable ConsoleKit support
dnl
@@ -332,9 +334,25 @@ if test x"$with_ck" = x"no"; then
no_ck="1"
else
with_ck="yes"
+ SESSION_TRACKING=ConsoleKit
fi
AC_DEFINE_UNQUOTED(NO_CONSOLEKIT, $no_ck, [Define to disable use of ConsoleKit])
+# systemd session tracking
+AC_ARG_ENABLE([systemd],
+ AS_HELP_STRING([--enable-systemd], [Use systemd for session tracking]),
+ [with_systemd=$enableval],
+ [with_systemd=no])
+if test "$with_systemd" = "yes" ; then
+ PKG_CHECK_MODULES(SYSTEMD, [libsystemd-login])
+ SESSION_TRACKING=systemd
+fi
+
+AC_SUBST(SYSTEMD_CFLAGS)
+AC_SUBST(SYSTEMD_LIBS)
+
+
+AM_CONDITIONAL(WITH_SYSTEMD, [test "$with_systemd" = "yes"], [Using systemd])
have_libnl="no"
PKG_CHECK_MODULES(LIBNL3, libnl-3.0, [have_libnl3=yes], [have_libnl3=no])
PKG_CHECK_MODULES(LIBNL_ROUTE3, libnl-route-3.0, [have_libnl_route3=yes], [have_libnl_route3=no])
@@ -777,9 +795,9 @@ else
fi
if test -n "${with_systemdsystemunitdir}"; then
- echo systemd support: ${with_systemdsystemunitdir}
+ echo systemd unit support: ${with_systemdsystemunitdir}
else
- echo systemd support: no
+ echo systemd unit support: no
fi
if test "${enable_polkit}" = "yes"; then
@@ -788,11 +806,7 @@ else
echo PolicyKit support: no
fi
-if test -n "${with_ck}"; then
- echo ConsoleKit support: ${with_ck}
-else
- echo ConsoleKit support: no
-fi
+ echo Session tracking: ${SESSION_TRACKING}
if test "${enable_wimax}" = "yes"; then
echo WiMAX support: yes
diff --git a/src/Makefile.am b/src/Makefile.am
index 37e6b9c7b3..a1137bf665 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -183,9 +183,17 @@ NetworkManager_SOURCES = \
nm-dhcp6-config.c \
nm-dhcp6-config.h \
nm-rfkill.h \
- nm-session-monitor.c \
nm-session-monitor.h
+if WITH_SYSTEMD
+NetworkManager_SOURCES += \
+ nm-session-monitor-systemd.c
+
+else
+NetworkManager_SOURCES += \
+ nm-session-monitor.c
+endif
+
nm-access-point-glue.h: $(top_srcdir)/introspection/nm-access-point.xml
$(AM_V_GEN) dbus-binding-tool --prefix=nm_access_point --mode=glib-server --output=$@ $<
@@ -251,6 +259,7 @@ NetworkManager_CPPFLAGS = \
$(LIBNL_CFLAGS) \
$(GMODULE_CFLAGS) \
$(POLKIT_CFLAGS) \
+ $(SYSTEMD_CFLAGS) \
-DG_DISABLE_DEPRECATED \
-DBINDIR=\"$(bindir)\" \
-DSBINDIR=\"$(sbindir)\" \
@@ -285,6 +294,7 @@ NetworkManager_LDADD = \
$(LIBNL_LIBS) \
$(GMODULE_LIBS) \
$(POLKIT_LIBS) \
+ $(SYSTEMD_LIBS) \
$(LIBM) \
$(LIBDL)
diff --git a/src/nm-session-monitor-systemd.c b/src/nm-session-monitor-systemd.c
new file mode 100644
index 0000000000..cecfb8b324
--- /dev/null
+++ b/src/nm-session-monitor-systemd.c
@@ -0,0 +1,318 @@
+/*
+ * 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, 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"
+
+/********************************************************************/
+
+#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_UNKNOWN_USER
+} NMSessionMonitorError;
+
+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;
+}
+
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+nm_session_monitor_error_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ /* Username or UID could could not be found */
+ ENUM_ENTRY (NM_SESSION_MONITOR_ERROR_UNKNOWN_USER, "UnknownUser"),
+ { 0, 0, 0 }
+ };
+ etype = g_enum_register_static ("NMSessionMonitorError", values);
+ }
+ return etype;
+}
+/********************************************************************/
+
+
+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;
+
+ if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 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));
+
+ return singleton;
+}
+
+static gboolean
+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;
+}
+
+gboolean
+nm_session_monitor_user_has_session (NMSessionMonitor *monitor,
+ const char *username,
+ uid_t *out_uid,
+ GError **error)
+{
+ uid_t uid;
+
+ if (!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 (!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)
+{
+ return sd_uid_get_sessions (uid, FALSE, NULL) > 0;
+}
+
+gboolean
+nm_session_monitor_uid_active (NMSessionMonitor *monitor,
+ uid_t uid,
+ GError **error)
+{
+ return sd_uid_get_sessions (uid, TRUE, NULL) > 0;
+}