Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 468930 | Differences between
and this patch

Collapse All | Expand All

(-)a/configure.ac (-1 / +3 lines)
Lines 368-374 if test "x$with_systemdsystemunitdir" != xno; then Link Here
368
fi
368
fi
369
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
369
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
370
370
371
AC_ARG_WITH(session-tracking, AS_HELP_STRING([--with-session-tracking=systemd|ck|none], [Build NetworkManager with specific session tracking support]))
371
AC_ARG_WITH(session-tracking, AS_HELP_STRING([--with-session-tracking=systemd|ck|none], [Build NetworkManager with specific session tracking support, systemd falls back to ConsoleKit if logind is not available]))
372
if test "z$with_session_tracking" = "z"; then
372
if test "z$with_session_tracking" = "z"; then
373
    # Default to ConsoleKit session tracking like we used before
373
    # Default to ConsoleKit session tracking like we used before
374
    with_session_tracking=ck
374
    with_session_tracking=ck
Lines 378-383 case $with_session_tracking in Link Here
378
    ck|none|no) ;;
378
    ck|none|no) ;;
379
    systemd)
379
    systemd)
380
        PKG_CHECK_MODULES(SYSTEMD, [libsystemd-login])
380
        PKG_CHECK_MODULES(SYSTEMD, [libsystemd-login])
381
        AC_DEFINE([SESSION_TRACKING_SYSTEMD], 1, [Define to 1 if libsystemd-login is available])
381
        ;;
382
        ;;
382
    *)
383
    *)
383
	AC_MSG_ERROR(--with-session-tracking must be one of [none, ck, systemd])
384
	AC_MSG_ERROR(--with-session-tracking must be one of [none, ck, systemd])
Lines 387-392 AC_SUBST(SYSTEMD_CFLAGS) Link Here
387
AC_SUBST(SYSTEMD_LIBS)
388
AC_SUBST(SYSTEMD_LIBS)
388
AM_CONDITIONAL(SESSION_TRACKING_CK, test "x$with_session_tracking" = "xck")
389
AM_CONDITIONAL(SESSION_TRACKING_CK, test "x$with_session_tracking" = "xck")
389
AM_CONDITIONAL(SESSION_TRACKING_SYSTEMD, test "x$with_session_tracking" = "xsystemd")
390
AM_CONDITIONAL(SESSION_TRACKING_SYSTEMD, test "x$with_session_tracking" = "xsystemd")
391
AM_CONDITIONAL(SESSION_TRACKING_NULL, test "x$with_session_tracking" = "xnone" || test "x$with_session_tracking" = "xno")
390
392
391
393
392
have_libnl="no"
394
have_libnl="no"
(-)a/src/Makefile.am (-7 / +3 lines)
Lines 199-212 if WITH_CONCHECK Link Here
199
NetworkManager_SOURCES += nm-connectivity.c nm-connectivity.h
199
NetworkManager_SOURCES += nm-connectivity.c nm-connectivity.h
200
endif
200
endif
201
201
202
if SESSION_TRACKING_SYSTEMD
202
if SESSION_TRACKING_NULL
203
NetworkManager_SOURCES += nm-session-monitor-systemd.c
204
else
205
if SESSION_TRACKING_CK
206
NetworkManager_SOURCES += nm-session-monitor-ck.c
207
else
208
NetworkManager_SOURCES += nm-session-monitor-null.c
203
NetworkManager_SOURCES += nm-session-monitor-null.c
209
endif
204
else
205
NetworkManager_SOURCES += nm-session-monitor.c
210
endif
206
endif
211
207
212
nm-access-point-glue.h: $(top_srcdir)/introspection/nm-access-point.xml
208
nm-access-point-glue.h: $(top_srcdir)/introspection/nm-access-point.xml
(-)a/src/nm-session-monitor-ck.c (-509 lines)
Lines 1-509 Link Here
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* This program is free software; you can redistribute it and/or modify
3
 * it under the terms of the GNU General Public License as published by
4
 * the Free Software Foundation; either version 2 of the License, or
5
 * (at your option) any later version.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License along
13
 * with this program; if not, write to the Free Software Foundation, Inc.,
14
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15
 *
16
 * (C) Copyright 2008 - 2010 Red Hat, Inc.
17
 * Author: David Zeuthen <davidz@redhat.com>
18
 * Author: Dan Williams <dcbw@redhat.com>
19
 */
20
21
#include "config.h"
22
#include <errno.h>
23
#include <string.h>
24
#include <sys/stat.h>
25
#include <gio/gio.h>
26
#include "nm-logging.h"
27
28
#include "nm-session-utils.h"
29
#include "nm-session-monitor.h"
30
31
#define CKDB_PATH "/var/run/ConsoleKit/database"
32
33
/* <internal>
34
 * SECTION:nm-session-monitor
35
 * @title: NMSessionMonitor
36
 * @short_description: Monitor sessions
37
 *
38
 * The #NMSessionMonitor class is a utility class to track and monitor sessions.
39
 */
