~ubuntu-branches/ubuntu/raring/gnome-session/raring

« back to all changes in this revision

Viewing changes to gnome-session/gsm-systemd.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2012-05-07 11:22:35 UTC
  • mfrom: (1.1.75) (2.2.14 sid)
  • Revision ID: package-import@ubuntu.com-20120507112235-z9pe25ur5d8zt4c6
Tags: 3.4.1-1ubuntu1
* Merge with Debian. Remaining changes:
 - debian/control.in:
   + gnome-session
     - Recommend nautilus and either unity, unity-2d or gnome-shell
     - Only suggest gnome-session-fallback (we don't want it to be installed
       by default)
     - Drop the Recommends on gnome-power-manager, the code gnome-session uses
       has moved to gnome-settings-daemon
   + gnome-session-fallback
     - Recommend cups-pk-helper for gnome-session-fallback so that
       System Settings>Printers works
 - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
    Moved registering gnome-session binary as a session manager to 
    gnome-session-bin package
 - debian/postinst, postrm:
    set the default lightdm session as ubuntu if none already set
 - don't install defaults.list (installed by desktop-file-utils in ubuntu):
    debian/gnome-session-common.dirs and gnome-session-common.install
 - add debian/gnome-session-common.gsettings-override:
   set ubuntu as the default session if nothing is provided
 - debian/55gnome-session_gnomerc:
    Use POSIX string substitutions (shell internal) instead of external
    basename and cut for startup speed.
 - debian/patches/20_hide_nodisplay.patch:
    Don't show applications in the Sessions properties dialog that have
    NoDisplay=true.
 - debian/patches/21_up_start_on_demand.patch:
    Don't call dkp_client_new() until actually needed. This blocks
    for some time whilst DK-Power is started, if it wasn't running already
    (which is the case during auto-login). This can delay the whole
    session from starting.
 - debian/patches/22_support_autostart_delay.patch:
    Bugzilla patch to support adding a delay to autostart apps, using
    a "X-GNOME-Autostart-Delay" key in the desktop file
 - debian/patches/50_ubuntu_sessions.patch:
    + Add Ubuntu & Ubuntu 2D sessions
    + Add GNOME Classic (Without Effects session). Use notify-osd for
      notifications, but don't add it to RequiredComponents since notify-osd
      doesn't have an autostart .desktop file
    + gnome-shell.desktop adds --session=gnome now that the "ubuntu" session
      is the default. Use TryExec to test if gnome-shell is installed.
 - debian/patches/51_remove_session_saving_from_gui.patch:
    add GNOME_SESSION_SAVE environment variable for people wanting to
    use the save session still, knowing that it can break your system
    if used unwisely (LP: #771896)
 - debian/patches/52_xdg_current_desktop.patch:
    Set XDG_CURRENT_DESKTOP inside gnome-session based on a
    new key 'DesktopName' in gnome-session .desktop files.
 - debian/patches/80_new_upstream_session_dialog.patch:
    Bugzilla patch to change the session dialog. (Deactivated, see bug 807503)
 - debian/patches/95_dbus_request_shutdown.patch:
    Add "RequestShutdown" and "RequestReboot" DBus methods to allow other
    applications to shutdown or reboot the machine via the session manager.
 - debian/patches/96_no_catch_sigsegv.patch:
    Don't register a handler for SIGSEGV. We want Apport to catch these
    crashes so that users can submit useful crash reports.
 - debian/patches/101_screen_lock_on_suspend.patch:
    Use the same logic as gnome-power-manager for deciding the "screen
    lock on suspend" policy. This restores the Jaunty behaviour rather
    than just using the screensaver settings, which is surprising for
    users.
    This patch is deactivated for now, we'll see with the new screensaver and
    screen locking experience what to do (not rebased on gsettings as well)
  - debian/patches/103_kill_the_fail_whale.patch:
    seems that the fail whale try to come back and resist from his removal
    refreshed the patch to ensure it's killed and won't come back ever ever
    again.
  - 104_dont_show_fallback_warning.patch:
    Disable GNOME Fallback warning. It doesn't really explain anything
    and assumes that there aren't people that want to run Fallback.
  - debian/patches/105_hide_session_startup_help.patch:
    Hide Help button on Startup Applications dialog, as it is broken
    and the help documentation hasn't been written for 3.x yet.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2011 Red Hat, Inc.
 
4
 *
 
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)
 
8
 * any later version.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 * 02111-1307, USA.
 
19
 *
 
