]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - src/display.c
1d572853b53e45be68d31e07002645b277eed136
[sojka/lightdm.git] / src / display.c
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 "pam-session.h"
22 #include "greeter.h"
23
24 enum {
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 typedef enum
39 {
40     SESSION_NONE = 0,
41     SESSION_GREETER_PRE_CONNECT,
42     SESSION_GREETER,
43     SESSION_GREETER_AUTHENTICATED,
44     SESSION_USER
45 } SessionType;
46
47 struct DisplayPrivate
48 {
49     /* Display server */
50     DisplayServer *display_server;
51
52     /* Greeter session */
53     gchar *greeter_session;
54
55     /* TRUE if the user list should be shown */
56     gboolean greeter_hide_users;
57
58     /* Session requested to log into */
59     gchar *user_session;
60
61     /* Program to run sessions through */
62     gchar *session_wrapper;
63
64     /* PAM service to authenticate against */
65     gchar *pam_service;
66
67     /* PAM service to authenticate against for automatic logins */
68     gchar *pam_autologin_service;
69   
70     /* TRUE if a session should be started on greeter quit */
71     gboolean start_session_on_greeter_quit;
72
73     /* TRUE if in a user session */
74     gboolean in_user_session;
75
76     /* TRUE if have got an X server / started a greeter */
77     gboolean is_ready;
78
79     /* Session process */
80     Session *session;
81
82     /* Communication link to greeter */
83     Greeter *greeter;
84
85     /* User that should be automatically logged in */
86     gchar *autologin_user;
87     gboolean autologin_guest;
88     gint autologin_timeout;
89
90     /* TRUE if start greeter if fail to login */
91     gboolean start_greeter_if_fail;
92
93     /* Hint to select user in greeter */
94     gchar *select_user_hint;
95     gboolean select_guest_hint;
96
97     /* TRUE if allowed to log into guest account */
98     gboolean allow_guest;
99
100     /* TRUE if stopping the display (waiting for dispaly server, greeter and session to stop) */
101     gboolean stopping;
102
103     /* TRUE if stopped */
104     gboolean stopped;
105 };
106
107 G_DEFINE_TYPE (Display, display, G_TYPE_OBJECT);
108
109 static gboolean start_greeter_session (Display *display);
110 static gboolean start_user_session (Display *display, PAMSession *authentication);
111
112 Display *
113 display_new (DisplayServer *display_server)
114 {
115     Display *display = g_object_new (DISPLAY_TYPE, NULL);
116
117     display->priv->display_server = g_object_ref (display_server);
118
119     return display;
120 }
121
122 DisplayServer *
123 display_get_display_server (Display *display)
124 {
125     g_return_val_if_fail (display != NULL, NULL);
126     return display->priv->display_server;
127 }
128
129 const gchar *
130 display_get_username (Display *display)
131 {
132     g_return_val_if_fail (display != NULL, NULL);
133
134     if (!display->priv->session || !display->priv->in_user_session)
135         return NULL;
136
137     return user_get_name (session_get_user (display->priv->session));
138 }
139
140 Session *
141 display_get_session (Display *display)
142 {
143     g_return_val_if_fail (display != NULL, NULL);
144     return display->priv->session;
145 }
146
147 void
148 display_set_greeter_session (Display *display, const gchar *greeter_session)
149 {
150     g_return_if_fail (display != NULL);
151     g_free (display->priv->greeter_session);
152     display->priv->greeter_session = g_strdup (greeter_session);
153 }
154
155 void
156 display_set_session_wrapper (Display *display, const gchar *session_wrapper)
157 {
158     g_return_if_fail (display != NULL);
159     g_free (display->priv->session_wrapper);
160     display->priv->session_wrapper = g_strdup (session_wrapper);
161 }
162
163 void
164 display_set_allow_guest (Display *display, gboolean allow_guest)
165 {
166     g_return_if_fail (display != NULL);
167     display->priv->allow_guest = allow_guest;
168 }
169
170 void
171 display_set_autologin_user (Display *display, const gchar *username, gboolean is_guest, gint timeout)
172 {
173     g_return_if_fail (display != NULL);
174     g_free (display->priv->autologin_user);
175     display->priv->autologin_user = g_strdup (username);
176     display->priv->autologin_guest = is_guest;
177     display->priv->autologin_timeout = timeout;
178 }
179
180 void
181 display_set_select_user_hint (Display *display, const gchar *username, gboolean is_guest)
182 {
183     g_return_if_fail (display != NULL);
184     g_free (display->priv->select_user_hint);
185     display->priv->select_user_hint = g_strdup (username);
186     display->priv->select_guest_hint = is_guest;
187 }
188
189 void
190 display_set_hide_users_hint (Display *display, gboolean hide_users)
191 {
192     g_return_if_fail (display != NULL);
193     display->priv->greeter_hide_users = hide_users;
194 }
195
196 void
197 display_set_user_session (Display *display, const gchar *session_name)
198 {
199     g_return_if_fail (display != NULL);
200     g_free (display->priv->user_session);
201     display->priv->user_session = g_strdup (session_name);
202 }
203
204 static gboolean
205 switch_to_user (Display *display, User *user)
206 {
207     gboolean result;
208     g_signal_emit (display, signals[SWITCH_TO_USER], 0, user, &result);
209     return result;
210 }
211
212 static gboolean
213 switch_to_guest (Display *display)
214 {
215     gboolean result;
216     g_signal_emit (display, signals[SWITCH_TO_GUEST], 0, &result);
217     return result;
218 }
219
220 static gchar *
221 get_guest_username (Display *display)
222 {
223     gchar *username;
224     g_signal_emit (display, signals[GET_GUEST_USERNAME], 0, &username);
225     return username;
226 }
227
228 static void
229 check_stopped (Display *display)
230 {
231     if (display->priv->stopping &&
232         !display->priv->stopped &&
233         display->priv->display_server == NULL &&
234         display->priv->session == NULL)
235     {
236         display->priv->stopped = TRUE;
237         g_debug ("Display stopped");
238         g_signal_emit (display, signals[STOPPED], 0);
239     }
240 }
241
242 static void
243 autologin_authentication_result_cb (PAMSession *authentication, int result, Display *display)
244 {
245     g_signal_handlers_disconnect_matched (authentication, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
246     if (display->priv->stopping)
247         return;
248
249     gboolean started_session = FALSE;
250
251     if (result == PAM_SUCCESS)
252     {
253         g_debug ("User %s authorized", pam_session_get_username (authentication));
254         started_session = start_user_session (display, authentication);
255         if (!started_session)
256             g_debug ("Failed to start autologin session");
257     }
258     else
259         g_debug ("Autologin failed authentication");
260
261     if (!started_session && display->priv->start_greeter_if_fail)
262     {
263         display_set_autologin_user (display, NULL, FALSE, 0);
264         if (display->priv->autologin_user)
265             display_set_select_user_hint (display, display->priv->autologin_user, FALSE);
266         started_session = start_greeter_session (display);
267     }
268
269     if (!started_session)
270         display_stop (display);
271 }
272
273 static gboolean
274 autologin (Display *display, const gchar *username, const gchar *service, gboolean start_greeter_if_fail)
275 {
276     gboolean result;
277     PAMSession *authentication;
278     GError *error = NULL;
279
280     display->priv->start_greeter_if_fail = start_greeter_if_fail;
281
282     display->priv->in_user_session = TRUE;
283     authentication = pam_session_new (service, username);
284     pam_session_set_interactive (authentication, FALSE);
285     g_signal_connect (authentication, "authentication-result", G_CALLBACK (autologin_authentication_result_cb), display);
286
287     result = pam_session_authenticate (authentication, &error);
288     if (error)
289         g_debug ("Failed to start autologin session for %s: %s", username, error->message);
290     if (!result)
291     {
292         g_signal_handlers_disconnect_matched (authentication, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
293         g_object_unref (authentication);
294     }
295     g_clear_error (&error);
296
297     return result;
298 }
299
300 static gboolean
301 autologin_guest (Display *display, const gchar *service, gboolean start_greeter_if_fail)
302 {
303     gchar *username;
304     gboolean result;
305
306     username = get_guest_username (display);
307     if (!username)
308     {
309         g_debug ("Can't autologin guest, no guest account");
310         return FALSE;
311     }
312
313     result = autologin (display, username, service, start_greeter_if_fail);
314     g_free (username);
315
316     return result;
317 }
318
319 static gboolean
320 cleanup_after_session (Display *display)
321 {
322     g_signal_handlers_disconnect_matched (display->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
323     g_object_unref (display->priv->session);
324     display->priv->session = NULL;
325
326     if (display->priv->stopping)
327     {
328         check_stopped (display);
329         return TRUE;
330     }
331
332     return FALSE;
333 }
334
335 static void
336 greeter_session_stopped_cb (Session *session, Display *display)
337 {
338     gboolean started_session = FALSE;
339
340     g_debug ("Greeter quit");
341
342     if (cleanup_after_session (display))
343         return;
344
345     if (!display->priv->display_server)
346         return;
347
348     /* Start the session for the authenticated user */
349     if (display->priv->start_session_on_greeter_quit)
350     {
351         if (greeter_get_guest_authenticated (display->priv->greeter))
352         {
353             started_session = autologin_guest (display, display->priv->pam_autologin_service, FALSE);
354             if (!started_session)
355                 g_debug ("Failed to start guest session");
356         }
357         else
358         {
359             display->priv->in_user_session = TRUE;
360             started_session = start_user_session (display, greeter_get_authentication (display->priv->greeter));
361             if (!started_session)
362                 g_debug ("Failed to start user session");
363         }
364     }
365
366     g_signal_handlers_disconnect_matched (display->priv->greeter, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
367     g_object_unref (display->priv->greeter);
368     display->priv->greeter = NULL;
369
370     if (!started_session)
371         display_stop (display);
372 }
373
374 static void
375 user_session_stopped_cb (Session *session, Display *display)
376 {
377     g_debug ("User session quit");
378
379     if (cleanup_after_session (display))
380         return;
381
382     /* This display has ended */
383     display_stop (display);
384 }
385
386 static Session *
387 create_session (Display *display, PAMSession *authentication, const gchar *session_name, gboolean is_greeter, const gchar *log_filename)
388 {
389     gchar *sessions_dir, *filename, *path, *command = NULL;
390     GKeyFile *session_desktop_file;
391     Session *session;
392     gboolean result;
393     GError *error = NULL;
394
395     g_debug ("Starting session %s as user %s logging to %s", session_name, pam_session_get_username (authentication), log_filename);
396
397     // FIXME: This is X specific, move into xsession.c
398     if (is_greeter)
399         sessions_dir = config_get_string (config_get_instance (), "LightDM", "xgreeters-directory");
400     else
401         sessions_dir = config_get_string (config_get_instance (), "LightDM", "xsessions-directory");
402     filename = g_strdup_printf ("%s.desktop", session_name);
403     path = g_build_filename (sessions_dir, filename, NULL);
404     g_free (sessions_dir);
405     g_free (filename);
406
407     session_desktop_file = g_key_file_new ();
408     result = g_key_file_load_from_file (session_desktop_file, path, G_KEY_FILE_NONE, &error);
409     if (error)
410         g_debug ("Failed to load session file %s: %s:", path, error->message);
411     g_clear_error (&error);
412     if (result)
413     {
414         command = g_key_file_get_string (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL);
415         if (!command)
416             g_debug ("No command in session file %s", path);
417     }
418     g_key_file_free (session_desktop_file);
419     g_free (path);
420     if (!command)
421         return NULL;
422     if (display->priv->session_wrapper && !is_greeter)
423     {
424         gchar *wrapper;
425
426         wrapper = g_find_program_in_path (display->priv->session_wrapper);
427         if (wrapper)
428         {
429             gchar *t = command;
430             command = g_strdup_printf ("%s '%s'", wrapper, command);
431             g_free (t);
432             g_free (wrapper);
433         }
434     }
435
436     g_signal_emit (display, signals[CREATE_SESSION], 0, &session);
437     g_return_val_if_fail (session != NULL, NULL);
438
439     if (is_greeter)
440         g_signal_connect_after (session, "stopped", G_CALLBACK (greeter_session_stopped_cb), display);
441     else
442         g_signal_connect_after (session, "stopped", G_CALLBACK (user_session_stopped_cb), display);
443     session_set_is_greeter (session, is_greeter);
444     session_set_authentication (session, authentication);
445     session_set_command (session, command);
446
447     session_set_env (session, "DESKTOP_SESSION", session_name); // FIXME: Apparently deprecated?
448     session_set_env (session, "GDMSESSION", session_name); // FIXME: Not cross-desktop
449
450     session_set_log_file (session, log_filename);
451
452     /* Connect using the session bus */
453     if (getuid () != 0)
454     {
455         if (g_getenv ("DBUS_SESSION_BUS_ADDRESS"))
456             session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
457         session_set_env (session, "LDM_BUS", "SESSION");
458         if (g_getenv ("LD_PRELOAD"))
459             session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
460         if (g_getenv ("LD_LIBRARY_PATH"))
461             session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
462         if (g_getenv ("PATH"))
463             session_set_env (session, "PATH", g_getenv ("PATH"));
464     }
465
466     /* Variables required for regression tests */
467     if (g_getenv ("LIGHTDM_TEST_STATUS_SOCKET"))
468     {
469         session_set_env (session, "LIGHTDM_TEST_STATUS_SOCKET", g_getenv ("LIGHTDM_TEST_STATUS_SOCKET"));
470         session_set_env (session, "LIGHTDM_TEST_CONFIG", g_getenv ("LIGHTDM_TEST_CONFIG"));
471         session_set_env (session, "LIGHTDM_TEST_HOME_DIR", g_getenv ("LIGHTDM_TEST_HOME_DIR"));
472         session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
473         session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
474     }
475
476     return session;
477 }
478
479 static void
480 display_set_is_ready (Display *display)
481 {
482     if (display->priv->is_ready)
483         return;
484
485     display->priv->is_ready = TRUE;
486     g_signal_emit (display, signals[READY], 0);
487 }
488
489 static void
490 greeter_connected_cb (Greeter *greeter, Display *display)
491 {
492     // FIXME: Should wait for greeter to signal completely ready if it supports it
493     g_debug ("Greeter connected, display is ready");
494     display_set_is_ready (display);
495 }
496
497 static PAMSession *
498 greeter_start_authentication_cb (Greeter *greeter, const gchar *username, Display *display)
499 {
500     return pam_session_new (display->priv->pam_service, username);
501 }
502
503 static gboolean
504 greeter_start_session_cb (Greeter *greeter, const gchar *session_name, Display *display)
505 {
506     /* Store the session to use, use the default if none was requested */
507     if (session_name)
508     {
509         g_free (display->priv->user_session);
510         display->priv->user_session = g_strdup (session_name);
511     }
512
513     /* Stop this display if that session already exists and can switch to it */
514     if (greeter_get_guest_authenticated (greeter))
515     {
516         if (switch_to_guest (display))
517             return TRUE;
518
519         /* Set to login as guest */
520         display_set_autologin_user (display, NULL, TRUE, 0);
521     }
522     else
523     {
524        if (switch_to_user (display, pam_session_get_user (greeter_get_authentication (display->priv->greeter))))
525            return TRUE;
526     }
527
528     /* Stop the greeter, the session will start when the greeter has quit */
529     g_debug ("Stopping greeter");
530     display->priv->start_session_on_greeter_quit = TRUE;
531     session_stop (display->priv->session);
532
533     return TRUE;
534 }
535
536 static void
537 greeter_authentication_result_cb (PAMSession *authentication, int result, Display *display)
538 {
539     gboolean start_result = FALSE;
540
541     if (result == PAM_SUCCESS)
542         g_signal_emit (display, signals[START_GREETER], 0, &start_result);
543     else
544         g_debug ("Greeter user failed authentication");
545
546     if (start_result)
547         display_stop (display);
548 }
549
550 static gboolean
551 start_greeter_session (Display *display)
552 {
553     User *user;
554     gchar *log_dir, *filename, *log_filename;
555     PAMSession *authentication;
556     gboolean result;
557     GError *error = NULL;
558
559     g_debug ("Starting greeter session");
560
561     if (getuid () != 0)
562         user = accounts_get_current_user ();
563     else
564     {
565         gchar *greeter_user;
566
567         greeter_user = config_get_string (config_get_instance (), "LightDM", "greeter-user");
568         if (!greeter_user)
569         {
570             g_warning ("Greeter must not be run as root");
571             return FALSE;
572         }
573
574         user = accounts_get_user_by_name (greeter_user);
575         if (!user)
576             g_debug ("Unable to start greeter, user %s does not exist", greeter_user);
577         g_free (greeter_user);
578         if (!user)
579             return FALSE;
580     }
581     display->priv->in_user_session = FALSE;
582
583     log_dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
584     filename = g_strdup_printf ("%s-greeter.log", display_server_get_name (display->priv->display_server));
585     log_filename = g_build_filename (log_dir, filename, NULL);
586     g_free (log_dir);
587     g_free (filename);
588   
589     /* Authenticate as the requested user */
590     authentication = pam_session_new (display->priv->pam_autologin_service, user_get_name (user));
591     pam_session_set_interactive (authentication, FALSE);
592     g_signal_connect (G_OBJECT (authentication), "authentication-result", G_CALLBACK (greeter_authentication_result_cb), display);
593     g_object_unref (user);
594
595     display->priv->session = create_session (display, authentication, display->priv->greeter_session, TRUE, log_filename);
596     g_object_unref (authentication);
597     g_free (log_filename);
598
599     if (!display->priv->session)
600         return FALSE;
601
602     display->priv->greeter = greeter_new (display->priv->session);
603     g_signal_connect (G_OBJECT (display->priv->greeter), "connected", G_CALLBACK (greeter_connected_cb), display);
604     g_signal_connect (G_OBJECT (display->priv->greeter), "start-authentication", G_CALLBACK (greeter_start_authentication_cb), display);
605     g_signal_connect (G_OBJECT (display->priv->greeter), "start-session", G_CALLBACK (greeter_start_session_cb), display);
606     if (display->priv->autologin_timeout)
607     {
608         gchar *value = g_strdup_printf ("%d", display->priv->autologin_timeout);
609         greeter_set_hint (display->priv->greeter, "autologin-timeout", value);
610         g_free (value);
611         if (display->priv->autologin_user)
612             greeter_set_hint (display->priv->greeter, "autologin-user", display->priv->autologin_user);
613         else if (display->priv->autologin_guest)
614             greeter_set_hint (display->priv->greeter, "autologin-guest", "true");
615     }
616     if (display->priv->select_user_hint)
617         greeter_set_hint (display->priv->greeter, "select-user", display->priv->select_user_hint);
618     else if (display->priv->select_guest_hint)
619         greeter_set_hint (display->priv->greeter, "select-guest", "true");
620     greeter_set_hint (display->priv->greeter, "default-session", display->priv->user_session);
621     greeter_set_allow_guest (display->priv->greeter, display->priv->allow_guest);
622     greeter_set_hint (display->priv->greeter, "has-guest-account", display->priv->allow_guest ? "true" : "false");
623     greeter_set_hint (display->priv->greeter, "hide-users", display->priv->greeter_hide_users ? "true" : "false");
624
625     result = pam_session_authenticate (session_get_authentication (display->priv->session), &error);
626     if (error)
627         g_debug ("Error authenticating greeter user: %s", error->message);
628     g_clear_error (&error);
629
630     return result;
631 }
632
633 static gboolean
634 display_start_greeter (Display *display)
635 {
636     if (!greeter_start (display->priv->greeter))
637     {
638         g_debug ("Failed to start greeter protocol");
639
640         g_signal_handlers_disconnect_matched (display->priv->greeter, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
641         g_object_unref (display->priv->greeter);
642         display->priv->greeter = NULL;
643
644         return TRUE;
645     }
646   
647     if (!session_start (SESSION (display->priv->session)))
648     {     
649         g_debug ("Failed to start greeter session");
650         return TRUE;
651     }
652
653     return FALSE;
654 }
655
656 static gboolean
657 start_user_session (Display *display, PAMSession *authentication)
658 {
659     User *user;
660     gchar *log_filename;
661     gboolean result;
662
663     g_debug ("Starting user session");
664
665     user = pam_session_get_user (authentication);
666
667     /* Update user's xsession setting */
668     user_set_xsession (user, display->priv->user_session);
669
670     // FIXME: Copy old error file
671     log_filename = g_build_filename (user_get_home_directory (user), ".xsession-errors", NULL);
672
673     display->priv->session = create_session (display, authentication, display->priv->user_session, FALSE, log_filename);
674     g_free (log_filename);
675
676     if (!display->priv->session)
677         return FALSE;
678
679     g_signal_emit (display, signals[START_SESSION], 0, &result);
680
681     return !result;
682 }
683
684 static gboolean
685 display_start_session (Display *display)
686 {
687     if (!session_start (SESSION (display->priv->session)))
688         return TRUE;
689
690     // FIXME: Wait for session to indicate it is ready (maybe)
691     display_set_is_ready (display);
692
693     return FALSE;
694 }
695
696 static void
697 display_server_stopped_cb (DisplayServer *server, Display *display)
698 {
699     g_debug ("Display server stopped");
700
701     g_signal_handlers_disconnect_matched (display->priv->display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
702     g_object_unref (display->priv->display_server);
703     display->priv->display_server = NULL;
704
705     /* Stop this display, it will be restarted by the seat if necessary */
706     display_stop (display);
707 }
708
709 static void
710 display_server_ready_cb (DisplayServer *display_server, Display *display)
711 {
712     gboolean result;
713     gboolean started_session = FALSE;
714
715     g_signal_emit (display, signals[DISPLAY_SERVER_READY], 0, &result);
716     if (!result)
717     {
718         display_stop (display);
719         return;
720     }
721
722     /* Don't run any sessions on local terminals */
723     if (!display_server_get_start_local_sessions (display_server))
724         return;
725
726     /* Automatically log in */
727     if (display->priv->autologin_guest)
728     {
729         g_debug ("Automatically logging in as guest");
730         started_session = autologin_guest (display, display->priv->pam_autologin_service, TRUE);
731         if (!started_session)
732             g_debug ("Failed to autologin as guest");
733     }
734     else if (display->priv->autologin_user)
735     {
736         g_debug ("Automatically logging in user %s", display->priv->autologin_user);
737         started_session = autologin (display, display->priv->autologin_user, display->priv->pam_autologin_service, TRUE);
738         if (!started_session)
739             g_debug ("Failed to autologin user %s", display->priv->autologin_user);
740     }
741     else if (display->priv->select_user_hint)
742     {
743         g_debug ("Logging in user %s", display->priv->select_user_hint);
744         started_session = autologin (display, display->priv->select_user_hint, display->priv->pam_service, TRUE);
745         if (!started_session)
746             g_debug ("Failed to login user %s", display->priv->select_user_hint);
747     }
748     else if (display->priv->select_guest_hint)
749     {
750         g_debug ("Logging in as guest");
751         started_session = autologin_guest (display, display->priv->pam_service, TRUE);
752         if (!started_session)
753             g_debug ("Failed login as guest");
754     }
755
756     /* Finally start a greeter */
757     if (!started_session)
758     {
759         started_session = start_greeter_session (display);
760         if (!started_session)
761             g_debug ("Failed to start greeter");
762     }
763
764     if (!started_session)
765         display_stop (display);
766 }
767
768 gboolean
769 display_start (Display *display)
770 {
771     g_return_val_if_fail (display != NULL, FALSE);
772
773     g_signal_connect (G_OBJECT (display->priv->display_server), "ready", G_CALLBACK (display_server_ready_cb), display);
774     g_signal_connect (G_OBJECT (display->priv->display_server), "stopped", G_CALLBACK (display_server_stopped_cb), display);
775
776     if (!display_server_start (display->priv->display_server))
777         return FALSE;
778
779     return TRUE;
780 }
781
782 void
783 display_stop (Display *display)
784 {
785     g_return_if_fail (display != NULL);
786
787     if (!display->priv->stopping)
788     {
789         g_debug ("Stopping display");
790
791         display->priv->stopping = TRUE;
792
793         if (display->priv->display_server)
794             display_server_stop (display->priv->display_server);
795         if (display->priv->session)
796         {
797             if (session_stop (display->priv->session))
798             {
799                 g_object_unref (display->priv->session);
800                 display->priv->session = NULL;
801             }
802         }
803     }
804
805     check_stopped (display);
806 }
807
808 gboolean
809 display_get_is_ready (Display *display)
810 {
811     g_return_val_if_fail (display != NULL, FALSE);
812
813     return display->priv->is_ready;
814 }
815
816 void
817 display_unlock (Display *display)
818 {
819     g_return_if_fail (display != NULL);
820
821     if (!display->priv->session)
822         return;
823
824     g_debug ("Unlocking display");
825
826     session_unlock (display->priv->session);
827 }
828
829 static gboolean
830 display_real_switch_to_user (Display *display, User *user)
831 {
832     return FALSE;
833 }
834
835 static gboolean
836 display_real_switch_to_guest (Display *display)
837 {
838     return FALSE;
839 }
840
841 static gchar *
842 display_real_get_guest_username (Display *display)
843 {
844     return NULL;
845 }
846
847 static void
848 display_init (Display *display)
849 {
850     display->priv = G_TYPE_INSTANCE_GET_PRIVATE (display, DISPLAY_TYPE, DisplayPrivate);
851     display->priv->pam_service = g_strdup ("lightdm");
852     display->priv->pam_autologin_service = g_strdup ("lightdm-autologin");
853 }
854
855 static void
856 display_finalize (GObject *object)
857 {
858     Display *self;
859
860     self = DISPLAY (object);
861
862     if (self->priv->display_server)
863         g_object_unref (self->priv->display_server);
864     g_free (self->priv->greeter_session);
865     if (self->priv->greeter)
866         g_object_unref (self->priv->greeter);
867     g_free (self->priv->session_wrapper);
868     g_free (self->priv->pam_service);
869     g_free (self->priv->pam_autologin_service);
870     if (self->priv->session)
871         g_object_unref (self->priv->session);
872     g_free (self->priv->autologin_user);
873     g_free (self->priv->select_user_hint);
874     g_free (self->priv->user_session);
875
876     G_OBJECT_CLASS (display_parent_class)->finalize (object);
877 }
878
879 static void
880 display_class_init (DisplayClass *klass)
881 {
882     GObjectClass *object_class = G_OBJECT_CLASS (klass);
883
884     klass->switch_to_user = display_real_switch_to_user;
885     klass->switch_to_guest = display_real_switch_to_guest;
886     klass->get_guest_username = display_real_get_guest_username;
887     klass->start_greeter = display_start_greeter;
888     klass->start_session = display_start_session;
889     object_class->finalize = display_finalize;
890
891     g_type_class_add_private (klass, sizeof (DisplayPrivate));
892
893     signals[CREATE_SESSION] =
894         g_signal_new ("create-session",
895                       G_TYPE_FROM_CLASS (klass),
896                       G_SIGNAL_RUN_LAST,
897                       G_STRUCT_OFFSET (DisplayClass, create_session),
898                       NULL, NULL,
899                       ldm_marshal_OBJECT__VOID,
900                       SESSION_TYPE, 0);
901     signals[READY] =
902         g_signal_new ("ready",
903                       G_TYPE_FROM_CLASS (klass),
904                       G_SIGNAL_RUN_LAST,
905                       G_STRUCT_OFFSET (DisplayClass, ready),
906                       NULL, NULL,
907                       g_cclosure_marshal_VOID__VOID,
908                       G_TYPE_NONE, 0);
909     signals[SWITCH_TO_USER] =
910         g_signal_new ("switch-to-user",
911                       G_TYPE_FROM_CLASS (klass),
912                       G_SIGNAL_RUN_LAST,
913                       G_STRUCT_OFFSET (DisplayClass, switch_to_user),
914                       g_signal_accumulator_true_handled,
915                       NULL,
916                       ldm_marshal_BOOLEAN__OBJECT,
917                       G_TYPE_BOOLEAN, 1, USER_TYPE);
918     signals[SWITCH_TO_GUEST] =
919         g_signal_new ("switch-to-guest",
920                       G_TYPE_FROM_CLASS (klass),
921                       G_SIGNAL_RUN_LAST,
922                       G_STRUCT_OFFSET (DisplayClass, switch_to_guest),
923                       g_signal_accumulator_true_handled,
924                       NULL,
925                       ldm_marshal_BOOLEAN__VOID,
926                       G_TYPE_BOOLEAN, 0);
927     signals[GET_GUEST_USERNAME] =
928         g_signal_new ("get-guest-username",
929                       G_TYPE_FROM_CLASS (klass),
930                       G_SIGNAL_RUN_LAST,
931                       G_STRUCT_OFFSET (DisplayClass, get_guest_username),
932                       g_signal_accumulator_first_wins,
933                       NULL,
934                       ldm_marshal_STRING__VOID,
935                       G_TYPE_STRING, 0);
936     signals[DISPLAY_SERVER_READY] =
937         g_signal_new ("display-server-ready",
938                       G_TYPE_FROM_CLASS (klass),
939                       G_SIGNAL_RUN_LAST,
940                       G_STRUCT_OFFSET (DisplayClass, display_server_ready),
941                       NULL, NULL,
942                       ldm_marshal_BOOLEAN__VOID,
943                       G_TYPE_BOOLEAN, 0);
944     signals[START_GREETER] =
945         g_signal_new ("start-greeter",
946                       G_TYPE_FROM_CLASS (klass),
947                       G_SIGNAL_RUN_LAST,
948                       G_STRUCT_OFFSET (DisplayClass, start_greeter),
949                       g_signal_accumulator_true_handled, NULL,
950                       ldm_marshal_BOOLEAN__VOID,
951                       G_TYPE_BOOLEAN, 0);
952     signals[START_SESSION] =
953         g_signal_new ("start-session",
954                       G_TYPE_FROM_CLASS (klass),
955                       G_SIGNAL_RUN_LAST,
956                       G_STRUCT_OFFSET (DisplayClass, start_session),
957                       g_signal_accumulator_true_handled, NULL,
958                       ldm_marshal_BOOLEAN__VOID,
959                       G_TYPE_BOOLEAN, 0);
960     signals[STOPPED] =
961         g_signal_new ("stopped",
962                       G_TYPE_FROM_CLASS (klass),
963                       G_SIGNAL_RUN_LAST,
964                       G_STRUCT_OFFSET (DisplayClass, stopped),
965                       NULL, NULL,
966                       g_cclosure_marshal_VOID__VOID,
967                       G_TYPE_NONE, 0);
968 }