40
41
struct _NMSessionMonitor {
42
	GObject parent_instance;
43
44
	GKeyFile *database;
45
	GFileMonitor *database_monitor;
46
	time_t database_mtime;
47
	GHashTable *sessions_by_uid;
48
	GHashTable *sessions_by_user;
49
};
50
51
struct _NMSessionMonitorClass {
52
	GObjectClass parent_class;
53
54
	void (*changed) (NMSessionMonitor *monitor);
55
};
56
57
58
enum {
59
	CHANGED,
60
	LAST_SIGNAL,
61
};
62
static guint signals[LAST_SIGNAL] = {0};
63
64
G_DEFINE_TYPE (NMSessionMonitor, nm_session_monitor, G_TYPE_OBJECT);
65
66
/********************************************************************/
67
68
typedef struct {
69
	char *user;
70
	uid_t uid;
71
	gboolean local;
72
	gboolean active;
73
} Session;
74
75
static void
76
session_free (Session *s)
77
{
78
	g_free (s->user);
79
	memset (s, 0, sizeof (Session));
80
	g_free (s);
81
}
82
83
static gboolean
84
check_key (GKeyFile *keyfile, const char *group, const char *key, GError **error)
85
{
86
	if (g_key_file_has_key (keyfile, group, key, error))
87
		return TRUE;
88
89
	if (!error) {
90
		g_set_error (error,
91
			         NM_SESSION_MONITOR_ERROR,
92
			         NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE,
93
			         "ConsoleKit database " CKDB_PATH " group '%s' had no '%s' key",
94
			         group, key);
95
	}
96
	return FALSE;
97
}
98
99
static Session *
100
session_new (GKeyFile *keyfile, const char *group, GError **error)
101
{
102
	GError *local = NULL;
103
	Session *s;
104
	const char *uname = NULL;
105
106
	s = g_new0 (Session, 1);
107
	g_assert (s);
108
109
	s->uid = G_MAXUINT; /* paranoia */
110
	if (!check_key (keyfile, group, "uid", &local))
111
		goto error;
112
	s->uid = (uid_t) g_key_file_get_integer (keyfile, group, "uid", &local);
113
	if (local)
114
		goto error;
115
116
	if (!check_key (keyfile, group, "is_active", &local))
117
		goto error;
118
	s->active = g_key_file_get_boolean (keyfile, group, "is_active", &local);
119
	if (local)
120
		goto error;
121
122
	if (!check_key (keyfile, group, "is_local", &local))
123
		goto error;
124
	s->local = g_key_file_get_boolean (keyfile, group, "is_local", &local);
125
	if (local)
126
		goto error;
127
128
	if (!nm_session_uid_to_user (s->uid, &uname, error))
129
		return FALSE;
130
	s->user = g_strdup (uname);
131
132
	return s;
133
134
error:
135
	session_free (s);
136
	g_propagate_error (error, local);
137
	return NULL;
138
}
139
140
static void
141
session_merge (Session *src, Session *dest)
142
{
143
	g_return_if_fail (src != NULL);
144
	g_return_if_fail (dest != NULL);
145
146
	g_warn_if_fail (g_strcmp0 (src->user, dest->user) == 0);
147
	g_warn_if_fail (src->uid == dest->uid);
148
149
	dest->local = (dest->local || src->local);
150
	dest->active = (dest->active || src->active);
151
}
152
153
/********************************************************************/
154
155
static void
156
free_database (NMSessionMonitor *self)
157
{
158
	if (self->database != NULL) {
159
		g_key_file_free (self->database);
160
		self->database = NULL;
161
	}
162
163
	g_hash_table_remove_all (self->sessions_by_uid);
164
	g_hash_table_remove_all (self->sessions_by_user);
165
}
166
167
static gboolean
168
reload_database (NMSessionMonitor *self, GError **error)
169
{
170
	struct stat statbuf;
171
	char **groups = NULL;
172
	gsize len = 0, i;
173
	Session *s;
174
175
	free_database (self);
176
177
	errno = 0;
178
	if (stat (CKDB_PATH, &statbuf) != 0) {
179
		g_set_error (error,
180
		             NM_SESSION_MONITOR_ERROR,
181
		             errno == ENOENT ? NM_SESSION_MONITOR_ERROR_NO_DATABASE : NM_SESSION_MONITOR_ERROR_IO_ERROR,
182
		             "Error statting file " CKDB_PATH ": %s",
183
		             strerror (errno));
184
		goto error;
185
	}
186
	self->database_mtime = statbuf.st_mtime;
187
188
	self->database = g_key_file_new ();
189
	if (!g_key_file_load_from_file (self->database, CKDB_PATH, G_KEY_FILE_NONE, error))
190
		goto error;
191
192
	groups = g_key_file_get_groups (self->database, &len);
193
	if (!groups) {
194
		g_set_error_literal (error,
195
		                     NM_SESSION_MONITOR_ERROR,
196
		                     NM_SESSION_MONITOR_ERROR_IO_ERROR,
197
		                     "Could not load groups from " CKDB_PATH "");
198
		goto error;
199
	}
200
201
	for (i = 0; i < len; i++) {
202
		Session *found;
203
204
		if (!g_str_has_prefix (groups[i], "Session "))
205
			continue;
206
207
		s = session_new (self->database, groups[i], error);
208
		if (!s)
209
			goto error;
210
211
		found = g_hash_table_lookup (self->sessions_by_user, (gpointer) s->user);
212
		if (found) {
213
			session_merge (s, found);
214
			session_free (s);
215
		} else {
216
			/* Entirely new user */
217
			g_hash_table_insert (self->sessions_by_user, (gpointer) s->user, s);
218
			g_hash_table_insert (self->sessions_by_uid, GUINT_TO_POINTER (s->uid), s);
219
		}
220
	}
221
222
	g_strfreev (groups);
223
	return TRUE;
224
225
error:
226
	if (groups)
227
		g_strfreev (groups);
228
	free_database (self);
229
	return FALSE;
230
}
231
232
static gboolean
233
ensure_database (NMSessionMonitor *self, GError **error)
234
{
235
	gboolean ret = FALSE;
236
237
	if (self->database != NULL) {
238
		struct stat statbuf;
239
240
		errno = 0;
241
		if (stat (CKDB_PATH, &statbuf) != 0) {
242
			g_set_error (error,
243
			             NM_SESSION_MONITOR_ERROR,
244
			             errno == ENOENT ? NM_SESSION_MONITOR_ERROR_NO_DATABASE : NM_SESSION_MONITOR_ERROR_IO_ERROR,
245
			             "Error statting file " CKDB_PATH " to check timestamp: %s",
246
			             strerror (errno));
247
			goto out;
248
		}
249
250
		if (statbuf.st_mtime == self->database_mtime) {
251
			ret = TRUE;
252
			goto out;
253
		}
254
	}
255
256
	ret = reload_database (self, error);
257
258
out:
259
	return ret;
260
}
261
262
static void
263
on_file_monitor_changed (GFileMonitor *    file_monitor,
264
                         GFile *           file,
265
                         GFile *           other_file,
266
                         GFileMonitorEvent event_type,
267
                         gpointer          user_data)