20
 * Author: Matthias Clasen
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
#include "gsm-systemd.h"
 
25
 
 
26
#ifdef HAVE_SYSTEMD
 
27
 
 
28
#include <errno.h>
 
29
#include <string.h>
 
30
#include <stdlib.h>
 
31
#include <unistd.h>
 
32
#include <sys/types.h>
 
33
#include <pwd.h>
 
34
 
 
35
#include <polkit/polkit.h>
 
36
#include <systemd/sd-login.h>
 
37
#include <systemd/sd-daemon.h>
 
38
 
 
39
#include <glib.h>
 
40
#include <glib-object.h>
 
41
#include <glib/gi18n.h>
 
42
#include <gio/gio.h>
 
43
 
 
44
#include "gsm-marshal.h"
 
45
#include "gsm-system.h"
 
46
 
 
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"
 
52
 
 
53
struct _GsmSystemdPrivate
 
54
{
 
55
        GDBusProxy      *sd_proxy;
 
56
        gchar           *session_id;
 
57
        gchar           *session_path;
 
58
        PolkitAuthority *authority;
 
59
        PolkitSubject   *subject;
 
60
};
 
61
 
 
62
static void gsm_systemd_system_init (GsmSystemInterface *iface);
 
63
 
 
64
G_DEFINE_TYPE_WITH_CODE (GsmSystemd, gsm_systemd, G_TYPE_OBJECT,
 
65
                         G_IMPLEMENT_INTERFACE (GSM_TYPE_SYSTEM,
 
66
                                                gsm_systemd_system_init))
 
67
 
 
68
 
 
69
static void
 
70
gsm_systemd_finalize (GObject *object)
 
71
{
 
72
        GsmSystemd *systemd = GSM_SYSTEMD (object);
 
73
 
 
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);
 
79
 
 
80
        G_OBJECT_CLASS (gsm_systemd_parent_class)->finalize (object);
 
81
}
 
82
 
 
83
static void
 
84
gsm_systemd_class_init (GsmSystemdClass *manager_class)
 
85
{
 
86
        GObjectClass *object_class;
 
87
 
 
88
        object_class = G_OBJECT_CLASS (manager_class);
 
89
 
 
90
        object_class->finalize = gsm_systemd_finalize;
 
91
 
 
92
        g_type_class_add_private (manager_class, sizeof (GsmSystemdPrivate));
 
93
}
 
94
 
 
95
static void
 
96
gsm_systemd_init (GsmSystemd *manager)
 
97
{
 
98
        GError *error;
 
99
        GDBusConnection *bus;
 
100
        GVariant *res;
 
101
 
 
102
        manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager,
 
103
                                                     GSM_TYPE_SYSTEMD,
 
104
                                                     GsmSystemdPrivate);
 
105
 
 
106
        error = NULL;
 
107
 
 
108
        bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
 
109
        if (bus == NULL) {
 
110
                g_warning ("Failed to connect to system bus: %s",
 
111
                           error->message);
 
112
                g_error_free (error);
 
113
        } else {
 
114
                manager->priv->sd_proxy =
 
115
                        g_dbus_proxy_new_sync (bus,
 
116
                                               0,
 
117
                                               NULL,
 
118
                                               SD_NAME,
 
119
                                               SD_PATH,
 
120
                                               SD_INTERFACE,
 
121
                                               NULL,
 
122
                                               &error);
 
123
 
 
124
                if (manager->priv->sd_proxy == NULL) {
 
125
                        g_warning ("Failed to connect to systemd: %s",
 
126
                                   error->message);
 
127
                        g_error_free (error);
 
128
                }
 
129
 
 
130
                g_object_unref (bus);
 
131
        }
 
132
 
 
133
        manager->priv->authority = polkit_authority_get_sync (NULL, NULL);
 
134
        manager->priv->subject = polkit_unix_session_new_for_process_sync (getpid (), NULL, NULL);
 
135
 
 
136
        sd_pid_get_session (getpid (), &manager->priv->session_id);
 
137
 
 
138
        res = g_dbus_proxy_call_sync (manager->priv->sd_proxy,
 
139
                                      "GetSession",
 
140
                                      g_variant_new ("(s)", manager->priv->session_id),
 
141
                                      0,
 
142
                                      G_MAXINT,
 
143
                                      NULL,
 
144
                                      NULL);
 
145
        g_variant_get (res, "(o)", &manager->priv->session_path);
 
146
        g_variant_unref (res);
 
147
}
 
148
 
 
149
static void
 
