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 281-291 AS_IF([! (echo "$with_session_tracking" | grep -q -E "^(systemd|consolekit|no)$" Link Here
281
	AC_MSG_ERROR([--with-session-tracking must be systemd/consolekit/no, not $with_session_tracking]))
281
	AC_MSG_ERROR([--with-session-tracking must be systemd/consolekit/no, not $with_session_tracking]))
282
# add conditionals and subtitutions
282
# add conditionals and subtitutions
283
AM_CONDITIONAL(SESSION_TRACKING_CK, test "$with_session_tracking" = "consolekit")
283
AM_CONDITIONAL(SESSION_TRACKING_CK, test "$with_session_tracking" = "consolekit")
284
AM_CONDITIONAL(SESSION_TRACKING_SYSTEMD, test "xwith_session_tracking" = "systemd")
284
AM_CONDITIONAL(SESSION_TRACKING_SYSTEMD, test "$with_session_tracking" = "systemd")
285
AM_CONDITIONAL(SESSION_TRACKING_NULL, test "$with_session_tracking" = "no")
285
if test "$with_session_tracking" = "systemd"; then
286
if test "$with_session_tracking" = "systemd"; then
286
	PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd-login])
287
	PKG_CHECK_MODULES(SYSTEMD_LOGIN, [libsystemd-login])
287
	AC_SUBST(SYSTEMD_LOGIN_CFLAGS)
288
	AC_SUBST(SYSTEMD_LOGIN_CFLAGS)
288
	AC_SUBST(SYSTEMD_LOGIN_LIBS)
289
	AC_SUBST(SYSTEMD_LOGIN_LIBS)
290
	AC_DEFINE([SESSION_TRACKING_SYSTEMD], 1, [Define to 1 if libsystemd-login is available])
289
fi
291
fi
290
if test "$with_session_tracking" = "consolekit"; then
292
if test "$with_session_tracking" = "consolekit"; then
291
	AC_SUBST(CKDB_PATH, /var/run/ConsoleKit/database)
293
	AC_SUBST(CKDB_PATH, /var/run/ConsoleKit/database)
(-)a/src/Makefile.am (-7 / +3 lines)
Lines 204-217 if WITH_CONCHECK Link Here
204
NetworkManager_SOURCES += nm-connectivity.c nm-connectivity.h
204
NetworkManager_SOURCES += nm-connectivity.c nm-connectivity.h
205
endif
205
endif
206
206
207
if SESSION_TRACKING_SYSTEMD
207
if SESSION_TRACKING_NULL
208
NetworkManager_SOURCES += nm-session-monitor-systemd.c
209
else
210
if SESSION_TRACKING_CK
211
NetworkManager_SOURCES += nm-session-monitor-ck.c
212
else
213
NetworkManager_SOURCES += nm-session-monitor-null.c
208
NetworkManager_SOURCES += nm-session-monitor-null.c
214
endif
209
else
210
NetworkManager_SOURCES += nm-session-monitor.c
215
endif
211
endif
216
212
217
if SUSPEND_RESUME_SYSTEMD
213
if SUSPEND_RESUME_SYSTEMD
(-)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