268
{
269
	NMSessionMonitor *self = NM_SESSION_MONITOR (user_data);
270
271
	/* throw away cache */
272
	free_database (self);
273
274
	g_signal_emit (self, signals[CHANGED], 0);
275
}
276
277
static void
278
nm_session_monitor_init (NMSessionMonitor *self)
279
{
280
	GError *error = NULL;
281
	GFile *file;
282
283
	/* Sessions-by-user is responsible for destroying the Session objects */
284
	self->sessions_by_user = g_hash_table_new_full (g_str_hash, g_str_equal,
285
	                                                NULL, (GDestroyNotify) session_free);
286
	self->sessions_by_uid = g_hash_table_new (g_direct_hash, g_direct_equal);
287
288
289
	error = NULL;
290
	if (!ensure_database (self, &error)) {
291
		/* Ignore the first error if the CK database isn't found yet */
292
		if (g_error_matches (error,
293
		                     NM_SESSION_MONITOR_ERROR,
294
		                     NM_SESSION_MONITOR_ERROR_NO_DATABASE) == FALSE) {
295
			nm_log_err (LOGD_CORE, "Error loading " CKDB_PATH ": %s", error->message);
296
		}
297
		g_error_free (error);
298
	}
299
300
	error = NULL;
301
	file = g_file_new_for_path (CKDB_PATH);
302
	self->database_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
303
	g_object_unref (file);
304
	if (self->database_monitor == NULL) {
305
		nm_log_err (LOGD_CORE, "Error monitoring " CKDB_PATH ": %s", error->message);
306
		g_error_free (error);
307
	} else {
308
		g_signal_connect (self->database_monitor,
309
		                  "changed",
310
		                  G_CALLBACK (on_file_monitor_changed),
311
		                  self);
312
	}
313
}
314
315
static void
316
finalize (GObject *object)
317
{
318
	NMSessionMonitor *self = NM_SESSION_MONITOR (object);
319
320
	if (self->database_monitor != NULL)
321
		g_object_unref (self->database_monitor);
322
323
	free_database (self);
324
325
	if (G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize != NULL)
326
		G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize (object);
327
}
328
329
static void
330
nm_session_monitor_class_init (NMSessionMonitorClass *klass)
331
{
332
	GObjectClass *gobject_class;
333
334
	gobject_class = G_OBJECT_CLASS (klass);
335
336
	gobject_class->finalize = finalize;
337
338
	/**
339
	 * NMSessionMonitor::changed:
340
	 * @monitor: A #NMSessionMonitor
341
	 *
342
	 * Emitted when something changes.
343
	 */
344
	signals[CHANGED] = g_signal_new (NM_SESSION_MONITOR_CHANGED,
345
	                                 NM_TYPE_SESSION_MONITOR,
346
	                                 G_SIGNAL_RUN_LAST,
347
	                                 G_STRUCT_OFFSET (NMSessionMonitorClass, changed),
348
	                                 NULL,                   /* accumulator      */
349
	                                 NULL,                   /* accumulator data */
350
	                                 g_cclosure_marshal_VOID__VOID,
351
	                                 G_TYPE_NONE, 0);
352
}
353
354
NMSessionMonitor *
355
nm_session_monitor_get (void)
356
{
357
	static NMSessionMonitor *singleton = NULL;
358
359
	if (singleton)
360
		return g_object_ref (singleton);
361
362
	singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL));
363
	return singleton;
364
}
365
366
/* ---------------------------------------------------------------------------------------------------- */
367
368
/**
369
 * nm_session_monitor_user_has_session:
370
 * @monitor: A #NMSessionMonitor.
371
 * @username: A username.
372
 * @error: Return location for error.
373
 *
374
 * Checks whether the given @username is logged into a session or not.
375
 *
376
 * Returns: %FALSE if @error is set otherwise %TRUE if the given @username is
377
 * currently logged into a session.
378
 */
379
gboolean
380
nm_session_monitor_user_has_session (NMSessionMonitor *monitor,
381
                                     const char *username,
382
                                     uid_t *out_uid,
383
                                     GError **error)
384
{
385
	Session *s;
386
387
	if (!ensure_database (monitor, error))
388
		return FALSE;
389
390
	s = g_hash_table_lookup (monitor->sessions_by_user, (gpointer) username);
391
	if (!s) {
392
		g_set_error (error,
393
		             NM_SESSION_MONITOR_ERROR,
394
		             NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
395
		             "No session found for user '%s'",
396
		             username);
397
		return FALSE;
398
	}
399
400
	if (out_uid)
401
		*out_uid = s->uid;
402
	return TRUE;
403
}
404
405
/**
406
 * nm_session_monitor_uid_has_session:
407
 * @monitor: A #NMSessionMonitor.
408
 * @uid: A user ID.
409
 * @error: Return location for error.
410
 *
411
 * Checks whether the given @uid is logged into a session or not.
412
 *
413
 * Returns: %FALSE if @error is set otherwise %TRUE if the given @uid is
414
 * currently logged into a session.
415
 */
416
gboolean
417
nm_session_monitor_uid_has_session (NMSessionMonitor *monitor,
418
                                    uid_t uid,
419
                                    const char **out_user,
420
                                    GError **error)
421
{
422
	Session *s;
423
424
	if (!ensure_database (monitor, error))
425
		return FALSE;
426
427
	s = g_hash_table_lookup (monitor->sessions_by_uid, GUINT_TO_POINTER (uid));
428
	if (!s) {
429
		g_set_error (error,
430
		             NM_SESSION_MONITOR_ERROR,
431
		             NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
432
		             "No session found for uid %d",
433
		             uid);
434
		return FALSE;
435
	}
436
437
	if (out_user)
438
		*out_user = s->user;
439
	return TRUE;
440
}
441
442
/**
443
 * nm_session_monitor_user_active:
444
 * @monitor: A #NMSessionMonitor.
445
 * @username: A username.
446
 * @error: Return location for error.
447
 *
448
 * Checks whether the given @username is logged into a active session or not.
449
 *
450
 * Returns: %FALSE if @error is set otherwise %TRUE if the given @username is
451
 * logged into an active session.
452
 */
453
gboolean
454
nm_session_monitor_user_active (NMSessionMonitor *monitor,
455
                                const char *username,
456
                                GError **error)