150
emit_restart_complete (GsmSystemd *manager,
 
151
                       GError     *error)
 
152
{
 
153
        GError *call_error;
 
154
 
 
155
        call_error = NULL;
 
156
 
 
157
        if (error != NULL) {
 
158
                call_error = g_error_new_literal (GSM_SYSTEM_ERROR,
 
159
                                                  GSM_SYSTEM_ERROR_RESTARTING,
 
160
                                                  error->message);
 
161
        }
 
162
 
 
163
        g_signal_emit_by_name (G_OBJECT (manager),
 
164
                               "request_completed", call_error);
 
165
 
 
166
        if (call_error != NULL) {
 
167
                g_error_free (call_error);
 
168
        }
 
169
}
 
170
 
 
171
static void
 
172
emit_stop_complete (GsmSystemd *manager,
 
173
                    GError     *error)
 
174
{
 
175
        GError *call_error;
 
176
 
 
177
        call_error = NULL;
 
178
 
 
179
        if (error != NULL) {
 
180
                call_error = g_error_new_literal (GSM_SYSTEM_ERROR,
 
181
                                                  GSM_SYSTEM_ERROR_STOPPING,
 
182
                                                  error->message);
 
183
        }
 
184
 
 
185
        g_signal_emit_by_name (G_OBJECT (manager),
 
186
                               "request_completed", call_error);
 
187
 
 
188
        if (call_error != NULL) {
 
189
                g_error_free (call_error);
 
190
        }
 
191
}
 
192
 
 
193
static void
 
194
restart_done (GObject      *source,
 
195
              GAsyncResult *result,
 
196
              gpointer      user_data)
 
197
{
 
198
        GDBusProxy *proxy = G_DBUS_PROXY (source);
 
199
        GsmSystemd *manager = user_data;
 
200
        GError *error = NULL;
 
201
        GVariant *res;
 
202
 
 
203
        res = g_dbus_proxy_call_finish (proxy, result, &error);
 
204
 
 
205
        if (!res) {
 
206
                g_warning ("Unable to restart system: %s", error->message);
 
207
                emit_restart_complete (manager, error);
 
208
                g_error_free (error);
 
209
        } else {
 
210
                emit_restart_complete (manager, NULL);
 
211
                g_variant_unref (res);
 
212
        }
 
213
}
 
214
 
 
215
static void
 
216
gsm_systemd_attempt_restart (GsmSystem *system)
 
217
{
 
218
        GsmSystemd *manager = GSM_SYSTEMD (system);
 
219
 
 
220
        g_dbus_proxy_call (manager->priv->sd_proxy,
 
221
                           "Reboot",
 
222
                           g_variant_new ("(b)", TRUE),
 
223
                           0,
 
224
                           G_MAXINT,
 
225
                           NULL,
 
226
                           restart_done,
 
227
                           manager);
 
228
}
 
229
 
 
230
static void
 
231
stop_done (GObject      *source,
 
232
           GAsyncResult *result,
 
233
           gpointer      user_data)
 
234
{
 
235
        GDBusProxy *proxy = G_DBUS_PROXY (source);
 
236
        GsmSystemd *manager = user_data;
 
237
        GError *error = NULL;
 
238
        GVariant *res;
 
239
 
 
240
        res = g_dbus_proxy_call_finish (proxy, result, &error);
 
241
 
 
242
        if (!res) {
 
243
                g_warning ("Unable to stop system: %s", error->message);
 
244
                emit_stop_complete (manager, error);
 
245
                g_error_free (error);
 
246
        } else {
 
247
                emit_stop_complete (manager, NULL);
 
248
                g_variant_unref (res);
 
249
        }
 
250
}
 
251
 
 
252
static void
 
253
gsm_systemd_attempt_stop (GsmSystem *system)
 
254
{
 
255
        GsmSystemd *manager = GSM_SYSTEMD (system);
 
256
 
 
257
        g_dbus_proxy_call (manager->priv->sd_proxy,
 
258
                           "PowerOff",
 
259
                           g_variant_new ("(b)", TRUE),
 
260
                           0,
 
261
                           G_MAXINT,
 
262
                           NULL,
 
263
                           stop_done,
 
264
                           manager);
 
265
}
 
266
 
 
267
static void
 
268
gsm_systemd_set_session_idle (GsmSystem *system,
 
269
                              gboolean   is_idle)
 
