diff options
author | Matthias Clasen <mclasen@redhat.com> | 2011-12-23 20:07:07 -0500 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2012-02-01 15:09:46 -0600 |
commit | 3b75a97ab0e34452b4b72b646ecb034027ef2080 (patch) | |
tree | f8fc59250da2da4c2287217a4c07d72ec91ae712 | |
parent | c09a59da4b2a4d91cde01f6faefae9c188c5c6e7 (diff) | |
download | NetworkManager-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.ac | 28 | ||||
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/nm-session-monitor-systemd.c | 318 |
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; +} |