~robert-ancell/lightdm/private-mir-connection-merge

« back to all changes in this revision

Viewing changes to src/seat.c

  • Committer: Robert Ancell
  • Date: 2013-07-23 02:24:45 UTC
  • mfrom: (1723 trunk)
  • mto: This revision was merged to the branch mainline in revision 1741.
  • Revision ID: robert.ancell@canonical.com-20130723022445-gpaq8vtkp4hods7r
Merge with trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
#include <sys/wait.h>
15
15
 
16
16
#include "seat.h"
 
17
#include "configuration.h"
17
18
#include "guest-account.h"
 
19
#include "greeter.h"
18
20
 
19
21
enum {
20
 
    DISPLAY_ADDED,
21
 
    DISPLAY_REMOVED,
 
22
    SESSION_ADDED,
 
23
    RUNNING_USER_SESSION,
 
24
    SESSION_REMOVED,
22
25
    STOPPED,
23
26
    LAST_SIGNAL
24
27
};
35
38
    /* TRUE if display server can be shared for sessions */
36
39
    gboolean share_display_server;
37
40
 
38
 
    /* Name of guest account */
39
 
    gchar *guest_username;
40
 
 
41
 
    /* The displays for this seat */
42
 
    GList *displays;
 
41
    /* The display servers on this seat */
 
42
    GList *display_servers;
 
43
 
 
44
    /* The sessions on this seat */
 
45
    GList *sessions;
 
46
 
 
47
    /* The session to set active when it starts */
 
48
    Session *session_to_activate;
43
49
 
44
50
    /* TRUE if stopping this seat (waiting for displays to stop) */
45
51
    gboolean stopping;
48
54
    gboolean stopped;
49
55
};
50
56
 
 
57
/* PAM services to use */
 
58
#define GREETER_SERVICE   "lightdm-greeter"
 
59
#define USER_SERVICE      "lightdm"
 
60
#define AUTOLOGIN_SERVICE "lightdm-autologin"
 
61
 
51
62
G_DEFINE_TYPE (Seat, seat, G_TYPE_OBJECT);
52
63
 
53
64
typedef struct
57
68
} SeatModule;
58
69
static GHashTable *seat_modules = NULL;
59
70
 
60
 
static Display *create_display (Seat *seat, const gchar *session_type);
 
71
// FIXME: Make a get_display_server() that re-uses display servers if supported
 
72
static DisplayServer *create_display_server (Seat *seat);
 
73
static Greeter *create_greeter_session (Seat *seat);
 
74
static void start_session (Seat *seat, Session *session);
61
75
 
62
76
void
63
77
seat_register_module (const gchar *name, GType type)
100
114
    g_hash_table_insert (seat->priv->properties, g_strdup (name), g_strdup (value));
101
115
}
102
116
 
103
 
gboolean
104
 
seat_has_property (Seat *seat, const gchar *name)
105
 
{
106
 
    g_return_val_if_fail (seat != NULL, FALSE);
107
 
    return g_hash_table_lookup (seat->priv->properties, name) != NULL;
108
 
}
109
 
 
110
117
const gchar *
111
118
seat_get_string_property (Seat *seat, const gchar *name)
112
119
{
155
162
}
156
163
 
157
164
GList *
158
 
seat_get_displays (Seat *seat)
 
165
seat_get_sessions (Seat *seat)
159
166
{
160
167
    g_return_val_if_fail (seat != NULL, NULL);
161
 
    return seat->priv->displays;
 
168
    return seat->priv->sessions;
162
169
}
163
170
 
164
171
void
165
 
seat_set_active_display (Seat *seat, Display *display)
 
172
seat_set_active_session (Seat *seat, Session *session)
166
173
{
 
174
    GList *link;
 
175
 
167
176
    g_return_if_fail (seat != NULL);
168
 
    SEAT_GET_CLASS (seat)->set_active_display (seat, display);
 
177
 
 
178
    SEAT_GET_CLASS (seat)->set_active_session (seat, session);
 
179
 
 
180
    /* Stop any greeters */
 
181
    for (link = seat->priv->sessions; link; link = link->next)
 
182
    {
 
183
        Session *s = link->data;
 
184
 
 
185
        if (s == session || session_get_is_stopping (s))
 
186
            continue;
 
187
 
 
188
        if (IS_GREETER (s))
 
189
        {
 
190
            g_debug ("Stopping greeter");
 
191
            session_stop (s);
 
192
        }
 
193
    }
169
194
}
170
195
 
171
 
Display *
172
 
seat_get_active_display (Seat *seat)
 
196
Session *
 
197
seat_get_active_session (Seat *seat)
173
198
{
174
199
    g_return_val_if_fail (seat != NULL, NULL);
175
 
    return SEAT_GET_CLASS (seat)->get_active_display (seat);
 
200
    return SEAT_GET_CLASS (seat)->get_active_session (seat);
176
201
}
177
202
 
178
203
gboolean
185
210
gboolean
186
211
seat_get_allow_guest (Seat *seat)
187
212
{
188
 
    g_return_val_if_fail (seat != NULL, FALSE);  
 
213
    g_return_val_if_fail (seat != NULL, FALSE);
189
214
    return seat_get_boolean_property (seat, "allow-guest") && guest_account_is_installed ();
190
215
}
191
216
 
192
 
gboolean
193
 
seat_get_greeter_allow_guest (Seat *seat)
194
 
{
195
 
    g_return_val_if_fail (seat != NULL, FALSE);  
196
 
    return seat_get_allow_guest (seat) && seat_get_boolean_property (seat, "greeter-allow-guest");
197
 
}
198
 
 
199
 
static gboolean
200
 
switch_to_user (Seat *seat, const gchar *username, gboolean unlock)
201
 
{
202
 
    GList *link;
203
 
 
204
 
    /* Switch to active display if it exists */
205
 
    for (link = seat->priv->displays; link; link = link->next)
206
 
    {
207
 
        Display *display = link->data;
208
 
 
209
 
        if (display_get_is_stopped (display))
210
 
            continue;
211
 
 
212
 
        /* If already logged in, then switch to that display */
213
 
        if (g_strcmp0 (display_get_username (display), username) == 0)        
214
 
        {
215
 
            if (username)
216
 
                g_debug ("Switching to existing session for user %s", username);
217
 
            else
218
 
                g_debug ("Switching to existing greeter");
219
 
            if (unlock)
220
 
                display_unlock (display);
221
 
            seat_set_active_display (seat, display);
222
 
            return TRUE;
223
 
        }
224
 
    }
225
 
 
226
 
    return FALSE;
227
 
}
228
 
 
229
 
static gboolean
230
 
display_switch_to_user_cb (Display *display, User *user, Seat *seat)
231
 
{
232
 
    return switch_to_user (seat, user_get_name (user), TRUE);
233
 
}
234
 
 
235
 
static gboolean
236
 
display_switch_to_guest_cb (Display *display, Seat *seat)
237
 
{
238
 
    /* No guest account */
239
 
    if (!seat->priv->guest_username)
240
 
        return FALSE;
241
 
 
242
 
    return switch_to_user (seat, seat->priv->guest_username, TRUE);
243
 
}
244
 
 
245
 
static const gchar *
246
 
display_get_guest_username_cb (Display *display, Seat *seat)
247
 
{
248
 
    if (seat->priv->guest_username)
249
 
        return seat->priv->guest_username;
250
 
 
251
 
    seat->priv->guest_username = guest_account_setup ();
252
 
    return g_strdup (seat->priv->guest_username);
253
 
}
254
 
 
255
 
static gboolean
256
 
run_script (Seat *seat, Display *display, const gchar *script_name, User *user)
 
217
static gboolean
 
218
run_script (Seat *seat, DisplayServer *display_server, const gchar *script_name, User *user)
257
219
{
258
220
    Process *script;
259
221
    gboolean result = FALSE;
286
248
    else
287
249
        process_set_env (script, "HOME", "/");
288
250
 
289
 
    SEAT_GET_CLASS (seat)->run_script (seat, display, script);
 
251
    SEAT_GET_CLASS (seat)->run_script (seat, display_server, script);
290
252
 
291
253
    if (process_start (script, TRUE))
292
254
    {
306
268
}
307
269
 
308
270
static void
309
 
seat_real_run_script (Seat *seat, Display *display, Process *process)
 
271
seat_real_run_script (Seat *seat, DisplayServer *display_server, Process *process)
310
272
{  
311
273
}
312
274
 
324
286
    g_free (cmd);
325
287
}
326
288
 
327
 
static gboolean
328
 
display_display_server_ready_cb (Display *display, Seat *seat)
329
 
{
330
 
    const gchar *script;
331
 
 
332
 
    /* Run setup script */
333
 
    script = seat_get_string_property (seat, "display-setup-script");
334
 
    if (script && !run_script (seat, display, script, NULL))
335
 
        return FALSE;
336
 
 
337
 
    emit_upstart_signal ("login-session-start");
338
 
 
339
 
    return TRUE;
340
 
}
341
 
 
342
 