457
{
458
	Session *s;
459
460
	if (!ensure_database (monitor, error))
461
		return FALSE;
462
463
	s = g_hash_table_lookup (monitor->sessions_by_user, (gpointer) username);
464
	if (!s) {
465
		g_set_error (error,
466
		             NM_SESSION_MONITOR_ERROR,
467
		             NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
468
		             "No session found for user '%s'",
469
		             username);
470
		return FALSE;
471
	}
472
473
	return s->active;
474
}
475
476
/**
477
 * nm_session_monitor_uid_active:
478
 * @monitor: A #NMSessionMonitor.
479
 * @uid: A user ID.
480
 * @error: Return location for error.
481
 *
482
 * Checks whether the given @uid is logged into a active session or not.
483
 *
484
 * Returns: %FALSE if @error is set otherwise %TRUE if the given @uid is
485
 * logged into an active session.
486
 */
487
gboolean
488
nm_session_monitor_uid_active (NMSessionMonitor *monitor,
489
                               uid_t uid,
490
                               GError **error)
491
{
492
	Session *s;
493
494
	if (!ensure_database (monitor, error))
495
		return FALSE;
496
497
	s = g_hash_table_lookup (monitor->sessions_by_uid, GUINT_TO_POINTER (uid));
498
	if (!s) {
499
		g_set_error (error,
500
		             NM_SESSION_MONITOR_ERROR,
501
		             NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
502
		             "No session found for uid '%d'",
503
		             uid);
504
		return FALSE;
505
	}
506
507
	return s->active;
508
}
509
(-)a/src/nm-session-monitor-systemd.c (-268 lines)
Lines 1-268 Link Here
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/*
3
 * Copyright (C) 2011 Red Hat, Inc.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General
16
 * Public License along with this library; if not, write to the
17
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
 * Boston, MA 02110-1301, USA.
19
 *
20
 * Author: Matthias Clasen
21
 */
22
23
#include "config.h"
24
#include <errno.h>
25
#include <pwd.h>
26
#include <grp.h>
27
#include <string.h>
28
#include <glib/gstdio.h>
29
#include <systemd/sd-login.h>
30
#include <stdlib.h>
31
32
#include "nm-session-utils.h"
33
#include "nm-session-monitor.h"
34
#include "nm-logging.h"
35
36
/********************************************************************/
37
38
typedef struct {
39
	GSource source;
40
	GPollFD pollfd;
41
	sd_login_monitor *monitor;
42
} SdSource;
43
44
static gboolean
45
sd_source_prepare (GSource *source, gint *timeout)
46
{
47
	*timeout = -1;
48
	return FALSE;
49
}
50
51
static gboolean
52
sd_source_check (GSource *source)
53
{
54
	SdSource *sd_source = (SdSource *) source;
55
56
	return sd_source->pollfd.revents != 0;
57
}
58
59
static gboolean
60
sd_source_dispatch (GSource     *source,
61
                    GSourceFunc  callback,
62
                    gpointer     user_data)
63
64
{
65
	SdSource *sd_source = (SdSource *)source;
66
	gboolean ret;
67
68
	g_warn_if_fail (callback != NULL);
69
	ret = (*callback) (user_data);
70
	sd_login_monitor_flush (sd_source->monitor);
71
	return ret;
72
}
73
74
static void
75
sd_source_finalize (GSource *source)
76
{
77
	SdSource *sd_source = (SdSource*) source;
78
79
	sd_login_monitor_unref (sd_source->monitor);
80
}
81
82
static GSourceFuncs sd_source_funcs = {
83
	sd_source_prepare,
84
	sd_source_check,
85
	sd_source_dispatch,
86
	sd_source_finalize
87
};
88
89
static GSource *
90
sd_source_new (void)
91
{
92
	GSource *source;
93
	SdSource *sd_source;
94
	int ret;
95
96
	source = g_source_new (&sd_source_funcs, sizeof (SdSource));
97
	sd_source = (SdSource *)source;
98
99
	ret = sd_login_monitor_new (NULL, &sd_source->monitor);
100
	if (ret < 0)
101
		g_printerr ("Error getting login monitor: %d", ret);
102
	else {
103
		sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor);
104
		sd_source->pollfd.events = G_IO_IN;
105
		g_source_add_poll (source, &sd_source->pollfd);
106
	}
107
108
	return source;
109
}
110
111
struct _NMSessionMonitor {
112
	GObject parent_instance;
113
114
	GSource *sd_source;
115
};
116
117
struct _NMSessionMonitorClass {
118
	GObjectClass parent_class;
119
120
	void (*changed) (NMSessionMonitor *monitor);
121
};
122
123
124
enum {
125
	CHANGED_SIGNAL,
126
	LAST_SIGNAL,
127
};
128
static guint signals[LAST_SIGNAL] = {0};
129
130
G_DEFINE_TYPE (NMSessionMonitor, nm_session_monitor, G_TYPE_OBJECT);
131
132
/* ---------------------------------------------------------------------------------------------------- */
133
134
static gboolean
135
sessions_changed (gpointer user_data)
136
{
137
	NMSessionMonitor *monitor = NM_SESSION_MONITOR (user_data);
138
139
	g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
140
	return TRUE;
141
}
142
143
144
static void
145
nm_session_monitor_init (NMSessionMonitor *monitor)
146
{
147
	monitor->sd_source = sd_source_new ();
148
	g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL);
149
	g_source_attach (monitor->sd_source, NULL);
