~ubuntu-branches/debian/stretch/lightdm/stretch

« back to all changes in this revision

Viewing changes to src/display.c

  • Committer: Package Import Robot
  • Author(s): Yves-Alexis Perez
  • Date: 2013-10-20 20:45:55 UTC
  • mfrom: (1.1.17)
  • Revision ID: package-import@ubuntu.com-20131020204555-0ht6bt0lw5bof9fn
Tags: 1.8.2-1
* New upstream release.
* debian/patches:
  - 01_set-default-path, 02_default-config, 05_debianize-pam-files
    refreshed.
  - 03_quit-plymouth disabled for now, to check if problem is really fixed
    upstream.
* debian/control:
  - rename liblightdm-qt-2-0 to liblightdm-qt-3-0 to match updated soname.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*-
2
 
 *
3
 
 * Copyright (C) 2010-2011 Robert Ancell.
4
 
 * Author: Robert Ancell <robert.ancell@canonical.com>
5
 
 *
6
 
 * This program is free software: you can redistribute it and/or modify it under
7
 
 * the terms of the GNU General Public License as published by the Free Software
8
 
 * Foundation, either version 3 of the License, or (at your option) any later
9
 
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
10
 
 * license.
11
 
 */
12
 
 
13
 
#include <config.h>
14
 
#include <stdlib.h>
15
 
#include <string.h>
16
 
#include <gio/gdesktopappinfo.h>
17
 
 
18
 
#include "display.h"
19
 
#include "configuration.h"
20
 
#include "ldm-marshal.h"
21
 
#include "greeter.h"
22
 
 
23
 
enum
24
 
{
25
 
    CREATE_SESSION,
26
 
    READY,
27
 
    SWITCH_TO_USER,
28
 
    SWITCH_TO_GUEST,
29
 
    GET_GUEST_USERNAME,
30
 
    DISPLAY_SERVER_READY,
31
 
    START_GREETER,
32
 
    START_SESSION,
33
 
    STOPPED,
34
 
    LAST_SIGNAL
35
 
};
36
 
static guint signals[LAST_SIGNAL] = { 0 };
37
 
 
38
 
struct DisplayPrivate
39
 
{
40
 
    /* Display server */
41
 
    DisplayServer *display_server;
42
 
 
43
 
    /* Greeter session */
44
 
    gchar *greeter_session;
45
 
 
46
 
    /* TRUE if the user list should be shown */
47
 
    gboolean greeter_hide_users;
48
 
 
49
 
    /* TRUE if a manual login option should be shown */
50
 
    gboolean greeter_show_manual_login;
51
 
 
52
 
    /* TRUE if a remote login option should be shown */
53
 
    gboolean greeter_show_remote_login;
54
 
 
55
 
    /* TRUE if the greeter is a lock screen */
56
 
    gboolean greeter_is_lock;
57
 
 
58
 
    /* Session requested to log into */
59
 
    SessionType user_session_type;
60
 
    gchar *user_session;
61
 
 
62
 
    /* Program to run sessions through */
63
 
    gchar *session_wrapper;
64
 
 
65
 
    /* TRUE if in a user session */
66
 
    gboolean in_user_session;
67
 
 
68
 
    /* TRUE if have got an X server / started a greeter */
69
 
    gboolean is_ready;
70
 
 
71
 
    /* Session process */
72
 
    Session *session;
73
 
 
74
 
    /* Communication link to greeter */
75
 
    Greeter *greeter;
76
 
 
77
 
    /* User that should be automatically logged in */
78
 
    gchar *autologin_user;
79
 
    gboolean autologin_guest;
80
 
    gint autologin_timeout;
81
 
 
82
 
    /* TRUE if start greeter if fail to login */
83
 
    gboolean start_greeter_if_fail;
84
 
 
85
 
    /* Hint to select user in greeter */
86
 
    gchar *select_user_hint;
87
 
    gboolean select_guest_hint;
88
 
    gboolean select_user_attempt_login;
89
 
 
90
 
    /* TRUE if allowed to log into guest account */
91
 
    gboolean allow_guest;
92
 
 
93
 
    /* TRUE if greeter is to show the guest account */
94
 
    gboolean greeter_allow_guest;
95
 
 
96
 
    /* TRUE if stopping the display (waiting for dispaly server, greeter and session to stop) */
97
 
    gboolean stopping;
98
 
 
99
 
    /* TRUE if stopped */
100
 
    gboolean stopped;
101
 
};
102
 
 
103
 
/* PAM services to use */
104
 
#define GREETER_SERVICE   "lightdm-greeter"
105
 
#define USER_SERVICE      "lightdm"
106
 
#define AUTOLOGIN_SERVICE "lightdm-autologin"
107
 
 
108
 
G_DEFINE_TYPE (Display, display, G_TYPE_OBJECT);
109
 
 
110
 
static void greeter_session_stopped_cb (Session *session, Display *display);
111
 
static void user_session_stopped_cb (Session *session, Display *display);
112
 
 
113
 
Display *
114
 
display_new (DisplayServer *display_server)
115
 
{
116
 
    Display *display;
117
 
 
118
 
    g_return_val_if_fail (display_server != NULL, NULL);
119
 
  
120
 
    display = g_object_new (DISPLAY_TYPE, NULL);
121
 
    display->priv->display_server = g_object_ref (display_server);
122
 
 
123
 
    return display;
124
 
}
125
 
 
126
 