static Session *
343
 
display_create_session_cb (Display *display, Seat *seat)
344
 
{
345
 
    return SEAT_GET_CLASS (seat)->create_session (seat, display);
346
 
}
347
 
 
348
 
static gboolean
349
 
display_start_greeter_cb (Display *display, Seat *seat)
350
 
{
351
 
    Session *session;
352
 
    const gchar *script;
353
 
 
354
 
    session = display_get_session (display);
355
 
 
356
 
    script = seat_get_string_property (seat, "greeter-setup-script");
357
 
    if (script)
358
 
        return !run_script (seat, display, script, session_get_user (session));
359
 
    else
360
 
        return FALSE;
361
 
}
362
 
 
363
 
static gboolean
364
 
display_start_session_cb (Display *display, Seat *seat)
365
 
{
366
 
    Session *session;
367
 
    const gchar *script;
368
 
 
369
 
    session = display_get_session (display);
370
 
 
371
 
    script = seat_get_string_property (seat, "session-setup-script");
372
 
    if (script)
373
 
        return !run_script (seat, display, script, session_get_user (session));
374
 
    else
375
 
        return FALSE;
376
 
}
377
 
 
378
 
static void
379
 
session_stopped_cb (Session *session, Seat *seat)
380
 
{
381
 
    Display *display = NULL;
382
 
    GList *link;
383
 
    const gchar *script;
384
 
  
385
 
    /* Work out what display this session is on, it's a bit hacky because we really should know already... */
386
 
    for (link = seat->priv->displays; link; link = link->next)
387
 
    {
388
 
        Display *d = link->data;
389
 
        if (display_get_session (d) == session)
390
 
        {
391
 
            display = d;
392
 
            break;
393
 
        }
394
 
    }
395
 
    g_return_if_fail (display != NULL);
396
 
 
397
 
    /* Cleanup */
398
 
    script = seat_get_string_property (seat, "session-cleanup-script");
399
 
    if (script)
400
 
        run_script (seat, display, script, session_get_user (session));
401
 
 
402
 
    if (seat->priv->guest_username && strcmp (session_get_username (session), seat->priv->guest_username) == 0)
403
 
    {
404
 
        g_free (seat->priv->guest_username);
405
 
        seat->priv->guest_username = NULL;
406
 
    }
407
 
}
408
 
 
409
 
static gboolean
410
 
display_session_started_cb (Display *display, Seat *seat)
411
 
{
412
 
    g_signal_connect (display_get_session (display), "stopped", G_CALLBACK (session_stopped_cb), seat);
413
 
    emit_upstart_signal ("desktop-session-start");
414
 
    return FALSE;
415
 
}
416
 
 
417
 
static void
418
 
display_ready_cb (Display *display, Seat *seat)
419
 
{
420
 
    /* Switch to this new display */
421
 
    g_debug ("New display ready, switching to it");
422
 
    SEAT_GET_CLASS (seat)->set_active_display (seat, display);
423
 
}
424
 
 
425
 
static Display *
426
 
display_create_display_cb (Display *display, Session *session, Seat *seat)
427
 
{
428
 
    Display *d;
429
 
 
430
 
    d = create_display (seat, session_get_session_type (session));
431
 
    g_signal_connect (d, "ready", G_CALLBACK (display_ready_cb), seat);
432
 
    g_signal_emit (seat, signals[DISPLAY_ADDED], 0, d);
433
 
 
434
 
    display_start_with_session (d, session);
435
 
 
436
 
    return g_object_ref (d);
437
 
}
438
 
 
439
289
static void
440
290
check_stopped (Seat *seat)
441
291
{
442
292
    if (seat->priv->stopping &&
443
293
        !seat->priv->stopped &&
444
 
        g_list_length (seat->priv->displays) == 0)
 
294
        g_list_length (seat->priv->display_servers) == 0 &&
 
295
        g_list_length (seat->priv->sessions) == 0)
445
296
    {
446
297
        seat->priv->stopped = TRUE;
447
298
        g_debug ("Seat stopped");
450
301
}
451
302
 
452
303
static void
453
 
display_stopped_cb (Display *display, Seat *seat)
454
 