150
}
151
152
static void
153
nm_session_monitor_finalize (GObject *object)
154
{
155
	NMSessionMonitor *monitor = NM_SESSION_MONITOR (object);
156
157
	if (monitor->sd_source != NULL) {
158
		g_source_destroy (monitor->sd_source);
159
		g_source_unref (monitor->sd_source);
160
	}
161
162
	if (G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize != NULL)
163
		G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize (object);
164
}
165
166
static void
167
nm_session_monitor_class_init (NMSessionMonitorClass *klass)
168
{
169
	GObjectClass *gobject_class;
170
171
	gobject_class = G_OBJECT_CLASS (klass);
172
	gobject_class->finalize = nm_session_monitor_finalize;
173
174
	/**
175
	 * NMSessionMonitor::changed:
176
	 * @monitor: A #NMSessionMonitor
177
	 *
178
	 * Emitted when something changes.
179
	 */
180
	signals[CHANGED_SIGNAL] = g_signal_new ("changed",
181
	                                        NM_TYPE_SESSION_MONITOR,
182
	                                        G_SIGNAL_RUN_LAST,
183
	                                        G_STRUCT_OFFSET (NMSessionMonitorClass, changed),
184
	                                        NULL,                   /* accumulator      */
185
	                                        NULL,                   /* accumulator data */
186
	                                        g_cclosure_marshal_VOID__VOID,
187
	                                        G_TYPE_NONE,
188
	                                        0);
189
}
190
191
NMSessionMonitor *
192
nm_session_monitor_get (void)
193
{
194
	static NMSessionMonitor *singleton = NULL;
195
196
	if (singleton)
197
		return g_object_ref (singleton);
198
199
	singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL));
200
	g_assert (singleton);
201
	return singleton;
202
}
203
204
gboolean
205
nm_session_monitor_user_has_session (NMSessionMonitor *monitor,
206
                                     const char *username,
207
                                     uid_t *out_uid,
208
                                     GError **error)
209
{
210
	uid_t uid;
211
212
	if (!nm_session_user_to_uid (username, &uid, error))
213
		return FALSE;
214
215
	if (out_uid)
216
		*out_uid = uid;
217
218
	return nm_session_monitor_uid_has_session (monitor, uid, NULL, error);
219
}
220
221
gboolean
222
nm_session_monitor_user_active (NMSessionMonitor *monitor,
223
                                const char *username,
224
                                GError **error)
225
{
226
	uid_t uid;
227
228
	if (!nm_session_user_to_uid (username, &uid, error))
229
		return FALSE;
230
231
	return nm_session_monitor_uid_active (monitor, uid, error);
232
}
233
234
gboolean
235
nm_session_monitor_uid_has_session (NMSessionMonitor *monitor,
236
                                    uid_t uid,
237
                                    const char **out_user,
238
                                    GError **error)
239
{
240
	int ret;
241
242
	if (!nm_session_uid_to_user (uid, out_user, error))
243
		return FALSE;
244
245
	ret = sd_uid_get_sessions (uid, FALSE, NULL) > 0;
246
	if (ret < 0) {
247
		nm_log_warn (LOGD_CORE, "Failed to get systemd sessions for uid %d: %d",
248
		             uid, ret);
249
		return FALSE;
250
	}
251
	return ret > 0 ? TRUE : FALSE;
252
}
253
254
gboolean
255
nm_session_monitor_uid_active (NMSessionMonitor *monitor,
256
                               uid_t uid,
257
                               GError **error)
258
{
259
	int ret;
260
261
	ret = sd_uid_get_sessions (uid, TRUE, NULL) > 0;
262
	if (ret < 0) {
263
		nm_log_warn (LOGD_CORE, "Failed to get active systemd sessions for uid %d: %d",
264
		             uid, ret);
265
		return FALSE;
266
	}
267
	return ret > 0 ? TRUE : FALSE;
268
}
(-)a/src/nm-session-monitor.c (+641 lines)
Line 0 Link Here
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/*
3
 * Copyright (C) 2011 Red Hat, Inc.
4
 *
5
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2 of the License, or (at your option) any later version.
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General
16
 * Public License along with this library; if not, write to the
17
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
 * Boston, MA 02110-1301, USA.
19
 *
20
 * Author: Matthias Clasen
21
 */
22
23
#include "config.h"
24
#include <errno.h>
25
#include <pwd.h>
26
#include <grp.h>
27
#include <string.h>
28
#include <sys/stat.h>
29
#include <glib/gstdio.h>
30
#include <gio/gio.h>
31
#ifdef SESSION_TRACKING_SYSTEMD
32
#include <systemd/sd-login.h>
33
#endif
34
#include <stdlib.h>
35
36
#include "nm-session-utils.h"
37
#include "nm-session-monitor.h"
38
#include "nm-logging.h"
39
40
#define CKDB_PATH "/var/run/ConsoleKit/database"
41
42
/********************************************************************/
43
44
#ifdef SESSION_TRACKING_SYSTEMD
45
typedef struct {
46
	GSource source;
47
	GPollFD pollfd;
48
	sd_login_monitor *monitor;
49
} SdSource;
50
51
static gboolean
52
sd_source_prepare (GSource *source, gint *timeout)
53
{
54
	*timeout = -1;
55
	return FALSE;
56
}
57
58
static gboolean
59
sd_source_check (GSource *source)
60
{
61
	SdSource *sd_source = (SdSource *) source;
62
63
	return sd_source->pollfd.revents != 0;
64
}
65
66
static gboolean
67
sd_source_dispatch (GSource     *source,
68
                    GSourceFunc  callback,
69
                    gpointer     user_data)
70
71
{
72
	SdSource *sd_source = (SdSource *)source;
73
	gboolean ret;
74
75
	g_warn_if_fail (callback != NULL);
76
	ret = (*callback) (user_data);
77
	sd_login_monitor_flush (sd_source->monitor);
78
	return ret;
79
}
80
81
static void
82
sd_source_finalize (GSource *source)
83
{
84
	SdSource *sd_source = (SdSource*) source;
85
86
	sd_login_monitor_unref (sd_source->monitor);
87
}
88
89
static GSourceFuncs sd_source_funcs = {
90
	sd_source_prepare,
91
	sd_source_check,
92
	sd_source_dispatch,
93
	sd_source_finalize
94
};
95
96
static GSource *
97
sd_source_new (void)
98
{
99
	GSource *source;
100
	SdSource *sd_source;
101
	int ret;
102
103
	source = g_source_new (&sd_source_funcs, sizeof (SdSource));
104
	sd_source = (SdSource *)source;
105
106
	ret = sd_login_monitor_new (NULL, &sd_source->monitor);
107
	if (ret < 0)
108
		g_printerr ("Error getting login monitor: %d", ret);
109
	else {
110
		sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor);
111
		sd_source->pollfd.events = G_IO_IN;
112
		g_source_add_poll (source, &sd_source->pollfd);
113
	}
114
115
	return source;