DisplayServer *
127
 
display_get_display_server (Display *display)
128
 
{
129
 
    g_return_val_if_fail (display != NULL, NULL);
130
 
    return display->priv->display_server;
131
 
}
132
 
 
133
 
const gchar *
134
 
display_get_username (Display *display)
135
 
{
136
 
    g_return_val_if_fail (display != NULL, NULL);
137
 
 
138
 
    if (!display->priv->session || !display->priv->in_user_session)
139
 
        return NULL;
140
 
 
141
 
    return session_get_username (display->priv->session);
142
 
}
143
 
 
144
 
Session *
145
 
display_get_session (Display *display)
146
 
{
147
 
    g_return_val_if_fail (display != NULL, NULL);
148
 
    return display->priv->session;
149
 
}
150
 
 
151
 
void
152
 
display_set_greeter_session (Display *display, const gchar *greeter_session)
153
 
{
154
 
    g_return_if_fail (display != NULL);
155
 
    g_free (display->priv->greeter_session);
156
 
    display->priv->greeter_session = g_strdup (greeter_session);
157
 
}
158
 
 
159
 
void
160
 
display_set_session_wrapper (Display *display, const gchar *session_wrapper)
161
 
{
162
 
    g_return_if_fail (display != NULL);
163
 
    g_free (display->priv->session_wrapper);
164
 
    display->priv->session_wrapper = g_strdup (session_wrapper);
165
 
}
166
 
 
167
 
void
168
 
display_set_allow_guest (Display *display, gboolean allow_guest)
169
 
{
170
 
    g_return_if_fail (display != NULL);
171
 
    display->priv->allow_guest = allow_guest;
172
 
}
173
 
 
174
 
void
175
 
display_set_greeter_allow_guest (Display *display, gboolean greeter_allow_guest)
176
 
{
177
 
    g_return_if_fail (display != NULL);
178
 
    display->priv->greeter_allow_guest = greeter_allow_guest;
179
 
}
180
 
 
181
 
void
182
 
display_set_autologin_user (Display *display, const gchar *username, gboolean is_guest, gint timeout)
183
 
{
184
 
    g_return_if_fail (display != NULL);
185
 
    g_free (display->priv->autologin_user);
186
 
    display->priv->autologin_user = g_strdup (username);
187
 
    display->priv->autologin_guest = is_guest;
188
 
    display->priv->autologin_timeout = timeout;
189
 
}
190
 
 
191
 
void
192
 
display_set_select_user_hint (Display *display, const gchar *username, gboolean is_guest, gboolean attempt_login)
193
 
{
194
 
    g_return_if_fail (display != NULL);
195
 
    g_free (display->priv->select_user_hint);
196
 
    display->priv->select_user_hint = g_strdup (username);
197
 
    display->priv->select_guest_hint = is_guest;
198
 
    display->priv->select_user_attempt_login = attempt_login;
199
 
}
200
 
 
201
 
void
202
 
display_set_hide_users_hint (Display *display, gboolean hide_users)
203
 
{
204
 
    g_return_if_fail (display != NULL);
205
 
    display->priv->greeter_hide_users = hide_users;
206
 
}
207
 
 
208
 
void
209
 
display_set_show_manual_login_hint (Display *display, gboolean show_manual_login)
210
 
{
211
 
    g_return_if_fail (display != NULL);
212
 
    display->priv->greeter_show_manual_login = show_manual_login;
213
 
}
214
 
 
215
 
void
216
 
display_set_show_remote_login_hint (Display *display, gboolean show_remote_login)
217
 
{
218
 
    g_return_if_fail (display != NULL);
219
 
    display->priv->greeter_show_remote_login = show_remote_login;
220
 
}
221
 
 
222
 
void
223
 
display_set_lock_hint (Display *display, gboolean is_lock)
224
 
{
225
 
    g_return_if_fail (display != NULL);
226
 
    display->priv->greeter_is_lock = is_lock;
227
 
}
228
 
 
229
 
void
230
 
display_set_user_session (Display *display, SessionType type, const gchar *session_name)
231
 
{
232
 
    g_return_if_fail (display != NULL);
233
 
    g_free (display->priv->user_session);
234
 
    display->priv->user_session_type = type;
235
 
    display->priv->user_session = g_strdup (session_name);
236
 
}
237
 
 
238
 
static void
239
 
display_set_is_ready (Display *display)
240
 
{
241
 
    if (display->priv->is_ready)
242
 
        return;
243
 
 
244
 
    display->priv->is_ready = TRUE;
245
 
    g_signal_emit (display, signals[READY], 0);
246
 
}
247
 
 
248
 
static gboolean
249
 
switch_to_user (Display *display, User *user)
250
 
{
251
 
    gboolean result;
252
 
    g_signal_emit (display, signals[SWITCH_TO_USER], 0, user, &result);
253
 
    return result;
254
 
}
255
 
 
256
 
static gboolean
257
 
switch_to_guest (Display *display)
258
 
{
259
 
    gboolean result;
260
 
    g_signal_emit (display, signals[SWITCH_TO_GUEST], 0, &result);
261
 
    return result;
262
 
}
263
 
 
264
 
static gchar *
265
 
get_guest_username (Display *display)
266
 
{
267
 
    gchar *username;
268
 
    g_signal_emit (display, signals[GET_GUEST_USERNAME], 0, &username);
269
 
    return username;
270
 
}
271
 
 
272
 