270
{
 
271
        GsmSystemd *manager = GSM_SYSTEMD (system);
 
272
        GDBusConnection *bus;
 
273
 
 
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,
 
277
                                SD_NAME,
 
278
                                manager->priv->session_path,
 
279
                                SD_SESSION_INTERFACE,
 
280
                                "SetIdleHint",
 
281
                                g_variant_new ("(b)", is_idle),
 
282
                                G_VARIANT_TYPE_BOOLEAN,
 
283
                                0,
 
284
                                G_MAXINT,
 
285
                                NULL, NULL, NULL);
 
286
}
 
287
 
 
288
static gboolean
 
289
gsm_systemd_can_switch_user (GsmSystem *system)
 
290
{
 
291
        GsmSystemd *manager = GSM_SYSTEMD (system);
 
292
        gchar *seat;
 
293
        gint ret;
 
294
 
 
295
        sd_session_get_seat (manager->priv->session_id, &seat);
 
296
        ret = sd_seat_can_multi_session (seat);
 
297
        free (seat);
 
298
 
 
299
        return ret > 0;
 
300
}
 
301
 
 
302
static gboolean
 
303
gsm_systemd_can_restart (GsmSystem *system)
 
304
{
 
305
        GsmSystemd *manager = GSM_SYSTEMD (system);
 
306
        PolkitAuthorizationResult *res;
 
307
        gboolean can_restart;
 
308
 
 
309
        res = polkit_authority_check_authorization_sync (manager->priv->authority,
 
310
                                                         manager->priv->subject,
 
311
                                                         "org.freedesktop.login1.reboot",
 
312
                                                         NULL,
 
313
                                                         POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
 
314
                                                         NULL,
 
315
                                                         NULL);
 
316
        if (res == NULL) {
 
317
                return FALSE;
 
318
        }
 
319
 
 
320
        can_restart = polkit_authorization_result_get_is_authorized (res) ||
 
321
                      polkit_authorization_result_get_is_challenge (res);
 
322
 
 
323
        g_object_unref (res);
 
324
 
 
325
        return can_restart;
 
326
}
 
327
 
 
328
static gboolean
 
329
gsm_systemd_can_stop (GsmSystem *system)
 
330
{
 
331
        GsmSystemd *manager = GSM_SYSTEMD (system);
 
332
        PolkitAuthorizationResult *res;
 
333
        gboolean can_stop;
 
334
 
 
335
        res = polkit_authority_check_authorization_sync (manager->priv->authority,
 
336
                                                         manager->priv->subject,
 
337
                                                         "org.freedesktop.login1.power-off",
 
338
                                                         NULL,
 
339
                                                         POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
 
340
                                                         NULL,
 
341
                                                         NULL);
 
342
        if (res == NULL) {
 
343
                return FALSE;
 
344
        }
 
345
 
 
346
        can_stop = polkit_authorization_result_get_is_authorized (res) ||
 
347
                   polkit_authorization_result_get_is_challenge (res);
 
348
 
 
349
        g_object_unref (res);
 
350
 
 
351
        return can_stop;
 
352
}
 
353
 
 
354
static gboolean
 
355
gsm_systemd_is_login_session (GsmSystem *system)
 
356
{
 
357
        GsmSystemd *manager = GSM_SYSTEMD (system);
 
358
        int res;
 
359
        gboolean ret;
 
360
        gchar *service = NULL;
 
361
 
 
362
        ret = FALSE;
 
363
 
 
364
        res = sd_session_get_service (manager->priv->session_id, &service);
 
365
        if (res < 0) {
 
366
                g_warning ("could not get pam service: %s", strerror (-res));
 
367
                return FALSE;
 
368
        }
 
369
        ret = (g_strcmp0 (service, "gdm-welcome") == 0);
 
370
        free (service);
 
371
 
 
372
        return ret;
 
373
}
 
374
 
 
375
static void
 
376
gsm_systemd_system_init (GsmSystemInterface *iface)
 
377
{
 
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;
 
385
}
 
386
 
 
387
GsmSystemd *
 
388
gsm_systemd_new (void)
 
389
{
 
390
        GsmSystemd *manager;
 
391
 
 
392
        if (sd_booted () <= 0)
 
393
                return NULL;
 
394
 
 
395
        manager = g_object_new (GSM_TYPE_SYSTEMD, NULL);
 
396
 
 
397
        return manager;
 
398
}
 
399
 
 
400
#else
 
401
 
 
402
GsmSystemd *
 
403
gsm_systemd_new (void)
 
404
{
 
405
        return NULL;
 
406
}
 
407
 
 
408
#endif