116
}
117
#endif /* SESSION_TRACKING_SYSTEMD */
118
119
struct _NMSessionMonitor {
120
	GObject parent_instance;
121
122
	GKeyFile *database;
123
	GFileMonitor *database_monitor;
124
	time_t database_mtime;
125
	GHashTable *sessions_by_uid;
126
	GHashTable *sessions_by_user;
127
128
	GSource *sd_source;
129
};
130
131
struct _NMSessionMonitorClass {
132
	GObjectClass parent_class;
133
134
	void (*changed) (NMSessionMonitor *monitor);
135
};
136
137
138
enum {
139
	CHANGED_SIGNAL,
140
	LAST_SIGNAL,
141
};
142
static guint signals[LAST_SIGNAL] = {0};
143
144
G_DEFINE_TYPE (NMSessionMonitor, nm_session_monitor, G_TYPE_OBJECT);
145
146
/* ---------------------------------------------------------------------------------------------------- */
147
148
typedef struct {
149
	char *user;
150
	uid_t uid;
151
	gboolean local;
152
	gboolean active;
153
} Session;
154
155
static void
156
session_free (Session *s)
157
{
158
	g_free (s->user);
159
	memset (s, 0, sizeof (Session));
160
	g_free (s);
161
}
162
163
static gboolean
164
check_key (GKeyFile *keyfile, const char *group, const char *key, GError **error)
165
{
166
	if (g_key_file_has_key (keyfile, group, key, error))
167
		return TRUE;
168
169
	if (!error) {
170
		g_set_error (error,
171
			         NM_SESSION_MONITOR_ERROR,
172
			         NM_SESSION_MONITOR_ERROR_MALFORMED_DATABASE,
173
			         "ConsoleKit database " CKDB_PATH " group '%s' had no '%s' key",
174
			         group, key);
175
	}
176
	return FALSE;
177
}
178
179
static Session *
180
session_new (GKeyFile *keyfile, const char *group, GError **error)
181
{
182
	GError *local = NULL;
183
	Session *s;
184
	const char *uname = NULL;
185
186
	s = g_new0 (Session, 1);
187
	g_assert (s);
188
189
	s->uid = G_MAXUINT; /* paranoia */
190
	if (!check_key (keyfile, group, "uid", &local))
191
		goto error;
192
	s->uid = (uid_t) g_key_file_get_integer (keyfile, group, "uid", &local);
193
	if (local)
194
		goto error;
195
196
	if (!check_key (keyfile, group, "is_active", &local))
197
		goto error;
198
	s->active = g_key_file_get_boolean (keyfile, group, "is_active", &local);
199
	if (local)
200
		goto error;
201
202
	if (!check_key (keyfile, group, "is_local", &local))
203
		goto error;
204
	s->local = g_key_file_get_boolean (keyfile, group, "is_local", &local);
205
	if (local)
206
		goto error;
207
208
	if (!nm_session_uid_to_user (s->uid, &uname, error))
209
		return FALSE;
210
	s->user = g_strdup (uname);
211
212
	return s;
213
214
error:
215
	session_free (s);
216
	g_propagate_error (error, local);
217
	return NULL;
218
}
219
220
static void
221
session_merge (Session *src, Session *dest)
222
{
223
	g_return_if_fail (src != NULL);
224
	g_return_if_fail (dest != NULL);
225
226
	g_warn_if_fail (g_strcmp0 (src->user, dest->user) == 0);
227
	g_warn_if_fail (src->uid == dest->uid);
228
229
	dest->local = (dest->local || src->local);
230
	dest->active = (dest->active || src->active);
231
}
232
233
static void
234
free_database (NMSessionMonitor *self)
235
{
236
	if (self->database != NULL) {
237
		g_key_file_free (self->database);
238
		self->database = NULL;
239
	}
240
241
	g_hash_table_remove_all (self->sessions_by_uid);
242
	g_hash_table_remove_all (self->sessions_by_user);
243
}
244
245
static gboolean
246
reload_database (NMSessionMonitor *self, GError **error)
247
{
248
	struct stat statbuf;
249
	char **groups = NULL;
250
	gsize len = 0, i;
251
	Session *s;
252
253
	free_database (self);
254
255
	errno = 0;
256
	if (stat (CKDB_PATH, &statbuf) != 0) {
257
		g_set_error (error,
258
		             NM_SESSION_MONITOR_ERROR,
259
		             errno == ENOENT ? NM_SESSION_MONITOR_ERROR_NO_DATABASE : NM_SESSION_MONITOR_ERROR_IO_ERROR,
260
		             "Error statting file " CKDB_PATH ": %s",
261
		             strerror (errno));
262
		goto error;
263
	}
264
	self->database_mtime = statbuf.st_mtime;
265
266
	self->database = g_key_file_new ();
267
	if (!g_key_file_load_from_file (self->database, CKDB_PATH, G_KEY_FILE_NONE, error))
268
		goto error;
269
270
	groups = g_key_file_get_groups (self->database, &len);
271
	if (!groups) {
272
		g_set_error_literal (error,
273
		                     NM_SESSION_MONITOR_ERROR,
274
		                     NM_SESSION_MONITOR_ERROR_IO_ERROR,
275
		                     "Could not load groups from " CKDB_PATH "");
276
		goto error;
277
	}
278
279
	for (i = 0; i < len; i++) {
280
		Session *found;
281
282
		if (!g_str_has_prefix (groups[i], "Session "))
283
			continue;
284
285
		s = session_new (self->database, groups[i], error);
286
		if (!s)
287
			goto error;
288
289
		found = g_hash_table_lookup (self->sessions_by_user, (gpointer) s->user);
290
		if (found) {
291
			session_merge (s, found);
292
			session_free (s);
293
		} else {
294
			/* Entirely new user */
295
			g_hash_table_insert (self->sessions_by_user, (gpointer) s->user, s);
296
			g_hash_table_insert (self->sessions_by_uid, GUINT_TO_POINTER (s->uid), s);
297
		}
298
	}
299
300
	g_strfreev (groups);
301
	return TRUE;
302
303
error:
304
	if (groups)
305
		g_strfreev (groups);
306
	free_database (self);
307
	return FALSE;
308
}
309
310
static gboolean
311
ensure_database (NMSessionMonitor *self, GError **error)
312
{
313
	gboolean ret = FALSE;
314
315
	if (self->database != NULL) {
316
		struct stat statbuf;
317
318
		errno = 0;
319
		if (stat (CKDB_PATH, &statbuf) != 0) {
320
			g_set_error (error,
321
			             NM_SESSION_MONITOR_ERROR,
322
			             errno == ENOENT ? NM_SESSION_MONITOR_ERROR_NO_DATABASE : NM_SESSION_MONITOR_ERROR_IO_ERROR,
323
			             "Error statting file " CKDB_PATH " to check timestamp: %s",
324
			             strerror (errno));
325
			goto out;
326
		}
327
328
		if (statbuf.st_mtime == self->database_mtime) {
329
			ret = TRUE;
330
			goto out;
331
		}
332
	}
333
334
	ret = reload_database (self, error);
335
336
out:
337
	return ret;
338
}
339
340
static void
341
on_file_monitor_changed (GFileMonitor *    file_monitor,
342
                         GFile *           file,
343
                         GFile *           other_file,
344
                         GFileMonitorEvent event_type,
345
                         gpointer          user_data)