{
455
 
    gboolean is_active;
456
 
 
457
 
    is_active = display == seat_get_active_display (seat);
458
 
 
459
 
    g_signal_handlers_disconnect_matched (display, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
460
 
    seat->priv->displays = g_list_remove (seat->priv->displays, display);
461
 
 
462
 
    g_signal_emit (seat, signals[DISPLAY_REMOVED], 0, display);
463
 
 
464
 
    /* If no more displays running either start a greeter or stop the seat */
465
 
    if (!seat->priv->stopping)
466
 
    {
467
 
        if (g_list_length (seat->priv->displays) == 0)
468
 
        {
469
 
            /* If failed to start then stop this seat */
470
 
            if (!display_get_is_ready (display))
471
 
            {
472
 
                g_debug ("Stopping seat, failed to start a display");
473
 
                seat_stop (seat);
474
 
            }
475
 
            /* Attempt to start a greeter */
476
 
            else if (!seat->priv->can_switch)
477
 
            {
478
 
                g_debug ("Stopping seat, display stopped");
479
 
                seat_stop (seat);             
480
 
            }
481
 
            
482
 
            else if (!seat_switch_to_greeter (seat))
483
 
            {
484
 
                g_debug ("Stopping seat, unable to start greeter");
485
 
                seat_stop (seat);
486
 
            }        
487
 
        }
488
 
        else if (is_active)
489
 
        {
490
 
            g_debug ("Active display stopped, switching to greeter");
491
 
            if (!seat_switch_to_greeter (seat))
492
 
            {
493
 
                g_debug ("Stopping seat, unable to start greeter");
494
 
                seat_stop (seat);              
495
 
            }
496
 
        }
497
 
    }
498
 
 
499
 
    g_object_unref (display);
500
 
 
501
 
    check_stopped (seat);
502
 
}
503
 
 
504
 
static Display *
505
 
create_display (Seat *seat, const gchar *session_type)
506
 
{
507
 
    Display *display;
508
 
    DisplayServer *display_server;
509
 
 
510
 
    display_server = SEAT_GET_CLASS (seat)->create_display_server (seat, session_type);
511
 
    display = display_new (display_server);
 
304
display_server_stopped_cb (DisplayServer *display_server, Seat *seat)
 
305
{
 
306
    GList *list, *link;
 
307
    Session *active_session;
 
308
 
 
309
    g_debug ("Display server stopped");
 
310
 
 
311
    g_signal_handlers_disconnect_matched (display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
 
312
    seat->priv->display_servers = g_list_remove (seat->priv->display_servers, display_server);
 
313
 
 
314
    if (seat->priv->stopping)
 
315
    {
 
316
        check_stopped (seat);
 
317
        g_object_unref (display_server);
 
318
        return;
 
319
    }
 
320
 
 
321
    /* Stop all sessions on this display server */
 
322
    list = g_list_copy (seat->priv->sessions);
 
323
    for (link = list; link; link = link->next)
 
324
        g_object_ref (link->data);
 
325
    for (link = list; link; link = link->next)
 
326
    {
 
327
        Session *session = link->data;
 
328
 
 
329
        if (session_get_display_server (session) != display_server || session_get_is_stopping (session))
 
330
            continue;
 
331
 
 
332
        /* Stop seat if this is the only display server and it failed to start a greeter */
 
333
        if (IS_GREETER (session) &&
 
334
            !session_get_is_started (session) &&
 
335
            g_list_length (seat->priv->display_servers) == 0)
 
336
        {
 
337
            g_debug ("Stopping seat, greeter display server failed to start");
 
338
            seat_stop (seat);
 
339
        }
 
340
 
 
341
        g_debug ("Stopping session");
 
342
        session_stop (session);
 
343
    }
 
344
    g_list_free_full (list, g_object_unref);
 
345
 
 
346
    if (!seat->priv->stopping && display_server_get_start_local_sessions (display_server))
 
347
    {
 
348
        /* If we were the active session, switch to a greeter */
 
349
        active_session = seat_get_active_session (seat);
 
350
        if (!active_session || session_get_display_server (active_session) == display_server)
 
351
        {
 
352
            g_debug ("Active display server stopped, starting greeter");
 
353
            seat_switch_to_greeter (seat);
 
354
        }
 
355
    }
 
356
 
512
357
    g_object_unref (display_server);
513
 
 
514
 
    g_signal_connect (display, "display-server-ready", G_CALLBACK (display_display_server_ready_cb), seat);  
515
 
    g_signal_connect (display, "switch-to-user", G_CALLBACK (display_switch_to_user_cb), seat);
516
 
    g_signal_connect (display, "switch-to-guest", G_CALLBACK (display_switch_to_guest_cb), seat);
517
 
    g_signal_connect (display, "get-guest-username", G_CALLBACK (display_get_guest_username_cb), seat);
518
 
    g_signal_connect (display, "create-session", G_CALLBACK (display_create_session_cb), seat);
519
 
    g_signal_connect (display, "start-greeter", G_CALLBACK (display_start_greeter_cb), seat);
520
 
    g_signal_connect (display, "start-session", G_CALLBACK (display_start_session_cb), seat);
521
 
    g_signal_connect_after (display, "start-session", G_CALLBACK (display_session_started_cb), seat);
522
 
    g_signal_connect (display, "create-display", G_CALLBACK (display_create_display_cb), seat);
523
 
    g_signal_connect (display, "stopped", G_CALLBACK (display_stopped_cb), seat);
524
 
    display_set_greeter_session (display, seat_get_string_property (seat, "greeter-session"));
525
 
    display_set_session_wrapper (display, seat_get_string_property (seat, "session-wrapper"));
526
 
    display_set_greeter_wrapper (display, seat_get_string_property (seat, "greeter-wrapper"));
527
 
    display_set_hide_users_hint (display, seat_get_boolean_property (seat, "greeter-hide-users"));
528
 
    display_set_show_manual_login_hint (display, seat_get_boolean_property (seat, "greeter-show-manual-login"));
529
 
    display_set_show_remote_login_hint (display, seat_get_boolean_property (seat, "greeter-show-remote-login"));
530
 
    display_set_allow_guest (display, seat_get_allow_guest (seat));
531
 
    display_set_greeter_allow_guest (display, seat_get_greeter_allow_guest (seat));
532
 
    display_set_user_session (display, SESSION_TYPE_LOCAL, seat_get_string_property (seat, "user-session"));
533
 
    display_set_share_display_server (display, seat->priv->share_display_server);
534
 
 
535
 
    seat->priv->displays = g_list_append (seat->priv->displays, display);
536
 
 
537
 
    return display;
 
358
}
 
359
 
 
360
static void
 
361
switch_to_greeter_from_failed_session (Seat *seat, Session *session)
 
362
{
 
363
    Greeter *greeter_session;
 
364
 
 
365
    greeter_session = create_greeter_session (seat);
 
366
    if (session_get_is_guest (session))
 
367
        greeter_set_hint (greeter_session, "select-guest", "true");
 
368
    else
 
369
        greeter_set_hint (greeter_session, "select-user", session_get_username (session));
 
370
    if (seat->priv->session_to_activate)
 
371
        g_object_unref (seat->priv->session_to_activate);
 
372
    seat->priv->session_to_activate = g_object_ref (greeter_session);
 
373
 
 
374
    if (seat->priv->share_display_server)
 
375
        session_set_display_server (SESSION (greeter_session), session_get_display_server (session));
 
376
    else
 
377
    {
 
378
        DisplayServer *display_server;
 
379
 
 
380
        display_server = create_display_server (seat);
 
381
        if (!display_server_start (display_server))
 
382
        {
 
383
            g_debug ("Failed to start display server for greeter");
 
384
            seat_stop (seat);
 
385
        }
 
386
 
 
387
        session_set_display_server (session, display_server);
 
388
    }
 
389
 
 
390
    start_session (seat, SESSION (greeter_session));
 
391
 
 
392
    /* Stop failed session */
 
393
    session_stop (session);
 
394
}
 
395
 
 
396
static void
 
397
start_session (Seat *seat, Session *session)
 
398
{
 
399
    if (session_start (session))
 
400
        return;
 
401
 
 
402
    if (IS_GREETER (session))
 
403
    {
 
404
        g_debug ("Failed to start greeter");
 
405
        display_server_stop (session_get_display_server (session));
 
406
        return;
 
407
    }
 
408
 
 
409
    g_debug ("Failed to start session, starting greeter");
 
410
    switch_to_greeter_from_failed_session (seat, session);
 
411
}
 
412
 
 
413
static void
 
414
run_session (Seat *seat, Session *session)
 
415
{
 
416
    const gchar *script;
 
417
 
 
418
    if (IS_GREETER (session))
 
419
        script = seat_get_string_property (seat, "greeter-setup-script");
 
420
    else
 
421
        script = seat_get_string_property (seat, "session-setup-script");
 
422
    if (script && !run_script (seat, session_get_display_server (session), script, NULL))
 
423
    {
 
424
        g_debug ("Switching to greeter due to failed setup script");
 
425
        switch_to_greeter_from_failed_session (seat, session);
 
426
        return;
 
427
    }
 
428
 
 
429
    if (!IS_GREETER (session))
 
430
        g_signal_emit (seat, signals[RUNNING_USER_SESSION], 0, session);
 
431
 
 
432
    session_run (session);
 
433
 
 
434
    // FIXME: Wait until the session is ready
 
435
 
 
436
    if (session == seat->priv->session_to_activate)
 
437
    {
 
438
        seat_set_active_session (seat, session);
 
439
        g_object_unref (seat->priv->session_to_activate);
 
440
        seat->priv->session_to_activate = NULL;
 
441
    }
 
442
}
 
443
 
 
444
static void
 
445
session_authentication_complete_cb (Session *session, Seat *seat)
 
446
{
 
447
    if (session_get_is_authenticated (session))
 
448
    {
 
449
        g_debug ("Session authenticated, running command");
 
450
        run_session (seat, session);
 
451
    }
 
452
    else if (!IS_GREETER (session))
 
453
    {
 
454
        g_debug ("Switching to greeter due to failed authentication");
 
455
        switch_to_greeter_from_failed_session (seat, session);
 
456
    }
 
457
    else
 
458
    {
 
459
        g_debug ("Stopping session that failed authentication");
 
460
        session_stop (session);
 
461
    }
 
462
}
 
463
 
 
464
static void
 
465
session_stopped_cb (Session *session, Seat *seat)
 
466
{
 
467
    DisplayServer *display_server;
 
468
 
 
469
    g_debug ("Session stopped");
 
470
 
 
471
    display_server = session_get_display_server (session);
 
472
 
 
473
    /* Cleanup */
 
474
    if (!IS_GREETER (session))
 
475
    {
 
476
        const gchar *script;
 
477
        script = seat_get_string_property (seat, "session-cleanup-script");
 
478
        if (script)
 
479
            run_script (seat, display_server, script, session_get_user (session));
 
480
    }
 
481
 
 
482
    g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
 
483
    seat->priv->sessions = g_list_remove (seat->priv->sessions, session);
 
484
 
 
485
    /* We were waiting for this session, but it didn't start :( */
 
486
    // FIXME: Start a greeter on this?
 
487
    if (session == seat->priv->session_to_activate)
 
488
    {
 
489
        g_object_unref (seat->priv->session_to_activate);
 
490
        seat->priv->session_to_activate = NULL;
 
491
    }
 
492
 
 
493
    if (seat->priv->stopping)
 
494
    {
 
495
        check_stopped (seat);
 
496
        g_object_unref (session);
 
497
        return;
 
498
    }
 
499
 
 
500
    /* If this is the greeter session then re-use this display server */
 
501
    if (IS_GREETER (session) && seat->priv->share_display_server &&
 
502
        greeter_get_start_session (GREETER (session)))
 
503
    {
 
504
        GList *link;
 
505
 
 
506
        for (link = seat->priv->sessions; link; link = link->next)
 
507
        {
 
508
            Session *s = link->data;
 
509
 
 
510
            /* Skip this session and sessions on other display servers */
 
511
            if (s == session || session_get_display_server (s) != display_server || session_get_is_stopping (s))
 
512
                continue;
 
513
 
 
514
            if (session_get_is_authenticated (s))
 
515
            {
 
516
                g_debug ("Greeter stopped, running session");
 
517
                run_session (seat, s);
 
518
            }
 
519
            else
 
520
            {
 
521
                g_debug ("Greeter stopped, starting session authentication");
 
522
                start_session (seat, s);
 
523
            }
 
524
            break;
 
525
        }
 
526
    }
 
527
    /* If this is the greeter and nothing else is running then stop the seat */
 
528
    else if (IS_GREETER (session) &&
 
529
        !greeter_get_start_session (GREETER (session)) &&
 
530
        g_list_length (seat->priv->display_servers) == 1 &&
 
531
        g_list_nth_data (seat->priv->display_servers, 0) == display_server)
 
532
    {
 
533
        g_debug ("Stopping seat, failed to start a greeter");
 
534
        seat_stop (seat);
 
535
    }
 
536
    /* If we were the active session, switch to a greeter */
 
537
    else if (!IS_GREETER (session) && session == seat_get_active_session (seat))
 
538
    {
 
539
        g_debug ("Active session stopped, starting greeter");
 
540
        seat_switch_to_greeter (seat);
 
541
    }
 
542
 
 
543
    /* Stop the display server if no-longer required */
 
544
    if (display_server && !display_server_get_is_stopping (display_server))
 
545
    {
 
546
        GList *link;
 
547
        int n_sessions = 0;
 
548
 
 
549
        for (link = seat->priv->sessions; link; link = link->next)
 
550
        {
 
551
            Session *s = link->data;
 
552
            if (s == session)
 
553
                continue;
 
554
            if (session_get_display_server (s) == display_server)
 
555
                n_sessions++;
 
556
        }
 
557
        if (n_sessions == 0)
 
558
        {
 
559
            g_debug ("Stopping display server, no sessions require it");
 
560
            display_server_stop (display_server);
 
561
        }
 
562
    }
 
563
 
 
564
    g_signal_emit (seat, signals[SESSION_REMOVED], 0, session);
 
565
    g_object_unref (session);
 
566
}
 
567
 
 
568
static void
 
569
set_session_env (Session *session)
 
570
{
 
571
    /* Connect using the session bus */
 
572
    if (getuid () != 0)
 
573
    {
 
574
        if (g_getenv ("DBUS_SESSION_BUS_ADDRESS"))
 
575
            session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
 
576
        session_set_env (session, "LDM_BUS", "SESSION");
 
577
        if (g_getenv ("LD_PRELOAD"))
 
578
            session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
 
579
        if (g_getenv ("LD_LIBRARY_PATH"))
 
580
            session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
 
581
        if (g_getenv ("PATH"))
 
582
            session_set_env (session, "PATH", g_getenv ("PATH"));
 
583
    }
 
584
 
 
585
    /* Variables required for regression tests */
 
586
    if (g_getenv ("LIGHTDM_TEST_ROOT"))
 
587
    {
 
588
        session_set_env (session, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
 
589
        session_set_env (session, "DBUS_SYSTEM_BUS_ADDRESS", g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
 
590
        session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
 
591
        session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
 
592
        session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
 
593
        session_set_env (session, "GI_TYPELIB_PATH", g_getenv ("GI_TYPELIB_PATH"));
 
594
    }
 
595
}
 
596
 
 
597
static Session *
 
598
create_session (Seat *seat, gboolean autostart)
 
599
{
 
600
    Session *session;
 
601
 
 
602
    session = SEAT_GET_CLASS (seat)->create_session (seat);
 
603
    seat->priv->sessions = g_list_append (seat->priv->sessions, session);
 
604
    if (autostart)
 
605
        g_signal_connect (session, "authentication-complete", G_CALLBACK (session_authentication_complete_cb), seat);
 
606
    g_signal_connect (session, "stopped", G_CALLBACK (session_stopped_cb), seat);
 
607
 
 
608
    set_session_env (session);
 
609
 
 
610
    g_signal_emit (seat, signals[SESSION_ADDED], 0, session);
 
611
 
 
612
    return session;
 
613
}
 
614
 
 
615
static gchar **
 
616
get_session_argv_from_filename (const gchar *filename, const gchar *session_wrapper)
 
617
{
 
618
    GKeyFile *session_desktop_file;
 
619
    gboolean result;
 
620
    int argc;
 
621
    gchar *command = NULL, **argv, *path;
 
622
    GError *error = NULL;
 
623
 
 
624
    /* Read the command from the .desktop file */
 
625
    session_desktop_file = g_key_file_new ();
 
626
    result = g_key_file_load_from_file (session_desktop_file, filename, G_KEY_FILE_NONE, &error);
 
627
    if (error)
 
628
        g_debug ("Failed to load session file %s: %s", filename, error->message);
 
629
    g_clear_error (&error);
 
630
    if (result)
 
631
    {
 
632
        command = g_key_file_get_string (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL);
 
633
        if (!command)
 
634
            g_debug ("No command in session file %s", filename);
 
635
    }
 
636
    g_key_file_free (session_desktop_file);
 
637
 
 
638
    if (!command)
 
639
        return NULL;
 
640
 
 
641
    /* If configured, run sessions through a wrapper */
 
642
    if (session_wrapper)
 
643
    {
 
644
        argv = g_malloc (sizeof (gchar *) * 3);
 
645
        path = g_find_program_in_path (session_wrapper);
 
646
        argv[0] = path ? path : g_strdup (session_wrapper);
 
647
        argv[1] = command;
 
648
        argv[2] = NULL;
 
649
        return argv;
 
650
    }
 
651
 
 
652
    /* Split command into an array listing and make command absolute */
 
653
    result = g_shell_parse_argv (command, &argc, &argv, &error);
 
654
    if (error)
 
655
        g_debug ("Invalid session command '%s': %s", command, error->message);
 
656
    g_clear_error (&error);
 
657
    g_free (command);
 
658
    if (!result)
 
659
        return NULL;
 
660
    path = g_find_program_in_path (argv[0]);
 
661
    if (path)
 
662
    {
 
663
        g_free (argv[0]);
 
664
        argv[0] = path;
 
665
    }
 
666
  
 
667
    return argv;
 
668
}
 
669
 
 
670
static gchar **
 
671
get_session_argv (const gchar *sessions_dir, const gchar *session_name, const gchar *session_wrapper)
 
672
{
 
673
    gchar **dirs, **argv = NULL;
 
674
    int i;
 
675
 
 
676
    g_return_val_if_fail (sessions_dir != NULL, NULL);
 
677
    g_return_val_if_fail (session_name != NULL, NULL);
 
678
 
 
679
    dirs = g_strsplit (sessions_dir, ":", -1);
 
680
    for (i = 0; dirs[i]; i++)
 
681
    {
 
682
        gchar *filename, *path;
 
683
 
 
684
        filename = g_strdup_printf ("%s.desktop", session_name);
 
685
        path = g_build_filename (dirs[i], filename, NULL);
 
686
        g_free (filename);
 
687
        argv = get_session_argv_from_filename (path, session_wrapper);
 
688
        g_free (path);
 
689
        if (argv)
 
690
            break;
 
691
    }
 
692
    g_strfreev (dirs);
 
693
 
 
694
    return argv;
 
695
}
 
696
 
 
697
static Session *
 
698
create_user_session (Seat *seat, const gchar *username)
 
699
{
 
700
    User *user;
 
701
    gchar *sessions_dir, **argv;
 
702
    const gchar *session_name, *language;
 
703
    Session *session = NULL;
 
704
 
 
705
    /* Load user preferences */
 
706
    user = accounts_get_user_by_name (username);
 
707
    if (!user)
 
708
    {
 
709
        g_debug ("Can't login unknown user '%s'", username);
 
710
        return NULL;
 
711
    }
 
712
    session_name = user_get_xsession (user);
 
713
    language = user_get_language (user);
 
714
 
 
715
    if (!session_name)
 
716
        session_name = seat_get_string_property (seat, "user-session");
 
717
    sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
 
718
    argv = get_session_argv (sessions_dir, session_name, seat_get_string_property (seat, "session-wrapper"));
 
719
    g_free (sessions_dir);
 
720
    if (argv)
 
721
    {
 
722
        session = create_session (seat, TRUE);
 
723
        session_set_env (session, "DESKTOP_SESSION", session_name);
 
724
        session_set_env (session, "GDMSESSION", session_name);
 
725
        if (language && language[0] != '\0')
 
726
        {
 
727
            session_set_env (session, "LANG", language);
 
728
            session_set_env (session, "GDM_LANG", language);
 
729
        }
 
730
        session_set_pam_service (session, AUTOLOGIN_SERVICE);
 
731
        session_set_username (session, username);
 
732
        session_set_do_authenticate (session, TRUE);
 
733
        session_set_argv (session, argv);     
 
734
    }
 
735
    else
 
736
        g_debug ("Can't find session '%s'", seat_get_string_property (seat, "user-session"));
 
737
 
 
738
    g_object_unref (user);
 
739
 
 
740
    return session;
 
741
}
 
742
 
 
743
static Session *
 
744
create_guest_session (Seat *seat)
 
745
{
 
746
    gchar *sessions_dir, **argv;
 
747
    Session *session;
 
748
 
 
749
    sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
 
750
    argv = get_session_argv (sessions_dir,
 
751
                             seat_get_string_property (seat, "user-session"),
 
752
                             seat_get_string_property (seat, "session-wrapper"));
 
753
    g_free (sessions_dir);
 
754
    if (!argv)
 
755
    {
 
756
        g_debug ("Can't find session '%s'", seat_get_string_property (seat, "user-session"));
 
757
        return NULL;
 
758
    }
 
759
 
 
760
    session = create_session (seat, TRUE);
 
761
    session_set_do_authenticate (session, TRUE);
 
762
    session_set_is_guest (session, TRUE);
 
763
    session_set_argv (session, argv);
 
764
  
 
765
    return session;
 
766
}
 
767
 
 
768
static Session *
 
769
greeter_create_session_cb (Greeter *greeter, Seat *seat)
 
770
{
 
771
    Session *session;
 
772
 
 
773
    session = create_session (seat, FALSE);
 
774
    session_set_display_server (session, session_get_display_server (SESSION (greeter)));
 
775
 
 
776
    return g_object_ref (session);
 
777
}
 
778
 
 
779
static void
 
780
prepend_argv (gchar ***argv, const gchar *value)
 
781
{
 
782
    gchar **old_argv, **new_argv;
 
783
    gint i;
 
784
 
 
785
    old_argv = *argv;
 
786
    new_argv = g_malloc (sizeof (gchar *) * (g_strv_length (*argv) + 2));
 
787
    new_argv[0] = g_strdup (value);
 
788
    for (i = 0; old_argv[i]; i++)
 
789
        new_argv[i + 1] = old_argv[i];
 
790
    new_argv[i + 1] = NULL;
 
791
 
 
792
    g_free (*argv);
 
793
    *argv = new_argv;
 
794
}
 
795
 
 
796
static Session *
 
797
find_user_session (Seat *seat, const gchar *username)
 
798
{
 
799
    GList *link;
 
800
 
 
801
    if (!username)
 
802
        return NULL;
 
803
 
 
804
    for (link = seat->priv->sessions; link; link = link->next)
 
805
    {
 
806
        Session *session = link->data;
 
807
 
 
808
        if (!session_get_is_stopping (session) && strcmp (session_get_username (session), username) == 0)
 
809
            return session;
 
810
    }
 
811
 
 
812
    return NULL;
538
813
}
539
814
 
540
815
static gboolean
541
 
start_display (Seat *seat, Display *display)
542
 
{
543
 
    g_signal_emit (seat, signals[DISPLAY_ADDED], 0, display);
544
 
 
545
 
    /* Switch to this display if currently not looking at anything */
546
 
    if (seat_get_active_display (seat) == NULL)
547
 
        seat_set_active_display (seat, display);
548
 
 
549
 
    return display_start (display);
 
816
greeter_start_session_cb (Greeter *greeter, SessionType type, const gchar *session_name, Seat *seat)
 
817
{
 
818
    Session *session, *existing_session;
 
819
    const gchar *username, *language = NULL;
 
820
    User *user;
 
821
    gchar *sessions_dir = NULL;
 
822
    gchar **argv;
 
823
 
 
824
    /* Get the session to use */
 
825
    if (greeter_get_guest_authenticated (greeter))
 
826
    {
 
827
        session = create_guest_session (seat);
 
828
        if (!session)
 
829
            return FALSE;
 
830
        session_set_pam_service (session, AUTOLOGIN_SERVICE);
 
831
    }
 
832
    else
 
833
        session = greeter_get_authentication_session (greeter);
 
834
 
 
835
    /* Switch to this session when it is ready */
 
836
    if (seat->priv->session_to_activate)
 
837
        g_object_unref (seat->priv->session_to_activate);
 
838
    seat->priv->session_to_activate = g_object_ref (session);
 
839
 
 
840
    /* Return to existing session if it is open */
 
841
    username = session_get_username (session);
 
842
    existing_session = find_user_session (seat, username);
 
843
    if (existing_session && session != existing_session)
 
844
    {
 
845
        g_debug ("Returning to existing user session %s", username);
 
846
        session_stop (session);
 
847
        seat_set_active_session (seat, existing_session);
 
848
        return TRUE;
 
849
    }
 
850
 
 
851
    /* Get session command to run */
 
852
    switch (type)
 
853
    {
 
854
    case SESSION_TYPE_LOCAL:
 
855
        sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
 
856
        break;
 
857
    case SESSION_TYPE_REMOTE:
 
858
        sessions_dir = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory");
 
859
        break;
 
860
    }
 
861
 
 
862
    /* Load user preferences */
 
863
    user = session_get_user (session);
 
864
    if (user)
 
865
    {
 
866
        if (!session_name)
 
867
            session_name = user_get_xsession (user);
 
868
        language = user_get_language (user);
 
869
    }
 
870
 
 
871
    if (!session_name)
 
872
        session_name = seat_get_string_property (seat, "user-session");
 
873
    if (user)
 
874
        user_set_xsession (session_get_user (session), session_name);
 
875
 
 
876
    argv = get_session_argv (sessions_dir, session_name, seat_get_string_property (seat, "session-wrapper"));
 
877
    g_free (sessions_dir);
 
878
  
 
879
    if (!argv)
 
880
    {
 
881
        g_debug ("Can't find session '%s'", seat_get_string_property (seat, "user-session"));
 
882
        return FALSE;
 
883
    }
 
884
 
 
885
    session_set_argv (session, argv);
 
886
    g_strfreev (argv);
 
887
    session_set_env (session, "DESKTOP_SESSION", session_name);
 
888
    session_set_env (session, "GDMSESSION", session_name);
 
889
    if (language && language[0] != '\0')
 
890
    {
 
891
        session_set_env (session, "LANG", language);
 
892
        session_set_env (session, "GDM_LANG", language);
 
893
    }
 
894
 
 
895
    /* If can re-use the display server, stop the greeter first */
 
896
    if (seat->priv->share_display_server)
 
897
    {
 
898
        /* Run on the same display server after the greeter has stopped */
 
899
        session_set_display_server (session, session_get_display_server (SESSION (greeter)));
 
900
 
 
901
        g_debug ("Stopping greeter");
 
902
        session_stop (SESSION (greeter));
 
903
 
 
904
        return TRUE;
 
905
    }
 
906
    /* Otherwise start a new display server for this session */
 
907
    else
 
908
    {
 
909
        DisplayServer *display_server;
 
910
 
 
911
        display_server = create_display_server (seat);
 
912
        if (!display_server_start (display_server))
 
913
            return FALSE;
 
914
 
 
915
        session_set_display_server (session, display_server);
 
916
 
 
917
        return TRUE;
 
918
    }
 
919
}
 
920
 
 
921
static Greeter *
 
922
create_greeter_session (Seat *seat)
 
923
{
 
924
    gchar *sessions_dir, **argv;
 
925
    Greeter *greeter_session;
 
926
    gchar *greeter_user;
 
927
    const gchar *greeter_wrapper;
 
928
 
 
929
    sessions_dir = config_get_string (config_get_instance (), "LightDM", "greeters-directory");
 
930
    argv = get_session_argv (sessions_dir,
 
931
                             seat_get_string_property (seat, "greeter-session"),
 
932
                             NULL);
 
933
    g_free (sessions_dir);
 
934
    if (!argv)
 
935
        return NULL;
 
936
 
 
937
    greeter_wrapper = seat_get_string_property (seat, "greeter-wrapper");
 
938
    if (greeter_wrapper)
 
939
    {
 
940
        gchar *path;
 
941
        path = g_find_program_in_path (greeter_wrapper);
 
942
        prepend_argv (&argv, path ? path : greeter_wrapper);
 
943
        g_free (path);
 
944
    }
 
945
 
 
946
    greeter_session = SEAT_GET_CLASS (seat)->create_greeter_session (seat);
 
947
    seat->priv->sessions = g_list_append (seat->priv->sessions, SESSION (greeter_session));
 
948
    g_signal_connect (greeter_session, "authentication-complete", G_CALLBACK (session_authentication_complete_cb), seat);
 
949
    g_signal_connect (greeter_session, "stopped", G_CALLBACK (session_stopped_cb), seat);
 
950
  
 
951
    set_session_env (SESSION (greeter_session));
 
952
 
 
953
    session_set_pam_service (SESSION (greeter_session), GREETER_SERVICE);
 
954
    greeter_user = config_get_string (config_get_instance (), "LightDM", "greeter-user");
 
955
    session_set_username (SESSION (greeter_session), greeter_user);
 
956
    g_free (greeter_user);
 
957
    session_set_argv (SESSION (greeter_session), argv);
 
958
 
 
959
    greeter_set_pam_services (greeter_session, USER_SERVICE, AUTOLOGIN_SERVICE);
 
960
    g_signal_connect (greeter_session, "create-session", G_CALLBACK (greeter_create_session_cb), seat);
 
961
    g_signal_connect (greeter_session, "start-session", G_CALLBACK (greeter_start_session_cb), seat);
 
962
 
 
963
    /* Set hints to greeter */
 
964
    greeter_set_hint (greeter_session, "default-session", seat_get_string_property (seat, "user-session"));
 
965
    greeter_set_allow_guest (greeter_session, seat_get_allow_guest (seat));
 
966
    greeter_set_hint (greeter_session, "hide-users", seat_get_boolean_property (seat, "greeter-hide-users") ? "true" : "false");
 
967
    greeter_set_hint (greeter_session, "show-manual-login", seat_get_boolean_property (seat, "greeter-show-manual-login") ? "true" : "false");
 
968
    greeter_set_hint (greeter_session, "show-remote-login", seat_get_boolean_property (seat, "greeter-show-remote-login") ? "true" : "false");
 
969
    greeter_set_hint (greeter_session, "has-guest-account", seat_get_allow_guest (seat) && seat_get_boolean_property (seat, "greeter-allow-guest") ? "true" : "false");
 
970
 
 
971
    return greeter_session;
 
972
}
 
973
 
 
974
static Session *
 
975
find_session_for_display_server (Seat *seat, DisplayServer *display_server)
 
976
{
 
977
    GList *link;
 
978
 
 
979
    for (link = seat->priv->sessions; link; link = link->next)
 
980
    {
 
981
        Session *session = link->data;
 
982
        if (session_get_display_server (session) == display_server && !session_get_is_stopping (session))
 
983
            return session;
 
984
    }
 
985
 
 
986
    return NULL;
 
987
}
 
988
 
 
989
static void
 
990
display_server_ready_cb (DisplayServer *display_server, Seat *seat)
 
991
{
 
992
    const gchar *script;
 
993
    Session *session;
 
994
 
 
995
    /* Run setup script */
 
996
    script = seat_get_string_property (seat, "display-setup-script");
 
997
    if (script && !run_script (seat, display_server, script, NULL))
 
998
    {
 
999
        g_debug ("Stopping display server due to failed setup script");
 
1000
        display_server_stop (display_server);
 
1001
        return;
 
1002
    }
 
1003
 
 
1004
    /* Stop if don't need to run a session */
 
1005
    if (!display_server_get_start_local_sessions (display_server))
 
1006
        return;
 
1007
 
 
1008
    emit_upstart_signal ("login-session-start");
 
1009
 
 
1010
    /* Start the session waiting for this display server */
 
1011
    session = find_session_for_display_server (seat, display_server);
 
1012
    if (session)
 
1013
    {
 
1014
        if (session_get_is_authenticated (session))
 
1015
        {
 
1016
            g_debug ("Display server ready, running session");
 
1017
            run_session (seat, session);
 
1018
        }
 
1019
        else
 
1020
        {
 
1021
            g_debug ("Display server ready, starting session authentication");
 
1022
            start_session (seat, session);
 
1023
        }
 
1024
    }
 
1025
    else
 
1026
    {
 
1027
        g_debug ("Stopping not required display server");
 
1028
        display_server_stop (display_server);
 
1029
    }
 
1030
}
 
1031
 
 
1032
static DisplayServer *
 
1033
create_display_server (Seat *seat)
 
1034
{
 
1035
    DisplayServer *display_server;
 
1036
 
 
1037
    display_server = SEAT_GET_CLASS (seat)->create_display_server (seat, "");
 
1038
    seat->priv->display_servers = g_list_append (seat->priv->display_servers, display_server);
 
1039
    g_signal_connect (display_server, "ready", G_CALLBACK (display_server_ready_cb), seat);
 
1040
    g_signal_connect (display_server, "stopped", G_CALLBACK (display_server_stopped_cb), seat);
 
1041
 
 
1042
    return display_server;
 
1043
}
 
1044
 
 
1045
static Greeter *
 
1046
find_greeter_session (Seat *seat)
 
1047
{
 
1048
    GList *link;
 
1049
 
 
1050
    for (link = seat->priv->sessions; link; link = link->next)
 
1051
    {
 
1052
        Session *session = link->data;
 
1053
        if (!session_get_is_stopping (session) && IS_GREETER (session))
 
1054
            return GREETER (session);
 
1055
    }
 
1056
 
 
1057
    return NULL;
550
1058
}
551
1059
 
552
1060
gboolean
553
1061
seat_switch_to_greeter (Seat *seat)
554
1062
{
555
 
    Display *display;
 
1063
    Greeter *greeter_session;
 
1064
    DisplayServer *display_server;
556
1065
 
557
1066
    g_return_val_if_fail (seat != NULL, FALSE);
558
1067
 
559
1068
    if (!seat->priv->can_switch)
560
1069
        return FALSE;
561
1070
 
562
 
    g_debug ("Switching to greeter");
563
 
 
564
1071
    /* Switch to greeter if one open (shouldn't be though) */
565
 
    if (switch_to_user (seat, NULL, FALSE))
 
1072
    greeter_session = find_greeter_session (seat);
 
1073
    if (greeter_session)
 
1074
    {
 
1075
        g_debug ("Switching to existing greeter");
 
1076
        seat_set_active_session (seat, SESSION (greeter_session));
566
1077
        return TRUE;
567
 
 
568
 
    g_debug ("Starting new display for greeter");
569
 
 
570
 
    display = create_display (seat, "x" /*FIXME greeter_type */);
571
 
    g_signal_connect (display, "ready", G_CALLBACK (display_ready_cb), seat);
572
 
 
573
 
    return start_display (seat, display);
 
1078
    }
 
1079
 
 
1080
    greeter_session = create_greeter_session (seat);
 
1081
    if (seat->priv->session_to_activate)
 
1082
        g_object_unref (seat->priv->session_to_activate);
 
1083
    seat->priv->session_to_activate = g_object_ref (greeter_session);
 
1084
 
 
1085
    display_server = create_display_server (seat);
 
1086
    session_set_display_server (SESSION (greeter_session), display_server);
 
1087
    if (!display_server_start (display_server))
 
1088
        return FALSE;
 
1089
 
 
1090
    return TRUE;
574
1091
}
575
1092
 
576
1093
gboolean
577
1094
seat_switch_to_user (Seat *seat, const gchar *username, const gchar *session_name)
578
1095
{
579
 
    Display *display;
 
1096
    Session *session;
 
1097
    DisplayServer *display_server;
580
1098
 
581
1099
    g_return_val_if_fail (seat != NULL, FALSE);
582
1100
    g_return_val_if_fail (username != NULL, FALSE);
586
1104
 
587
1105
    g_debug ("Switching to user %s", username);
588
1106
 
589
 
    /* Switch to session if one open */
590
 
    if (switch_to_user (seat, username, FALSE))
 
1107
    session = find_user_session (seat, username);
 
1108
    if (session)
 
1109
    {
 
1110
        g_debug ("Switching to existing user session %s", username);
 
1111
        seat_set_active_session (seat, session);
591
1112
        return TRUE;
592
 
 
593
 
    if (username)
594
 
        g_debug ("Starting new display for greeter with user %s selected", username);
595
 
    else
596
 
        g_debug ("Starting new display for greeter");
597
 
 
598
 
    display = create_display (seat, "x" /* FIXME greeter_type */);
599
 
    g_signal_connect (display, "ready", G_CALLBACK (display_ready_cb), seat);
600
 
    display_set_select_user_hint (display, username, FALSE, TRUE);
601
 
    if (session_name != NULL)
602
 
        display_set_user_session (display, SESSION_TYPE_LOCAL, session_name);
603
 
 
604
 
    return start_display (seat, display);
 
1113
    }
 
1114
 
 
1115
    session = create_user_session (seat, username);
 
1116
    if (!session)
 
1117
        return FALSE;
 
1118
    if (seat->priv->session_to_activate)
 
1119
        g_object_unref (seat->priv->session_to_activate);
 
1120
    seat->priv->session_to_activate = g_object_ref (session);
 
1121
    session_set_pam_service (session, USER_SERVICE);
 
1122
 
 
1123
    display_server = create_display_server (seat);
 
1124
    session_set_display_server (session, display_server);
 
1125
    if (!display_server_start (display_server))
 
1126
        return FALSE;
 
1127
 
 
1128
    return FALSE;
 
1129
}
 
1130
 
 
1131
static Session *
 
1132
find_guest_session (Seat *seat)
 
1133
{
 
1134
    GList *link;
 
1135
 
 
1136
    for (link = seat->priv->sessions; link; link = link->next)
 
1137
    {
 
1138
        Session *session = link->data;
 
1139
        if (!session_get_is_stopping (session) && session_get_is_guest (session))
 
1140
            return session;
 
1141
    }
 
1142
 
 
1143
    return NULL;
605
1144
}
606
1145
 
607
1146
gboolean
608
1147
seat_switch_to_guest (Seat *seat, const gchar *session_name)
609
1148
{
610
 
    Display *display;
 
1149
    Session *session;
 
1150
    DisplayServer *display_server;
611
1151
 
612
1152
    g_return_val_if_fail (seat != NULL, FALSE);
613
1153
 
615
1155
        return FALSE;
616
1156
 
617
1157
    /* Switch to session if one open */
618
 
    if (seat->priv->guest_username)
 
1158
    session = find_guest_session (seat);
 
1159
    if (session)
619
1160
    {
620
 
        g_debug ("Switching to existing guest account %s", seat->priv->guest_username);
621
 
        return switch_to_user (seat, seat->priv->guest_username, FALSE);
 
1161
        g_debug ("Switching to existing guest account %s", session_get_username (session));
 
1162
        seat_set_active_session (seat, session);
 
1163
        return TRUE;
622
1164
    }
623
1165
 
624
 
    g_debug ("Starting new display for automatic guest login");
625
 
 
626
 
    display = create_display (seat, "x" /* FIXME guest_type */);
627
 
    g_signal_connect (display, "ready", G_CALLBACK (display_ready_cb), seat);
628
 
    display_set_autologin_user (display, NULL, TRUE, 0);
629
 
    if (session_name != NULL)
630
 
        display_set_user_session (display, SESSION_TYPE_LOCAL, session_name);
631
 
 
632
 
    return start_display (seat, display);
 
1166
    display_server = create_display_server (seat);
 
1167
    if (!display_server_start (display_server))
 
1168
        return FALSE;
 
1169
 
 
1170
    session = create_guest_session (seat);
 
1171
    if (!session)
 
1172
        return FALSE;
 
1173
    if (seat->priv->session_to_activate)
 
1174
        g_object_unref (seat->priv->session_to_activate);
 
1175
    seat->priv->session_to_activate = g_object_ref (session);
 
1176
    session_set_pam_service (session, AUTOLOGIN_SERVICE);
 
1177
    session_set_display_server (session, display_server);
 
1178
 
 
1179
    return TRUE;
633
1180
}
634
1181
 
635
1182
gboolean
636
1183
seat_lock (Seat *seat, const gchar *username)
637
1184
{
638
 
    Display *display;
 
1185
    Greeter *greeter_session;
 
1186
    DisplayServer *display_server;
639
1187
 
640
1188
    g_return_val_if_fail (seat != NULL, FALSE);
641
1189
 
645
1193
    g_debug ("Locking seat");
646
1194
 
647
1195
    /* Switch to greeter if one open (shouldn't be though) */
648
 
    if (switch_to_user (seat, NULL, FALSE))
 
1196
    greeter_session = find_greeter_session (seat);
 
1197
    if (greeter_session)
 
1198
    {
 
1199
        g_debug ("Switching to existing greeter");
 
1200
        seat_set_active_session (seat, SESSION (greeter_session));
649
1201
        return TRUE;
650
 
 
651
 
    g_debug ("Starting new display for greeter (lock screen)");
652
 
 
653
 
    display = create_display (seat, "x" /* FIXMEgreeter_type */);
654
 
    g_signal_connect (display, "ready", G_CALLBACK (display_ready_cb), seat);
655
 
    display_set_lock_hint (display, TRUE);
656
 
    display_set_select_user_hint (display, username, FALSE, FALSE);
657
 
 
658
 
    return start_display (seat, display);
 
1202
    }
 
1203
 
 
1204
    display_server = create_display_server (seat);
 
1205
    if (!display_server_start (display_server))
 
1206
        return FALSE;
 
1207
 
 
1208
    greeter_session = create_greeter_session (seat);
 
1209
    if (seat->priv->session_to_activate)
 
1210
        g_object_unref (seat->priv->session_to_activate);
 
1211
    seat->priv->session_to_activate = g_object_ref (greeter_session);
 
1212
    greeter_set_hint (greeter_session, "lock-screen", "true");
 
1213
    if (username)
 
1214
        greeter_set_hint (greeter_session, "select-user", username);
 
1215
    session_set_display_server (SESSION (greeter_session), display_server);
 
1216
 
 
1217
    return TRUE;
659
1218
}
660
1219
 
661
1220
void
683
1242
{
684
1243
}
685
1244
 
686
 
static void
687
 
autologin_greeter_ready_cb (Display *display, Seat *seat)
688
 
{
689
 
    const gchar *autologin_username;
690
 
    gboolean autologin_guest;
691
 
    Display *autologin_display;
692
 
 
693
 
    g_debug ("Greeter ready, starting autologin session");
694
 
 
695
 
    /* Get autologin settings */
696
 
    autologin_username = seat_get_string_property (seat, "autologin-user");
697
 
    if (g_strcmp0 (autologin_username, "") == 0)
698
 
        autologin_username = NULL;
699
 
    autologin_guest = seat_get_boolean_property (seat, "autologin-guest");
700
 
 
701
 
    if (autologin_guest)
702
 
        g_debug ("Starting new display for automatic guest login");
703
 
    else if (autologin_username)
704
 
        g_debug ("Starting new display for automatic login as user %s", autologin_username);
705
 
 
706
 
    autologin_display = create_display (seat, "x" /* FIXMEsession_type */);
707
 
    display_set_autologin_user (autologin_display, autologin_username, autologin_guest, 0);
708
 
 
709
 
    start_display (seat, autologin_display);
710
 
}
711
 
 
712
1245
static gboolean
713
1246
seat_real_start (Seat *seat)
714
1247
{
715
1248
    const gchar *autologin_username;
716
1249
    int autologin_timeout;
717
1250
    gboolean autologin_guest;
718
 
    gboolean do_autologin;
719
1251
    gboolean autologin_in_background;
720
 
    Display *display;
 
1252
    Session *session = NULL;
 
1253
    DisplayServer *display_server;
721
1254
 
722
1255
    g_debug ("Starting seat");
723
1256
 
 
1257
    display_server = create_display_server (seat);
 
1258
 
 
1259
    /* If this display server doesn't have a session running on it, just start it */
 
1260
    if (!display_server_get_start_local_sessions (display_server))
 
1261
        return display_server_start (display_server);
 
1262
 
724
1263
    /* Get autologin settings */
725
1264
    autologin_username = seat_get_string_property (seat, "autologin-user");
726
1265
    if (g_strcmp0 (autologin_username, "") == 0)
728
1267
    autologin_timeout = seat_get_integer_property (seat, "autologin-user-timeout");
729
1268
    autologin_guest = seat_get_boolean_property (seat, "autologin-guest");
730
1269
    autologin_in_background = seat_get_boolean_property (seat, "autologin-in-background");
731
 
    do_autologin = autologin_username != NULL || autologin_guest;
732
 
 
733
 
    /* Background automatic logins need the greeter showing first */
734
 
    if (do_autologin && autologin_in_background && !switch_to_user (seat, NULL, FALSE)) 
735
 
    {
736
 
        g_debug ("Autologin in background, opening greeter first");
737
 
        display = create_display (seat, "x" /* FIXMEgreeter_type */);
738
 
        g_signal_connect (display, "ready", G_CALLBACK (autologin_greeter_ready_cb), seat);
739
 
        if (autologin_timeout > 0)
740
 
            display_set_autologin_user (display, autologin_username, autologin_guest, autologin_timeout);
741
 
        return start_display (seat, display);
742
 
    }
743
 
 
744
 
    if (autologin_guest)
745
 
        g_debug ("Starting new display for automatic guest login");
746
 
    else if (autologin_username)
747
 
        g_debug ("Starting new display for automatic login as user %s", autologin_username);
748
 
    else
749
 
        g_debug ("Starting new display for greeter");
750
 
 
751
 
    display = create_display (seat, "x" /* FIXMEsession_type */);
752
 
    g_signal_connect (display, "ready", G_CALLBACK (display_ready_cb), seat);
753
 
    display_set_autologin_user (display, autologin_username, autologin_guest, autologin_timeout);
754
 
 
755
 
    return start_display (seat, display);
 
1270
 
 
1271
    /* Autologin if configured */
 
1272
    if (autologin_timeout == 0 || autologin_in_background)
 
1273
    {
 
1274
        if (autologin_guest)
 
1275
            session = create_guest_session (seat);
 
1276
        else if (autologin_username != NULL)
 
1277
            session = create_user_session (seat, autologin_username);
 
1278
      
 
1279
        if (session)
 
1280
        {
 
1281
            if (seat->priv->session_to_activate)
 
1282
                g_object_unref (seat->priv->session_to_activate);
 
1283
            seat->priv->session_to_activate = g_object_ref (session);
 
1284
            session_set_pam_service (session, AUTOLOGIN_SERVICE);
 
1285
        }
 
1286
 
 
1287
        /* Load in background if required */
 
1288
        if (autologin_in_background && session)
 
1289
        {
 
1290
            DisplayServer *background_display_server;
 
1291
 
 
1292
            background_display_server = create_display_server (seat);
 
1293
            session_set_display_server (session, background_display_server);
 
1294
            if (!display_server_start (background_display_server))
 
1295
                return FALSE;
 
1296
 
 
1297
            /* Start a greeter as well */
 
1298
            session = NULL;
 
1299
        }
 
1300
    }
 
1301
 
 
1302
    /* Fallback to a greeter */
 
1303
    if (!session)
 
1304
    {
 
1305
        Greeter *greeter_session;
 
1306
 
 
1307
        greeter_session = create_greeter_session (seat);
 
1308
        if (seat->priv->session_to_activate)
 
1309
            g_object_unref (seat->priv->session_to_activate);
 
1310
        seat->priv->session_to_activate = g_object_ref (greeter_session);
 
1311
        session = SESSION (greeter_session);
 
1312
 
 
1313
        if (autologin_timeout)
 
1314
        {
 
1315
            gchar *value;
 
1316
 
 
1317
            value = g_strdup_printf ("%d", autologin_timeout);
 
1318
            greeter_set_hint (greeter_session, "autologin-timeout", value);
 
1319
            g_free (value);
 
1320
            if (autologin_username)
 
1321
                greeter_set_hint (greeter_session, "autologin-user", autologin_username);
 
1322
            if (autologin_guest)
 
1323
                greeter_set_hint (greeter_session, "autologin-guest", "true");
 
1324
        }
 
1325
    }
 
1326
 
 
1327
    /* Fail if can't start a session */
 
1328
    if (!session)
 
1329
    {
 
1330
        seat_stop (seat);
 
1331
        return FALSE;
 
1332
    }
 
1333
 
 
1334
    /* Start display server to show session on */
 
1335
    session_set_display_server (session, display_server);
 
1336
    if (!display_server_start (display_server))
 
1337
        return FALSE;
 
1338
 
 
1339
    return TRUE;
756
1340
}
757
1341
 
758
1342
static DisplayServer *
762
1346
}
763
1347
 
764
1348
static void
765
 
seat_real_set_active_display (Seat *seat, Display *display)
 
1349
seat_real_set_active_session (Seat *seat, Session *session)
766
1350
{
767
 
    GList *link;
768
 
 
769
 
    for (link = seat->priv->displays; link; link = link->next)
770
 
    {
771
 
        Display *d = link->data;
772
 
 
773
 
        if (d == display)
774
 
            continue;
775
 
 
776
 
        /* Stop any greeters and lock any other sessions */
777
 
        if (!display_get_username (d))
778
 
        {
779
 
            g_debug ("Stopping background greeter");
780
 
            display_stop (d);
781
 
        }
782
 
        else
783
 
            display_lock (d);
784
 
    }  
785
1351
}
786
1352
 
787
 
static Display *
788
 
seat_real_get_active_display (Seat *seat)
 
1353
static Session *
 
1354
seat_real_get_active_session (Seat *seat)
789
1355
{
790
1356
    return NULL;
791
1357
}
793
1359
static void
794
1360
seat_real_stop (Seat *seat)
795
1361
{
796
 
    GList *displays, *link;
 
1362
    GList *list, *link;
797
1363
 
798
1364
    check_stopped (seat);
799
1365
    if (seat->priv->stopped)
800
1366
        return;
801
1367
 
802
 
    /* Stop all the displays on the seat. Copy the list as it might be modified if a display stops during this loop */
803
 
    displays = g_list_copy (seat->priv->displays);
804
 
    for (link = displays; link; link = link->next)
805
 
    {
806
 
        Display *display = link->data;
807
 
        display_stop (display);
808
 
    }
809
 
    g_list_free (displays);
 
1368
    /* Stop all the display servers and sessions on the seat. Copy the list as
 
1369
     * it might be modified if a display server / session stops during this loop */
 
1370
    list = g_list_copy (seat->priv->display_servers);
 
1371
    for (link = list; link; link = link->next)
 
1372
        g_object_ref (link->data);
 
1373
    for (link = list; link; link = link->next)
 
1374
    {
 
1375
        DisplayServer *display_server = link->data;
 
1376
        if (!display_server_get_is_stopping (display_server))
 
1377
        {
 
1378
            g_debug ("Stopping display server");
 
1379
            display_server_stop (display_server);
 
1380
        }
 
1381
    }
 
1382
    g_list_free_full (list, g_object_unref);
 
1383
    list = g_list_copy (seat->priv->sessions);
 
1384
    for (link = list; link; link = link->next)
 
1385
        g_object_ref (link->data);
 
1386
    for (link = list; link; link = link->next)
 
1387
    {
 
1388
        Session *session = link->data;
 
1389
        if (!session_get_is_stopping (session))
 
1390
        {
 
1391
            g_debug ("Stopping session");
 
1392
            session_stop (session);
 
1393
        }
 
1394
    }
 
1395
    g_list_free_full (list, g_object_unref);
810
1396
}
811
1397
 
812
1398
static void
826
1412
    self = SEAT (object);
827
1413
 
828
1414
    g_hash_table_unref (self->priv->properties);
829
 
    g_free (self->priv->guest_username);
830
 
    for (link = self->priv->displays; link; link = link->next)
 
1415
    for (link = self->priv->display_servers; link; link = link->next)
831
1416
    {
832
 
        Display *display = link->data;
833
 
        g_signal_handlers_disconnect_matched (display, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
 
1417
        DisplayServer *display_server = link->data;
 
1418
        g_signal_handlers_disconnect_matched (display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
834
1419
    }  
835
 
    g_list_free_full (self->priv->displays, g_object_unref);
 
1420
    g_list_free_full (self->priv->display_servers, g_object_unref);
 
1421
    for (link = self->priv->sessions; link; link = link->next)
 
1422
    {
 
1423
        Session *session = link->data;
 
1424
        g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
 
1425
    }
 
1426
    g_list_free_full (self->priv->sessions, g_object_unref);
 
1427
    if (self->priv->session_to_activate)
 
1428
        g_object_unref (self->priv->session_to_activate);
836
1429
 
837
1430
    G_OBJECT_CLASS (seat_parent_class)->finalize (object);
838
1431
}
845
1438
    klass->setup = seat_real_setup;
846
1439
    klass->start = seat_real_start;
847
1440
    klass->create_display_server = seat_real_create_display_server;
848
 
    klass->set_active_display = seat_real_set_active_display;
849
 
    klass->get_active_display = seat_real_get_active_display;
 
1441
    klass->set_active_session = seat_real_set_active_session;
 
1442
    klass->get_active_session = seat_real_get_active_session;
850
1443
    klass->run_script = seat_real_run_script;
851
1444
    klass->stop = seat_real_stop;
852
1445
 
854
1447
 
855
1448
    g_type_class_add_private (klass, sizeof (SeatPrivate));
856
1449
 
857
 
    signals[DISPLAY_ADDED] =
858
 
        g_signal_new ("display-added",
859
 
                      G_TYPE_FROM_CLASS (klass),
860
 
                      G_SIGNAL_RUN_LAST,
861
 
                      G_STRUCT_OFFSET (SeatClass, display_added),
862
 
                      NULL, NULL,
863
 
                      g_cclosure_marshal_VOID__OBJECT,
864
 
                      G_TYPE_NONE, 1, DISPLAY_TYPE);
865
 
    signals[DISPLAY_REMOVED] =
866
 
        g_signal_new ("display-removed",
867
 
                      G_TYPE_FROM_CLASS (klass),
868
 
                      G_SIGNAL_RUN_LAST,
869
 
                      G_STRUCT_OFFSET (SeatClass, display_removed),
870
 
                      NULL, NULL,
871
 
                      g_cclosure_marshal_VOID__OBJECT,
872
 
                      G_TYPE_NONE, 1, DISPLAY_TYPE);
 
1450
    signals[SESSION_ADDED] =
 
1451
        g_signal_new ("session-added",
 
1452
                      G_TYPE_FROM_CLASS (klass),
 
1453
                      G_SIGNAL_RUN_LAST,
 
1454
                      G_STRUCT_OFFSET (SeatClass, session_added),
 
1455
                      NULL, NULL,
 
1456
                      NULL,
 
1457
                      G_TYPE_NONE, 1, SESSION_TYPE);
 
1458
    signals[RUNNING_USER_SESSION] =
 
1459
        g_signal_new ("running-user-session",
 
1460
                      G_TYPE_FROM_CLASS (klass),
 
1461
                      G_SIGNAL_RUN_LAST,
 
1462
                      G_STRUCT_OFFSET (SeatClass, running_user_session),
 
1463
                      NULL, NULL,
 
1464
                      NULL,
 
1465
                      G_TYPE_NONE, 1, SESSION_TYPE);
 
1466
    signals[SESSION_REMOVED] =
 
1467
        g_signal_new ("session-removed",
 
1468
                      G_TYPE_FROM_CLASS (klass),
 
1469
                      G_SIGNAL_RUN_LAST,
 
1470
                      G_STRUCT_OFFSET (SeatClass, session_removed),
 
1471
                      NULL, NULL,
 
1472
                      NULL,
 
1473
                      G_TYPE_NONE, 1, SESSION_TYPE);
873
1474
    signals[STOPPED] =
874
1475
        g_signal_new ("stopped",
875
1476
                      G_TYPE_FROM_CLASS (klass),
876
1477
                      G_SIGNAL_RUN_LAST,
877
1478
                      G_STRUCT_OFFSET (SeatClass, stopped),
878
1479
                      NULL, NULL,
879
 
                      g_cclosure_marshal_VOID__VOID,
 
1480
                      NULL,
880
1481
                      G_TYPE_NONE, 0);
881
1482
}