2
* Copyright (C) 2011 Red Hat, Inc.
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General
15
* Public License along with this library; if not, write to the
16
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17
* Boston, MA 02111-1307, USA.
19
* Author: Matthias Clasen
27
#include <glib/gstdio.h>
28
#include <systemd/sd-login.h>
31
#include <polkit/polkit.h>
32
#include "polkitbackendsessionmonitor.h"
35
* SECTION:polkitbackendsessionmonitor
36
* @title: PolkitBackendSessionMonitor
37
* @short_description: Monitor sessions
39
* The #PolkitBackendSessionMonitor class is a utility class to track and monitor sessions.
46
sd_login_monitor *monitor;
50
sd_source_prepare (GSource *source,
58
sd_source_check (GSource *source)
60
SdSource *sd_source = (SdSource *)source;
62
return sd_source->pollfd.revents != 0;
66
sd_source_dispatch (GSource *source,
71
SdSource *sd_source = (SdSource *)source;
74
g_warn_if_fail (callback != NULL);
76
ret = (*callback) (user_data);
78
sd_login_monitor_flush (sd_source->monitor);
84
sd_source_finalize (GSource *source)
86
SdSource *sd_source = (SdSource*)source;
88
sd_login_monitor_unref (sd_source->monitor);
91
static GSourceFuncs sd_source_funcs = {
105
source = g_source_new (&sd_source_funcs, sizeof (SdSource));
106
sd_source = (SdSource *)source;
108
if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 0)
110
g_printerr ("Error getting login monitor: %d", ret);
114
sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor);
115
sd_source->pollfd.events = G_IO_IN;
116
g_source_add_poll (source, &sd_source->pollfd);
122
struct _PolkitBackendSessionMonitor
124
GObject parent_instance;
126
GDBusConnection *system_bus;
131
struct _PolkitBackendSessionMonitorClass
133
GObjectClass parent_class;
135
void (*changed) (PolkitBackendSessionMonitor *monitor);
145
static guint signals[LAST_SIGNAL] = {0};
147
G_DEFINE_TYPE (PolkitBackendSessionMonitor, polkit_backend_session_monitor, G_TYPE_OBJECT);
149
/* ---------------------------------------------------------------------------------------------------- */
152
sessions_changed (gpointer user_data)
154
PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data);
156
g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0);
163
polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor)
168
monitor->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
169
if (monitor->system_bus == NULL)
171
g_printerr ("Error getting system bus: %s", error->message);
172
g_error_free (error);
175
monitor->sd_source = sd_source_new ();
176
g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL);
177
g_source_attach (monitor->sd_source, NULL);
181
polkit_backend_session_monitor_finalize (GObject *object)
183
PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (object);
185
if (monitor->system_bus != NULL)
186
g_object_unref (monitor->system_bus);
188
if (monitor->sd_source != NULL)
190
g_source_destroy (monitor->sd_source);
191
g_source_unref (monitor->sd_source);
194
if (G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize != NULL)
195
G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize (object);
199
polkit_backend_session_monitor_class_init (PolkitBackendSessionMonitorClass *klass)
201
GObjectClass *gobject_class;
203
gobject_class = G_OBJECT_CLASS (klass);
205
gobject_class->finalize = polkit_backend_session_monitor_finalize;
208
* PolkitBackendSessionMonitor::changed:
209
* @monitor: A #PolkitBackendSessionMonitor
211
* Emitted when something changes.
213
signals[CHANGED_SIGNAL] = g_signal_new ("changed",
214
POLKIT_BACKEND_TYPE_SESSION_MONITOR,
216
G_STRUCT_OFFSET (PolkitBackendSessionMonitorClass, changed),
217
NULL, /* accumulator */
218
NULL, /* accumulator data */
219
g_cclosure_marshal_VOID__VOID,
224
PolkitBackendSessionMonitor *
225
polkit_backend_session_monitor_new (void)
227
PolkitBackendSessionMonitor *monitor;
229
monitor = POLKIT_BACKEND_SESSION_MONITOR (g_object_new (POLKIT_BACKEND_TYPE_SESSION_MONITOR, NULL));
234
/* ---------------------------------------------------------------------------------------------------- */
237
polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monitor)
243
/* ---------------------------------------------------------------------------------------------------- */
246
* polkit_backend_session_monitor_get_user:
247
* @monitor: A #PolkitBackendSessionMonitor.
248
* @subject: A #PolkitSubject.
249
* @error: Return location for error.
251
* Gets the user corresponding to @subject or %NULL if no user exists.
253
* Returns: %NULL if @error is set otherwise a #PolkitUnixUser that should be freed with g_object_unref().
256
polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor *monitor,
257
PolkitSubject *subject,
265
if (POLKIT_IS_UNIX_PROCESS (subject))
267
uid = polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject));
268
if ((gint) uid == -1)
273
"Unix process subject does not have uid set");
276
ret = polkit_unix_user_new (uid);
278
else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
282
result = g_dbus_connection_call_sync (monitor->system_bus,
283
"org.freedesktop.DBus",
284
"/org/freedesktop/DBus",
285
"org.freedesktop.DBus",
286
"GetConnectionUnixUser",
287
g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))),
288
G_VARIANT_TYPE ("(u)"),
289
G_DBUS_CALL_FLAGS_NONE,
290
-1, /* timeout_msec */
291
NULL, /* GCancellable */
295
g_variant_get (result, "(u)", &uid);
296
g_variant_unref (result);
298
ret = polkit_unix_user_new (uid);
300
else if (POLKIT_IS_UNIX_SESSION (subject))
303
if (sd_session_get_uid (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject)), &uid) < 0)
308
"Error getting uid for session");
312
ret = polkit_unix_user_new (uid);
320
* polkit_backend_session_monitor_get_session_for_subject:
321
* @monitor: A #PolkitBackendSessionMonitor.
322
* @subject: A #PolkitSubject.
323
* @error: Return location for error.
325
* Gets the session corresponding to @subject or %NULL if no session exists.
327
* Returns: %NULL if @error is set otherwise a #PolkitUnixSession that should be freed with g_object_unref().
330
polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMonitor *monitor,
331
PolkitSubject *subject,
334
PolkitSubject *session;
338
if (POLKIT_IS_UNIX_PROCESS (subject))
343
pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject));
344
if (sd_pid_get_session (pid, &session_id) < 0)
347
session = polkit_unix_session_new (session_id);
350
else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
356
result = g_dbus_connection_call_sync (monitor->system_bus,
357
"org.freedesktop.DBus",
358
"/org/freedesktop/DBus",
359
"org.freedesktop.DBus",
360
"GetConnectionUnixProcessID",
361
g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))),
362
G_VARIANT_TYPE ("(u)"),
363
G_DBUS_CALL_FLAGS_NONE,
364
-1, /* timeout_msec */
365
NULL, /* GCancellable */
369
g_variant_get (result, "(u)", &pid);
370
g_variant_unref (result);
372
if (sd_pid_get_session (pid, &session_id) < 0)
375
session = polkit_unix_session_new (session_id);
382
POLKIT_ERROR_NOT_SUPPORTED,
383
"Cannot get user for subject of type %s",
384
g_type_name (G_TYPE_FROM_INSTANCE (subject)));
393
polkit_backend_session_monitor_is_session_local (PolkitBackendSessionMonitor *monitor,
394
PolkitSubject *session)
398
if (!sd_session_get_seat (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)), &seat))
409
polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor,
410
PolkitSubject *session)
412
return sd_session_is_active (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)));