346
{
347
	NMSessionMonitor *self = NM_SESSION_MONITOR (user_data);
348
349
	/* throw away cache */
350
	free_database (self);
351
352
	g_signal_emit (self, signals[CHANGED_SIGNAL], 0);
353
}
354
355
#ifdef SESSION_TRACKING_SYSTEMD
356
static gboolean
357
sessions_changed (gpointer user_data)
358
{
359
	NMSessionMonitor *monitor = NM_SESSION_MONITOR (user_data);
360
361
	g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
362
	return TRUE;
363
}
364
#endif /* SESSION_TRACKING_SYSTEMD */
365
366
367
static void
368
nm_session_monitor_init (NMSessionMonitor *monitor)
369
{
370
	GError *error;
371
	GFile *file;
372
373
	monitor->sd_source = NULL;
374
	monitor->database = NULL;
375
	monitor->database_monitor = NULL;
376
	monitor->sessions_by_uid = NULL;
377
	monitor->sessions_by_user = NULL;
378
379
#ifdef SESSION_TRACKING_SYSTEMD
380
	if (LOGIND_RUNNING())
381
	{
382
		monitor->sd_source = sd_source_new ();
383
		g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL);
384
		g_source_attach (monitor->sd_source, NULL);
385
		return;
386
	}
387
	/* fall through */
388
#endif /* SESSION_TRACKING_SYSTEMD */
389
390
	error = NULL;
391
392
	/* Sessions-by-user is responsible for destroying the Session objects */
393
	monitor->sessions_by_user = g_hash_table_new_full (g_str_hash, g_str_equal,
394
			NULL, (GDestroyNotify) session_free);
395
	monitor->sessions_by_uid = g_hash_table_new (g_direct_hash, g_direct_equal);
396
397
398
	error = NULL;
399
	if (!ensure_database (monitor, &error)) {
400
		/* Ignore the first error if the CK database isn't found yet */
401
		if (g_error_matches (error,
402
		                     NM_SESSION_MONITOR_ERROR,
403
		                     NM_SESSION_MONITOR_ERROR_NO_DATABASE) == FALSE) {
404
			nm_log_err (LOGD_CORE, "Error loading " CKDB_PATH ": %s", error->message);
405
		}
406
		g_error_free (error);
407
	}
408
409
	error = NULL;
410
	file = g_file_new_for_path (CKDB_PATH);
411
	monitor->database_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
412
	g_object_unref (file);
413
	if (monitor->database_monitor == NULL) {
414
		nm_log_err (LOGD_CORE, "Error monitoring " CKDB_PATH ": %s", error->message);
415
		g_error_free (error);
416
	} else {
417
		g_signal_connect (monitor->database_monitor,
418
		                  "changed",
419
		                  G_CALLBACK (on_file_monitor_changed),
420
		                  monitor);
421
	}
422
}
423
424
static void
425
nm_session_monitor_finalize (GObject *object)
426
{
427
	NMSessionMonitor *monitor = NM_SESSION_MONITOR (object);
428
429
	if (monitor->sd_source != NULL) {
430
		g_source_destroy (monitor->sd_source);
431
		g_source_unref (monitor->sd_source);
432
	}
433
434
	if (monitor->database_monitor != NULL)
435
		g_object_unref (monitor->database_monitor);
436
437
	free_database (monitor);
438
439
	if (G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize != NULL)
440
		G_OBJECT_CLASS (nm_session_monitor_parent_class)->finalize (object);
441
}
442
443
static void
444
nm_session_monitor_class_init (NMSessionMonitorClass *klass)
445
{
446
	GObjectClass *gobject_class;
447
448
	gobject_class = G_OBJECT_CLASS (klass);
449
	gobject_class->finalize = nm_session_monitor_finalize;
450
451
	/**
452
	 * NMSessionMonitor::changed:
453
	 * @monitor: A #NMSessionMonitor
454
	 *
455
	 * Emitted when something changes.
456
	 */
457
	signals[CHANGED_SIGNAL] = g_signal_new (NM_SESSION_MONITOR_CHANGED,
458
	                                        NM_TYPE_SESSION_MONITOR,
459
	                                        G_SIGNAL_RUN_LAST,
460
	                                        G_STRUCT_OFFSET (NMSessionMonitorClass, changed),
461
	                                        NULL,                   /* accumulator      */
462
	                                        NULL,                   /* accumulator data */
463
	                                        g_cclosure_marshal_VOID__VOID,
464
	                                        G_TYPE_NONE,
465
	                                        0);
466
}
467
468
NMSessionMonitor *
469
nm_session_monitor_get (void)
470
{
471
	static NMSessionMonitor *singleton = NULL;
472
473
	if (singleton)
474
		return g_object_ref (singleton);
475
476
	singleton = NM_SESSION_MONITOR (g_object_new (NM_TYPE_SESSION_MONITOR, NULL));
477
	g_assert (singleton);
478
	return singleton;
479
}
480
481
gboolean
482
nm_session_monitor_user_has_session (NMSessionMonitor *monitor,
483
                                     const char *username,
484
                                     uid_t *out_uid,
485
                                     GError **error)