static Session *
273
 
create_session (Display *display)
274
 
{
275
 
    Session *session;
276
 
 
277
 
    g_signal_emit (display, signals[CREATE_SESSION], 0, &session);
278
 
    if (!session)
279
 
        return NULL;
280
 
 
281
 
    /* Connect using the session bus */
282
 
    if (getuid () != 0)
283
 
    {
284
 
        if (g_getenv ("DBUS_SESSION_BUS_ADDRESS"))
285
 
            session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
286
 
        session_set_env (session, "LDM_BUS", "SESSION");
287
 
        if (g_getenv ("LD_PRELOAD"))
288
 
            session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
289
 
        if (g_getenv ("LD_LIBRARY_PATH"))
290
 
            session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
291
 
        if (g_getenv ("PATH"))
292
 
            session_set_env (session, "PATH", g_getenv ("PATH"));
293
 
    }
294
 
 
295
 
    /* Variables required for regression tests */
296
 
    if (g_getenv ("LIGHTDM_TEST_ROOT"))
297
 
    {
298
 
        session_set_env (session, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
299
 
        session_set_env (session, "DBUS_SYSTEM_BUS_ADDRESS", g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
300
 
        session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
301
 
        session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
302
 
        session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
303
 
        session_set_env (session, "GI_TYPELIB_PATH", g_getenv ("GI_TYPELIB_PATH"));
304
 
    }
305
 
 
306
 
    return session;
307
 
}
308
 
 
309
 
static void
310
 
destroy_session (Display *display)
311
 
{
312
 
    if (!display->priv->session)
313
 
        return;
314
 
 
315
 
    g_signal_handlers_disconnect_matched (display->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
316
 
    session_stop (display->priv->session);
317
 
    g_object_unref (display->priv->session);
318
 
    display->priv->session = NULL;
319
 
}
320
 
 
321
 
static void
322
 
greeter_authentication_complete_cb (Session *session, Display *display)
323
 
{
324
 
    gboolean result = FALSE;
325
 
 
326
 
    if (display->priv->stopping)
327
 
        return;
328
 
 
329
 
    if (session_get_is_authenticated (session))
330
 
    {
331
 
        g_debug ("Greeter authorized");
332
 
        g_signal_emit (display, signals[START_GREETER], 0, &result);
333
 
        result = !result;
334
 
    }
335
 
    else
336
 
        g_debug ("Greeter failed authentication");
337
 
 
338
 
    if (!result)
339
 
    {
340
 
        g_debug ("Greeter failed to start");
341
 
        display_stop (display);
342
 
    }
343
 
}
344
 
 
345
 
static void
346
 
greeter_connected_cb (Greeter *greeter, Display *display)
347
 
{
348
 
    // FIXME: Should wait for greeter to signal completely ready if it supports it
349
 
    g_debug ("Greeter connected, display is ready");
350
 
    display_set_is_ready (display);
351
 
}
352
 
 
353
 
static Session *
354
 
greeter_start_authentication_cb (Greeter *greeter, const gchar *username, Display *display)
355
 
{
356
 
    return create_session (display);
357
 
}
358
 
 
359
 
static gboolean
360
 
greeter_start_session_cb (Greeter *greeter, SessionType type, const gchar *session_name, Display *display)
361
 
{
362
 
    /* If no session requested, use the previous one */
363
 
    if (!session_name && !greeter_get_guest_authenticated (greeter))
364
 
    {
365
 
        User *user;
366
 
 
367
 
        user = session_get_user (greeter_get_authentication_session (greeter));
368
 
        type = SESSION_TYPE_LOCAL;
369
 
        session_name = user_get_xsession (user);
370
 
    }
371
 
 
372
 
    /* If a session was requested, override the default */
373
 
    if (session_name)
374
 
    {
375
 
        g_debug ("Using session %s", session_name);
376
 
        display_set_user_session (display, type, session_name);
377
 
    }
378
 
 
379
 
    /* Stop this display if that session already exists and can switch to it */
380
 
    if (greeter_get_guest_authenticated (greeter))
381
 
    {
382
 
        if (switch_to_guest (display))
383
 
            return TRUE;
384
 
 
385
 
        /* Set to login as guest */
386
 
        display_set_autologin_user (display, NULL, TRUE, 0);
387
 
    }
388
 
    else
389
 
    {
390
 
        if (switch_to_user (display, session_get_user (greeter_get_authentication_session (display->priv->greeter))))
391
 
            return TRUE;
392
 
    }
393
 
 
394
 
    /* Stop the greeter, the session will start when the greeter has quit */
395
 
    g_debug ("Stopping greeter");
396
 
    session_stop (display->priv->session);
397
 
 
398
 
    return TRUE;
399
 
}
400
 
 
401
 
static gboolean
402
 
start_greeter (Display *display)
403
 
{
404
 
    gchar *greeter_user;
405
 
    gboolean result;
406
 
 
407
 
    destroy_session (display);
408
 
    display->priv->session = create_session (display);
409
 
    session_set_class (display->priv->session, XDG_SESSION_CLASS_GREETER);
410
 
    g_signal_connect (display->priv->session, "authentication-complete", G_CALLBACK (greeter_authentication_complete_cb), display);
411
 
 
412
 
    /* Make communication link to greeter that will run on this session */
413
 
    display->priv->greeter = greeter_new (display->priv->session, USER_SERVICE, AUTOLOGIN_SERVICE);
414
 
    g_signal_connect (G_OBJECT (display->priv->greeter), "connected", G_CALLBACK (greeter_connected_cb), display);
415
 
    g_signal_connect (G_OBJECT (display->priv->greeter), "start-authentication", G_CALLBACK (greeter_start_authentication_cb), display);
416
 
    g_signal_connect (G_OBJECT (display->priv->greeter), "start-session", G_CALLBACK (greeter_start_session_cb), display);
417
 
    if (display->priv->autologin_timeout)
418
 
    {
419
 
        gchar *value = g_strdup_printf ("%d", display->priv->autologin_timeout);
420
 
        greeter_set_hint (display->priv->greeter, "autologin-timeout", value);
421
 
        g_free (value);
422
 
        if (display->priv->autologin_user)
423
 
            greeter_set_hint (display->priv->greeter, "autologin-user", display->priv->autologin_user);
424
 
        else if (display->priv->autologin_guest)
425
 
            greeter_set_hint (display->priv->greeter, "autologin-guest", "true");
426
 
    }
427
 
    if (display->priv->select_user_hint)
428
 
        greeter_set_hint (display->priv->greeter, "select-user", display->priv->select_user_hint);
429
 
    else if (display->priv->select_guest_hint)
430
 
        greeter_set_hint (display->priv->greeter, "select-guest", "true");
431
 
    greeter_set_hint (display->priv->greeter, "default-session", display->priv->user_session);
432
 
    greeter_set_allow_guest (display->priv->greeter, display->priv->allow_guest);
433
 
    greeter_set_hint (display->priv->greeter, "has-guest-account", (display->priv->allow_guest && display->priv->greeter_allow_guest) ? "true" : "false");
434
 
    greeter_set_hint (display->priv->greeter, "hide-users", display->priv->greeter_hide_users ? "true" : "false");
435
 
    greeter_set_hint (display->priv->greeter, "show-manual-login", display->priv->greeter_show_manual_login ? "true" : "false");
436
 
    greeter_set_hint (display->priv->greeter, "show-remote-login", display->priv->greeter_show_remote_login ? "true" : "false");
437
 
    if (display->priv->greeter_is_lock)
438
 
        greeter_set_hint (display->priv->greeter, "lock-screen", "true");
439
 
 
440
 
    /* Run greeter as unprivileged user */
441
 
    if (getuid () != 0)
442
 
    {
443
 
        User *user;
444
 
        user = accounts_get_current_user ();
445
 
        greeter_user = g_strdup (user_get_name (user));
446
 
        g_object_unref (user);
447
 
    }
448
 
    else
449
 
    {
450
 
        greeter_user = config_get_string (config_get_instance (), "LightDM", "greeter-user");
451
 
        if (!greeter_user)
452
 
        {
453
 
            g_warning ("Greeter must not be run as root");
454
 
            display_stop (display);
455
 
            return FALSE;
456
 
        }
457
 
    }
458
 
 
459
 
    g_signal_connect_after (display->priv->session, "stopped", G_CALLBACK (greeter_session_stopped_cb), display);
460
 
    result = greeter_start (display->priv->greeter, GREETER_SERVICE, greeter_user);
461
 
    g_free (greeter_user);
462
 
 
463
 
    if (!result)
464
 
        display_stop (display);
465
 
 
466
 
    return result;
467
 
}
468
 
 
469
 
static void
470
 
autologin_authentication_complete_cb (Session *session, Display *display)
471
 
{
472
 
    gboolean result = FALSE;
473
 
 
474
 
    if (display->priv->stopping)
475
 
        return;
476
 
 
477
 
    if (session_get_is_authenticated (session))
478
 
    {
479
 
        const gchar *session_name;
480
 
 
481
 
        g_debug ("Autologin user %s authorized", session_get_username (session));
482
 
 
483
 
        session_name = user_get_xsession (session_get_user (session));
484
 
        if (session_name)
485
 
        {
486
 
            g_debug ("Autologin using session %s", session_name);
487
 
            display_set_user_session (display, SESSION_TYPE_LOCAL, session_name);
488
 
        }
489
 
 
490
 
        g_signal_emit (display, signals[START_SESSION], 0, &result);
491
 
        result = !result;
492
 
    }
493
 
    else
494
 
        g_debug ("Autologin failed authentication");
495
 
 
496
 
    if (!result)
497
 
    {
498
 
        if (display->priv->start_greeter_if_fail)
499
 
            start_greeter (display);
500
 
        else
501
 
            display_stop (display);
502
 
    }
503
 
}
504
 
 
505
 
static gboolean
506
 
autologin (Display *display, const gchar *username, const gchar *service, gboolean start_greeter_if_fail, gboolean is_guest)
507
 
{
508
 
    display->priv->start_greeter_if_fail = start_greeter_if_fail;
509
 
 
510
 
    display->priv->in_user_session = TRUE;
511
 
    destroy_session (display);
512
 
    display->priv->session = create_session (display);
513
 
    g_signal_connect (display->priv->session, "authentication-complete", G_CALLBACK (autologin_authentication_complete_cb), display);
514
 
    g_signal_connect_after (display->priv->session, "stopped", G_CALLBACK (user_session_stopped_cb), display);
515
 
    return session_start (display->priv->session, service, username, TRUE, FALSE, is_guest);
516
 
}
517
 
 
518
 
static gboolean
519
 
autologin_guest (Display *display, const gchar *service, gboolean start_greeter_if_fail)
520
 
{
521
 
    gchar *username;
522
 
    gboolean result;
523
 
 
524
 
    username = get_guest_username (display);
525
 
    if (!username)
526
 
    {
527
 
        g_debug ("Can't autologin guest, no guest account");
528
 
        return FALSE;
529
 
    }
530
 
 
531
 
    result = autologin (display, username, service, start_greeter_if_fail, TRUE);
532
 
    g_free (username);
533
 
 
534
 
    return result;
535
 
}
536
 
 
537
 
static gchar **
538
 
get_session_command (const gchar *filename, const gchar *session_wrapper)
539
 
{
540
 
    GKeyFile *session_desktop_file;
541
 
    gboolean result;
542
 
    int argc;
543
 
    gchar *command = NULL, **argv, *path;
544
 
    GError *error = NULL;
545
 
 
546
 
    /* Read the command from the .desktop file */
547
 
    session_desktop_file = g_key_file_new ();
548
 
    result = g_key_file_load_from_file (session_desktop_file, filename, G_KEY_FILE_NONE, &error);
549
 
    if (error)
550
 
        g_debug ("Failed to load session file %s: %s", filename, error->message);
551
 
    g_clear_error (&error);
552
 
    if (result)
553
 
    {
554
 
        command = g_key_file_get_string (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL);
555
 
        if (!command)
556
 
            g_debug ("No command in session file %s", filename);
557
 
    }
558
 
    g_key_file_free (session_desktop_file);
559
 
 
560
 
    if (!command)
561
 
        return NULL;
562
 
 
563
 
    /* If configured, run sessions through a wrapper */
564
 
    if (session_wrapper)
565
 
    {
566
 
        argv = g_malloc (sizeof (gchar *) * 3);
567
 
        path = g_find_program_in_path (session_wrapper);
568
 
        argv[0] = path ? path : g_strdup (session_wrapper);
569
 
        argv[1] = command;
570
 
        argv[2] = NULL;
571
 
        return argv;
572
 
    }
573
 
 
574
 
    /* Split command into an array listing and make command absolute */
575
 
    result = g_shell_parse_argv (command, &argc, &argv, &error);
576
 
    if (error)
577
 
        g_debug ("Invalid session command '%s': %s", command, error->message);
578
 
    g_clear_error (&error);
579
 
    g_free (command);
580
 
    if (!result)
581
 
        return NULL;
582
 
    path = g_find_program_in_path (argv[0]);
583
 
    if (path)
584
 
    {
585
 
        g_free (argv[0]);
586
 
        argv[0] = path;
587
 
    }
588
 
  
589
 
    return argv;
590
 
}
591
 
 
592
 
static void
593
 
greeter_session_stopped_cb (Session *session, Display *display)
594
 
{
595
 
    gboolean result = FALSE;
596
 
 
597
 
    g_debug ("Greeter quit");
598
 
 
599
 
    destroy_session (display);
600
 
 
601
 
    if (display->priv->stopping)
602
 
    {
603
 
        display_stop (display);
604
 
        return;
605
 
    }
606
 
 
607
 
    if (display_server_get_is_stopped (display->priv->display_server))
608
 
        return;
609
 
 
610
 
    /* Start the session for the authenticated user */
611
 
    if (greeter_get_start_session (display->priv->greeter))
612
 
    {
613
 
        /* If guest, then start a new autologin guest session (so can setup account) */
614
 
        if (greeter_get_guest_authenticated (display->priv->greeter))
615
 
            result = autologin_guest (display, AUTOLOGIN_SERVICE, FALSE);
616
 
        /* Otherwise, use the session the greeter has authenticated */
617
 
        else
618
 
        {
619
 
            destroy_session (display);
620
 
            display->priv->session = g_object_ref (greeter_get_authentication_session (display->priv->greeter));
621
 
            g_signal_connect_after (display->priv->session, "stopped", G_CALLBACK (user_session_stopped_cb), display);
622
 
            display->priv->in_user_session = TRUE;
623
 
            g_signal_emit (display, signals[START_SESSION], 0, &result);
624
 
            result = !result;
625
 
        }
626
 
    }
627
 
 
628
 
    /* Destroy the greeter */
629
 
    g_signal_handlers_disconnect_matched (display->priv->greeter, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
630
 
    g_object_unref (display->priv->greeter);
631
 
    display->priv->greeter = NULL;
632
 
 
633
 
    if (!result)
634
 
    {
635
 
        g_debug ("Failed to start greeter");
636
 
        display_stop (display);
637
 
    }
638
 
}
639
 
 
640
 
static gboolean
641
 
display_start_greeter (Display *display)
642
 
{
643
 
    gchar *log_dir, *filename, *log_filename, *sessions_dir, *path;
644
 
    gchar **argv;
645
 
 
646
 
    /* Log the output of the greeter to a system location */
647
 
    log_dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
648
 
    filename = g_strdup_printf ("%s-greeter.log", display_server_get_name (display->priv->display_server));
649
 
    log_filename = g_build_filename (log_dir, filename, NULL);
650
 
    g_free (log_dir);
651
 
    g_free (filename);
652
 
    g_debug ("Logging to %s", log_filename);
653
 
    session_set_log_file (display->priv->session, log_filename);
654
 
    g_free (log_filename);
655
 
 
656
 
    /* Load the greeter session information */
657
 
    sessions_dir = config_get_string (config_get_instance (), "LightDM", "xgreeters-directory");
658
 
    filename = g_strdup_printf ("%s.desktop", display->priv->greeter_session);
659
 
    path = g_build_filename (sessions_dir, filename, NULL);
660
 
    g_free (sessions_dir);
661
 
    g_free (filename);
662
 
    argv = get_session_command (path, NULL);
663
 
    g_free (path);
664
 
    if (!argv)
665
 
        return TRUE;
666
 
 
667
 
    session_run (display->priv->session, argv);
668
 
 
669
 
    return FALSE;
670
 
}
671
 
 
672
 
static void
673
 
user_session_stopped_cb (Session *session, Display *display)
674
 
{
675
 
    g_debug ("User session quit");
676
 
 
677
 
    destroy_session (display);
678
 
 
679
 
    /* This display has ended */
680
 
    display_stop (display);
681
 
}
682
 
 
683
 
static void
684
 
prepend_argv (gchar ***argv, const gchar *value)
685
 
{
686
 
    gchar **old_argv, **new_argv;
687
 
    gint i;
688
 
 
689
 
    old_argv = *argv;
690
 
    new_argv = g_malloc (sizeof (gchar *) * (g_strv_length (*argv) + 2));
691
 
    new_argv[0] = g_strdup (value);
692
 
    for (i = 0; old_argv[i]; i++)
693
 
        new_argv[i + 1] = old_argv[i];
694
 
    new_argv[i + 1] = NULL;
695
 
 
696
 
    g_free (*argv);
697
 
    *argv = new_argv;
698
 
}
699
 
 
700
 
static gboolean
701
 
display_start_session (Display *display)
702
 
{
703
 
    User *user;
704
 
    gchar *filename, *sessions_dir, *path;
705
 
    gchar **argv;
706
 
    gboolean disable_guest_wrapper;
707
 
 
708
 
    user = session_get_user (display->priv->session);
709
 
 
710
 
    /* Find the command to run for the selected session */
711
 
    if (display->priv->user_session_type == SESSION_TYPE_LOCAL)
712
 
    {
713
 
        sessions_dir = config_get_string (config_get_instance (), "LightDM", "xsessions-directory");
714
 
 
715
 
        /* Store this session name so we automatically use it next time */
716
 
        user_set_xsession (user, display->priv->user_session);
717
 
    }
718
 
    else
719
 
        sessions_dir = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory");
720
 
    filename = g_strdup_printf ("%s.desktop", display->priv->user_session);
721
 
    path = g_build_filename (sessions_dir, filename, NULL);
722
 
    g_free (sessions_dir);
723
 
    g_free (filename);
724
 
    argv = get_session_command (path, display->priv->session_wrapper);
725
 
    g_free (path);
726
 
    if (!argv)
727
 
        return TRUE;
728
 
  
729
 
    session_set_env (display->priv->session, "DESKTOP_SESSION", display->priv->user_session); // FIXME: Apparently deprecated?
730
 
    session_set_env (display->priv->session, "GDMSESSION", display->priv->user_session); // FIXME: Not cross-desktop
731
 
 
732
 
    /* Run a guest session through the wrapper covered by MAC */
733
 
    disable_guest_wrapper = config_get_boolean (config_get_instance (), "LightDM", "disable-guest-wrapper");
734
 
    if (display->priv->autologin_guest && !disable_guest_wrapper)
735
 
    {
736
 
        gchar *wrapper = g_build_filename (PKGLIBEXEC_DIR, "lightdm-guest-session-wrapper", NULL);
737
 
        g_debug ("Running guest session through wrapper: %s", wrapper);
738
 
        prepend_argv (&argv, wrapper);
739
 
        g_free (wrapper);
740
 
    }
741
 
 
742
 
    g_debug ("Starting session %s as user %s", display->priv->user_session, session_get_username (display->priv->session));
743
 
 
744
 
    session_run (display->priv->session, argv);
745
 
    g_strfreev (argv);
746
 
 
747
 
    // FIXME: Wait for session to indicate it is ready (maybe)
748
 
    display_set_is_ready (display);
749
 
 
750
 
    return FALSE;
751
 
}
752
 
 
753
 
static void
754
 
display_server_stopped_cb (DisplayServer *server, Display *display)
755
 
{
756
 
    g_debug ("Display server stopped");
757
 
 
758
 
    /* Stop this display, it will be restarted by the seat if necessary */
759
 
    display_stop (display);
760
 
}
761
 
 
762
 
static void
763
 
display_server_ready_cb (DisplayServer *display_server, Display *display)
764
 
{
765
 
    gboolean result = FALSE;
766
 
 
767
 
    g_signal_emit (display, signals[DISPLAY_SERVER_READY], 0, &result);
768
 
    if (!result)
769
 
    {
770
 
        display_stop (display);
771
 
        return;
772
 
    }
773
 
 
774
 
    /* Don't run any sessions on local terminals */
775
 
    if (!display_server_get_start_local_sessions (display_server))
776
 
        return;
777
 
 
778
 
    /* Automatically start requested user session */
779
 
    result = FALSE;
780
 
    if (display->priv->autologin_timeout == 0 && display->priv->autologin_guest)
781
 
    {
782
 
        g_debug ("Automatically logging in as guest");
783
 
        result = autologin_guest (display, AUTOLOGIN_SERVICE, TRUE);
784
 
    }
785
 
    else if (display->priv->autologin_timeout == 0 && display->priv->autologin_user)
786
 
    {
787
 
        g_debug ("Automatically logging in user %s", display->priv->autologin_user);
788
 
        result = autologin (display, display->priv->autologin_user, AUTOLOGIN_SERVICE, TRUE, FALSE);
789
 
    }
790
 
    else if (display->priv->select_user_hint && display->priv->select_user_attempt_login)
791
 
    {
792
 
        g_debug ("Logging in user %s", display->priv->select_user_hint);
793
 
        result = autologin (display, display->priv->select_user_hint, USER_SERVICE, TRUE, FALSE);
794
 
    }
795
 
 
796
 
    /* If no session started, start a greeter */
797
 
    if (!result)
798
 
    {
799
 
        g_debug ("Starting greeter");      
800
 
        result = start_greeter (display);
801
 
    }
802
 
 
803
 
    /* If nothing started, then the display can't work */
804
 
    if (!result)
805
 
        display_stop (display);
806
 
}
807
 
 
808
 
gboolean
809
 
display_start (Display *display)
810
 
{
811
 
    g_return_val_if_fail (display != NULL, FALSE);
812
 
 
813
 
    g_signal_connect (G_OBJECT (display->priv->display_server), "ready", G_CALLBACK (display_server_ready_cb), display);
814
 
    g_signal_connect (G_OBJECT (display->priv->display_server), "stopped", G_CALLBACK (display_server_stopped_cb), display);
815
 
 
816
 
    if (!display_server_start (display->priv->display_server))
817
 
        return FALSE;
818
 
 
819
 
    return TRUE;
820
 
}
821
 
 
822
 
gboolean
823
 
display_get_is_ready (Display *display)
824
 
{
825
 
    g_return_val_if_fail (display != NULL, FALSE);
826
 
 
827
 
    return display->priv->is_ready;
828
 
}
829
 
 
830
 
void
831
 
display_lock (Display *display)
832
 
{
833
 
    g_return_if_fail (display != NULL);
834
 
 
835
 
    if (!display->priv->session)
836
 
        return;
837
 
 
838
 
    g_debug ("Locking display");
839
 
 
840
 
    session_lock (display->priv->session);
841
 
}
842
 
 
843
 
void
844
 
display_unlock (Display *display)
845
 
{
846
 
    g_return_if_fail (display != NULL);
847
 
 
848
 
    if (!display->priv->session)
849
 
        return;
850
 
 
851
 
    g_debug ("Unlocking display");
852
 
 
853
 
    session_unlock (display->priv->session);
854
 
}
855
 
 
856
 
void
857
 
display_stop (Display *display)
858
 
{
859
 
    g_return_if_fail (display != NULL);
860
 
 
861
 
    if (display->priv->stopped)
862
 
        return;
863
 
 
864
 
    if (!display->priv->stopping)
865
 
    {
866
 
        g_debug ("Stopping display");
867
 
        display->priv->stopping = TRUE;
868
 
    }
869
 
 
870
 
    /* Stop the session first */
871
 
    if (display->priv->session)
872
 
    {
873
 
        session_stop (display->priv->session);
874
 
        return;
875
 
    }
876
 
 
877
 
    /* Stop the display server after that */
878
 
    if (!display_server_get_is_stopped (display->priv->display_server))
879
 
    {
880
 
        display_server_stop (display->priv->display_server);
881
 
        return;
882
 
    }
883
 
 
884
 
    display->priv->stopped = TRUE;
885
 
    g_signal_emit (display, signals[STOPPED], 0);
886
 
}
887
 
 
888
 
gboolean
889
 
display_get_is_stopped (Display *display)
890
 
{
891
 
    g_return_val_if_fail (display != NULL, FALSE);
892
 
    return display->priv->stopped;
893
 
}
894
 
 
895
 
static gboolean
896
 
display_real_switch_to_user (Display *display, User *user)
897
 
{
898
 
    return FALSE;
899
 
}
900
 
 
901
 
static gboolean
902
 
display_real_switch_to_guest (Display *display)
903
 
{
904
 
    return FALSE;
905
 
}
906
 
 
907
 
static gchar *
908
 
display_real_get_guest_username (Display *display)
909
 
{
910
 
    return NULL;
911
 
}
912
 
 
913
 
static void
914
 
display_init (Display *display)
915
 
{
916
 
    display->priv = G_TYPE_INSTANCE_GET_PRIVATE (display, DISPLAY_TYPE, DisplayPrivate);
917
 
}
918
 
 
919
 
static void
920
 
display_finalize (GObject *object)
921
 
{
922
 
    Display *self;
923
 
 
924
 
    self = DISPLAY (object);
925
 
 
926
 
    g_signal_handlers_disconnect_matched (self->priv->display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
927
 
    g_object_unref (self->priv->display_server);
928
 
    g_free (self->priv->greeter_session);
929
 
    if (self->priv->greeter)
930
 
    {
931
 
        g_signal_handlers_disconnect_matched (self->priv->greeter, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
932
 
        g_object_unref (self->priv->greeter);
933
 
    }
934
 
    g_free (self->priv->session_wrapper);
935
 
    if (self->priv->session)
936
 
    {
937
 
        g_signal_handlers_disconnect_matched (self->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);      
938
 
        g_object_unref (self->priv->session);
939
 
    }
940
 
    g_free (self->priv->autologin_user);
941
 
    g_free (self->priv->select_user_hint);
942
 
    g_free (self->priv->user_session);
943
 
 
944
 
    G_OBJECT_CLASS (display_parent_class)->finalize (object);
945
 
}
946
 
 
947
 
static void
948
 
display_class_init (DisplayClass *klass)
949
 
{
950
 
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
951
 
 
952
 
    klass->switch_to_user = display_real_switch_to_user;
953
 
    klass->switch_to_guest = display_real_switch_to_guest;
954
 
    klass->get_guest_username = display_real_get_guest_username;
955
 
    klass->start_greeter = display_start_greeter;
956
 
    klass->start_session = display_start_session;
957
 
    object_class->finalize = display_finalize;
958
 
 
959
 
    g_type_class_add_private (klass, sizeof (DisplayPrivate));
960
 
 
961
 
    signals[CREATE_SESSION] =
962
 
        g_signal_new ("create-session",
963
 
                      G_TYPE_FROM_CLASS (klass),
964
 
                      G_SIGNAL_RUN_LAST,
965
 
                      G_STRUCT_OFFSET (DisplayClass, create_session),
966
 
                      NULL, NULL,
967
 
                      ldm_marshal_OBJECT__VOID,
968
 
                      SESSION_TYPE, 0);
969
 
    signals[READY] =
970
 
        g_signal_new ("ready",
971
 
                      G_TYPE_FROM_CLASS (klass),
972
 
                      G_SIGNAL_RUN_LAST,
973
 
                      G_STRUCT_OFFSET (DisplayClass, ready),
974
 
                      NULL, NULL,
975
 
                      g_cclosure_marshal_VOID__VOID,
976
 
                      G_TYPE_NONE, 0);
977
 
    signals[SWITCH_TO_USER] =
978
 
        g_signal_new ("switch-to-user",
979
 
                      G_TYPE_FROM_CLASS (klass),
980
 
                      G_SIGNAL_RUN_LAST,
981
 
                      G_STRUCT_OFFSET (DisplayClass, switch_to_user),
982
 
                      g_signal_accumulator_true_handled,
983
 
                      NULL,
984
 
                      ldm_marshal_BOOLEAN__OBJECT,
985
 
                      G_TYPE_BOOLEAN, 1, USER_TYPE);
986
 
    signals[SWITCH_TO_GUEST] =
987
 
        g_signal_new ("switch-to-guest",
988
 
                      G_TYPE_FROM_CLASS (klass),
989
 
                      G_SIGNAL_RUN_LAST,
990
 
                      G_STRUCT_OFFSET (DisplayClass, switch_to_guest),
991
 
                      g_signal_accumulator_true_handled,
992
 
                      NULL,
993
 
                      ldm_marshal_BOOLEAN__VOID,
994
 
                      G_TYPE_BOOLEAN, 0);
995
 
    signals[GET_GUEST_USERNAME] =
996
 
        g_signal_new ("get-guest-username",
997
 
                      G_TYPE_FROM_CLASS (klass),
998
 
                      G_SIGNAL_RUN_LAST,
999
 
                      G_STRUCT_OFFSET (DisplayClass, get_guest_username),
1000
 
                      g_signal_accumulator_first_wins,
1001
 
                      NULL,
1002
 
                      ldm_marshal_STRING__VOID,
1003
 
                      G_TYPE_STRING, 0);
1004
 
    signals[DISPLAY_SERVER_READY] =
1005
 
        g_signal_new ("display-server-ready",
1006
 
                      G_TYPE_FROM_CLASS (klass),
1007
 
                      G_SIGNAL_RUN_LAST,
1008
 
                      G_STRUCT_OFFSET (DisplayClass, display_server_ready),
1009
 
                      NULL, NULL,
1010
 
                      ldm_marshal_BOOLEAN__VOID,
1011
 
                      G_TYPE_BOOLEAN, 0);
1012
 
    signals[START_GREETER] =
1013
 
        g_signal_new ("start-greeter",
1014
 
                      G_TYPE_FROM_CLASS (klass),
1015
 
                      G_SIGNAL_RUN_LAST,
1016
 
                      G_STRUCT_OFFSET (DisplayClass, start_greeter),
1017
 
                      g_signal_accumulator_true_handled, NULL,
1018
 
                      ldm_marshal_BOOLEAN__VOID,
1019
 
                      G_TYPE_BOOLEAN, 0);
1020
 
    signals[START_SESSION] =
1021
 
        g_signal_new ("start-session",
1022
 
                      G_TYPE_FROM_CLASS (klass),
1023
 
                      G_SIGNAL_RUN_LAST,
1024
 
                      G_STRUCT_OFFSET (DisplayClass, start_session),
1025
 
                      g_signal_accumulator_true_handled, NULL,
1026
 
                      ldm_marshal_BOOLEAN__VOID,
1027
 
                      G_TYPE_BOOLEAN, 0);
1028
 
    signals[STOPPED] =
1029
 
        g_signal_new ("stopped",
1030
 
                      G_TYPE_FROM_CLASS (klass),
1031
 
                      G_SIGNAL_RUN_LAST,
1032
 
                      G_STRUCT_OFFSET (DisplayClass, stopped),
1033
 
                      NULL, NULL,
1034
 
                      g_cclosure_marshal_VOID__VOID,
1035
 
                      G_TYPE_NONE, 0);
1036
 
}