1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2011 Red Hat, Inc.
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2, or (at your option)
10
* This program 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
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20
* Author: Matthias Clasen
24
#include "gsm-systemd.h"
32
#include <sys/types.h>
35
#include <polkit/polkit.h>
36
#include <systemd/sd-login.h>
37
#include <systemd/sd-daemon.h>
40
#include <glib-object.h>
41
#include <glib/gi18n.h>
44
#include "gsm-marshal.h"
45
#include "gsm-system.h"
47
#define SD_NAME "org.freedesktop.login1"
48
#define SD_PATH "/org/freedesktop/login1"
49
#define SD_INTERFACE "org.freedesktop.login1.Manager"
50
#define SD_SEAT_INTERFACE "org.freedesktop.login1.Seat"
51
#define SD_SESSION_INTERFACE "org.freedesktop.login1.Session"
53
struct _GsmSystemdPrivate
58
PolkitAuthority *authority;
59
PolkitSubject *subject;
62
static void gsm_systemd_system_init (GsmSystemInterface *iface);
64
G_DEFINE_TYPE_WITH_CODE (GsmSystemd, gsm_systemd, G_TYPE_OBJECT,
65
G_IMPLEMENT_INTERFACE (GSM_TYPE_SYSTEM,
66
gsm_systemd_system_init))
70
gsm_systemd_finalize (GObject *object)
72
GsmSystemd *systemd = GSM_SYSTEMD (object);
74
g_clear_object (&systemd->priv->sd_proxy);
75
g_clear_object (&systemd->priv->authority);
76
g_clear_object (&systemd->priv->subject);
77
g_free (systemd->priv->session_id);
78
g_free (systemd->priv->session_path);
80
G_OBJECT_CLASS (gsm_systemd_parent_class)->finalize (object);
84
gsm_systemd_class_init (GsmSystemdClass *manager_class)
86
GObjectClass *object_class;
88
object_class = G_OBJECT_CLASS (manager_class);
90
object_class->finalize = gsm_systemd_finalize;
92
g_type_class_add_private (manager_class, sizeof (GsmSystemdPrivate));
96
gsm_systemd_init (GsmSystemd *manager)
102
manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
108
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
110
g_warning ("Failed to connect to system bus: %s",
112
g_error_free (error);
114
manager->priv->sd_proxy =
115
g_dbus_proxy_new_sync (bus,
124
if (manager->priv->sd_proxy == NULL) {
125
g_warning ("Failed to connect to systemd: %s",
127
g_error_free (error);
130
g_object_unref (bus);
133
manager->priv->authority = polkit_authority_get_sync (NULL, NULL);
134
manager->priv->subject = polkit_unix_session_new_for_process_sync (getpid (), NULL, NULL);
136
sd_pid_get_session (getpid (), &manager->priv->session_id);
138
res = g_dbus_proxy_call_sync (manager->priv->sd_proxy,
140
g_variant_new ("(s)", manager->priv->session_id),
145
g_variant_get (res, "(o)", &manager->priv->session_path);
146
g_variant_unref (res);
150
emit_restart_complete (GsmSystemd *manager,
158
call_error = g_error_new_literal (GSM_SYSTEM_ERROR,
159
GSM_SYSTEM_ERROR_RESTARTING,
163
g_signal_emit_by_name (G_OBJECT (manager),
164
"request_completed", call_error);
166
if (call_error != NULL) {
167
g_error_free (call_error);
172
emit_stop_complete (GsmSystemd *manager,
180
call_error = g_error_new_literal (GSM_SYSTEM_ERROR,
181
GSM_SYSTEM_ERROR_STOPPING,
185
g_signal_emit_by_name (G_OBJECT (manager),
186
"request_completed", call_error);
188
if (call_error != NULL) {
189
g_error_free (call_error);
194
restart_done (GObject *source,
195
GAsyncResult *result,
198
GDBusProxy *proxy = G_DBUS_PROXY (source);
199
GsmSystemd *manager = user_data;
200
GError *error = NULL;
203
res = g_dbus_proxy_call_finish (proxy, result, &error);
206
g_warning ("Unable to restart system: %s", error->message);
207
emit_restart_complete (manager, error);
208
g_error_free (error);
210
emit_restart_complete (manager, NULL);
211
g_variant_unref (res);
216
gsm_systemd_attempt_restart (GsmSystem *system)
218
GsmSystemd *manager = GSM_SYSTEMD (system);
220
g_dbus_proxy_call (manager->priv->sd_proxy,
222
g_variant_new ("(b)", TRUE),
231
stop_done (GObject *source,
232
GAsyncResult *result,
235
GDBusProxy *proxy = G_DBUS_PROXY (source);
236
GsmSystemd *manager = user_data;
237
GError *error = NULL;
240
res = g_dbus_proxy_call_finish (proxy, result, &error);
243
g_warning ("Unable to stop system: %s", error->message);
244
emit_stop_complete (manager, error);
245
g_error_free (error);
247
emit_stop_complete (manager, NULL);
248
g_variant_unref (res);
253
gsm_systemd_attempt_stop (GsmSystem *system)
255
GsmSystemd *manager = GSM_SYSTEMD (system);
257
g_dbus_proxy_call (manager->priv->sd_proxy,
259
g_variant_new ("(b)", TRUE),
268
gsm_systemd_set_session_idle (GsmSystem *system,
271
GsmSystemd *manager = GSM_SYSTEMD (system);
272
GDBusConnection *bus;
274
g_debug ("Updating systemd idle status: %d", is_idle);
275
bus = g_dbus_proxy_get_connection (manager->priv->sd_proxy);
276
g_dbus_connection_call (bus,
278
manager->priv->session_path,
279
SD_SESSION_INTERFACE,
281
g_variant_new ("(b)", is_idle),
282
G_VARIANT_TYPE_BOOLEAN,
289
gsm_systemd_can_switch_user (GsmSystem *system)
291
GsmSystemd *manager = GSM_SYSTEMD (system);
295
sd_session_get_seat (manager->priv->session_id, &seat);
296
ret = sd_seat_can_multi_session (seat);
303
gsm_systemd_can_restart (GsmSystem *system)
305
GsmSystemd *manager = GSM_SYSTEMD (system);
306
PolkitAuthorizationResult *res;
307
gboolean can_restart;
309
res = polkit_authority_check_authorization_sync (manager->priv->authority,
310
manager->priv->subject,
311
"org.freedesktop.login1.reboot",
313
POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
320
can_restart = polkit_authorization_result_get_is_authorized (res) ||
321
polkit_authorization_result_get_is_challenge (res);
323
g_object_unref (res);
329
gsm_systemd_can_stop (GsmSystem *system)
331
GsmSystemd *manager = GSM_SYSTEMD (system);
332
PolkitAuthorizationResult *res;
335
res = polkit_authority_check_authorization_sync (manager->priv->authority,
336
manager->priv->subject,
337
"org.freedesktop.login1.power-off",
339
POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
346
can_stop = polkit_authorization_result_get_is_authorized (res) ||
347
polkit_authorization_result_get_is_challenge (res);
349
g_object_unref (res);
355
gsm_systemd_is_login_session (GsmSystem *system)
357
GsmSystemd *manager = GSM_SYSTEMD (system);
360
gchar *service = NULL;
364
res = sd_session_get_service (manager->priv->session_id, &service);
366
g_warning ("could not get pam service: %s", strerror (-res));
369
ret = (g_strcmp0 (service, "gdm-welcome") == 0);
376
gsm_systemd_system_init (GsmSystemInterface *iface)
378
iface->can_switch_user = gsm_systemd_can_switch_user;
379
iface->can_stop = gsm_systemd_can_stop;
380
iface->can_restart = gsm_systemd_can_restart;
381
iface->attempt_stop = gsm_systemd_attempt_stop;
382
iface->attempt_restart = gsm_systemd_attempt_restart;
383
iface->set_session_idle = gsm_systemd_set_session_idle;
384
iface->is_login_session = gsm_systemd_is_login_session;
388
gsm_systemd_new (void)
392
if (sd_booted () <= 0)
395
manager = g_object_new (GSM_TYPE_SYSTEMD, NULL);
403
gsm_systemd_new (void)