486
{
487
#ifdef SESSION_TRACKING_SYSTEMD
488
	if (LOGIND_RUNNING())
489
	{
490
		uid_t uid;
491
492
		if (!nm_session_user_to_uid (username, &uid, error))
493
			return FALSE;
494
495
		if (out_uid)
496
			*out_uid = uid;
497
498
		return nm_session_monitor_uid_has_session (monitor, uid, NULL, error);
499
	}
500
	/* fall through */
501
#endif /* SESSION_TRACKING_SYSTEMD */
502
503
	Session *s;
504
505
	if (!ensure_database (monitor, error))
506
		return FALSE;
507
508
	s = g_hash_table_lookup (monitor->sessions_by_user, (gpointer) username);
509
	if (!s) {
510
		g_set_error (error,
511
		             NM_SESSION_MONITOR_ERROR,
512
		             NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
513
		             "No session found for user '%s'",
514
		             username);
515
		return FALSE;
516
	}
517
518
	if (out_uid)
519
		*out_uid = s->uid;
520
	return TRUE;
521
}
522
523
gboolean
524
nm_session_monitor_user_active (NMSessionMonitor *monitor,
525
                                const char *username,
526
                                GError **error)
527
{
528
#ifdef SESSION_TRACKING_SYSTEMD
529
	if (LOGIND_RUNNING())
530
	{
531
		uid_t uid;
532
533
		if (!nm_session_user_to_uid (username, &uid, error))
534
			return FALSE;
535
536
		return nm_session_monitor_uid_active (monitor, uid, error);
537
	}
538
	/* fall through */
539
#endif
540
541
	Session *s;
542
543
	if (!ensure_database (monitor, error))
544
		return FALSE;
545
546
	s = g_hash_table_lookup (monitor->sessions_by_user, (gpointer) username);
547
	if (!s) {
548
		g_set_error (error,
549
		             NM_SESSION_MONITOR_ERROR,
550
		             NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
551
		             "No session found for user '%s'",
552
		             username);
553
		return FALSE;
554
	}
555
556
	return s->active;
557
}
558
559
gboolean
560
nm_session_monitor_uid_has_session (NMSessionMonitor *monitor,
561
                                    uid_t uid,
562
                                    const char **out_user,
563
                                    GError **error)
564
{
565
#ifdef SESSION_TRACKING_SYSTEMD
566
	if (LOGIND_RUNNING())
567
	{
568
		int ret;
569
570
		if (!nm_session_uid_to_user (uid, out_user, error))
571
			return FALSE;
572
573
		ret = sd_uid_get_sessions (uid, FALSE, NULL) > 0;
574
		if (ret < 0) {
575
			nm_log_warn (LOGD_CORE, "Failed to get systemd sessions for uid %d: %d",
576
						 uid, ret);
577
			return FALSE;
578
		}
579
		return ret > 0 ? TRUE : FALSE;
580
	}
581
	/* fall through */
582
#endif
583
584
	Session *s;
585
586
	if (!ensure_database (monitor, error))
587
		return FALSE;
588
589
	s = g_hash_table_lookup (monitor->sessions_by_uid, GUINT_TO_POINTER (uid));
590
	if (!s) {
591
		g_set_error (error,
592
		             NM_SESSION_MONITOR_ERROR,
593
		             NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
594
		             "No session found for uid %d",
595
		             uid);
596
		return FALSE;
597
	}
598
599
	if (out_user)
600
		*out_user = s->user;
601
	return TRUE;
602
}
603
604
gboolean
605
nm_session_monitor_uid_active (NMSessionMonitor *monitor,
606
                               uid_t uid,
607
                               GError **error)
608
{
609
#ifdef SESSION_TRACKING_SYSTEMD
610
	if (LOGIND_RUNNING())
611
	{
612
		int ret;
613
614
		ret = sd_uid_get_sessions (uid, TRUE, NULL) > 0;
615
		if (ret < 0) {
616
			nm_log_warn (LOGD_CORE, "Failed to get active systemd sessions for uid %d: %d",
617
						 uid, ret);
618
			return FALSE;
619
		}
620
		return ret > 0 ? TRUE : FALSE;
621
	}
622
	/* fall through */
623
#endif
624
625
	Session *s;
626
627
	if (!ensure_database (monitor, error))
628
		return FALSE;
629
630
	s = g_hash_table_lookup (monitor->sessions_by_uid, GUINT_TO_POINTER (uid));
631
	if (!s) {
632
		g_set_error (error,
633
		             NM_SESSION_MONITOR_ERROR,
634
		             NM_SESSION_MONITOR_ERROR_UNKNOWN_USER,
635
		             "No session found for uid '%d'",
636
		             uid);
637
		return FALSE;
638
	}
639
640
	return s->active;
641
}
(-)a/src/nm-session-monitor.h (-1 / +6 lines)
Lines 21-26 Link Here
21
#ifndef NM_SESSION_MONITOR_H
21
#ifndef NM_SESSION_MONITOR_H
22
#define NM_SESSION_MONITOR_H
22
#define NM_SESSION_MONITOR_H
23
23
24
#include <unistd.h>
24
#include <glib-object.h>
25
#include <glib-object.h>
25
26
26
G_BEGIN_DECLS
27
G_BEGIN_DECLS
Lines 34-39 G_BEGIN_DECLS Link Here
34
35
35
#define NM_SESSION_MONITOR_CHANGED "changed"
36
#define NM_SESSION_MONITOR_CHANGED "changed"
36
37
38
/* check if logind is running
39
 * thanks to: https://bugzilla.gnome.org/show_bug.cgi?id=696266
40
 */
41
#define LOGIND_RUNNING() (access("/run/systemd/seats/", F_OK) >= 0)
42
37
typedef struct _NMSessionMonitor         NMSessionMonitor;
43
typedef struct _NMSessionMonitor         NMSessionMonitor;
38
typedef struct _NMSessionMonitorClass    NMSessionMonitorClass;
44
typedef struct _NMSessionMonitorClass    NMSessionMonitorClass;
39
45
40
- 

Return to bug 468930