]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blob - src/seat.c
Set $XDG_CURRENT_DESKTOP if specified in the xsession file
[sojka/lightdm.git] / src / seat.c
1 /*
2  * Copyright (C) 2010-2011 Robert Ancell.
3  * Author: Robert Ancell <robert.ancell@canonical.com>
4  * 
5  * This program is free software: you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License as published by the Free Software
7  * Foundation, either version 3 of the License, or (at your option) any later
8  * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
9  * license.
10  */
11
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sys/wait.h>
15
16 #include "seat.h"
17 #include "configuration.h"
18 #include "guest-account.h"
19 #include "greeter.h"
20 #include "session-config.h"
21
22 enum {
23     SESSION_ADDED,
24     RUNNING_USER_SESSION,
25     SESSION_REMOVED,
26     STOPPED,
27     LAST_SIGNAL
28 };
29 static guint signals[LAST_SIGNAL] = { 0 };
30
31 struct SeatPrivate
32 {
33     /* Configuration for this seat */
34     GHashTable *properties;
35
36     /* TRUE if able to switch users */
37     gboolean can_switch;
38
39     /* TRUE if display server can be shared for sessions */
40     gboolean share_display_server;
41
42     /* The display servers on this seat */
43     GList *display_servers;
44
45     /* The sessions on this seat */
46     GList *sessions;
47
48     /* The last session set to active */
49     Session *active_session;
50
51     /* The session to set active when it starts */
52     Session *session_to_activate;
53   
54     /* TRUE once we have started */
55     gboolean started;
56
57     /* TRUE if stopping this seat (waiting for displays to stop) */
58     gboolean stopping;
59
60     /* TRUE if stopped */
61     gboolean stopped;
62 };
63
64 /* PAM services to use */
65 #define GREETER_SERVICE   "lightdm-greeter"
66 #define USER_SERVICE      "lightdm"
67 #define AUTOLOGIN_SERVICE "lightdm-autologin"
68
69 G_DEFINE_TYPE (Seat, seat, G_TYPE_OBJECT);
70
71 typedef struct
72 {
73     const gchar *name;
74     GType type;
75 } SeatModule;
76 static GHashTable *seat_modules = NULL;
77
78 // FIXME: Make a get_display_server() that re-uses display servers if supported
79 static DisplayServer *create_display_server (Seat *seat, const gchar *session_type);
80 static Greeter *create_greeter_session (Seat *seat);
81 static void start_session (Seat *seat, Session *session);
82
83 void
84 seat_register_module (const gchar *name, GType type)
85 {
86     SeatModule *module;
87
88     if (!seat_modules)
89         seat_modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
90
91     g_debug ("Registered seat module %s", name);
92
93     module = g_malloc0 (sizeof (SeatModule));
94     module->name = g_strdup (name);
95     module->type = type;
96     g_hash_table_insert (seat_modules, g_strdup (name), module);
97 }
98
99 Seat *
100 seat_new (const gchar *module_name)
101 {
102     Seat *seat;
103     SeatModule *m = NULL;
104   
105     g_return_val_if_fail (module_name != NULL, NULL);
106
107     if (seat_modules)
108         m = g_hash_table_lookup (seat_modules, module_name);
109     if (!m)
110         return NULL;
111
112     seat = g_object_new (m->type, NULL);
113
114     return seat;
115 }
116
117 void
118 seat_set_property (Seat *seat, const gchar *name, const gchar *value)
119 {
120     g_return_if_fail (seat != NULL);
121     g_hash_table_insert (seat->priv->properties, g_strdup (name), g_strdup (value));
122 }
123
124 const gchar *
125 seat_get_string_property (Seat *seat, const gchar *name)
126 {
127     g_return_val_if_fail (seat != NULL, NULL);
128     return g_hash_table_lookup (seat->priv->properties, name);
129 }
130
131 gboolean
132 seat_get_boolean_property (Seat *seat, const gchar *name)
133 {
134     return g_strcmp0 (seat_get_string_property (seat, name), "true") == 0;
135 }
136
137 gint
138 seat_get_integer_property (Seat *seat, const gchar *name)
139 {
140     const gchar *value;
141
142     value = seat_get_string_property (seat, name);
143     return value ? atoi (value) : 0;
144 }
145
146 void
147 seat_set_can_switch (Seat *seat, gboolean can_switch)
148 {
149     g_return_if_fail (seat != NULL);
150
151     seat->priv->can_switch = can_switch;
152 }
153
154 void
155 seat_set_share_display_server (Seat *seat, gboolean share_display_server)
156 {
157     g_return_if_fail (seat != NULL);
158
159     seat->priv->share_display_server = share_display_server;
160 }
161
162 gboolean
163 seat_start (Seat *seat)
164 {
165     g_return_val_if_fail (seat != NULL, FALSE);
166   
167     SEAT_GET_CLASS (seat)->setup (seat);
168     return SEAT_GET_CLASS (seat)->start (seat);
169 }
170
171 GList *
172 seat_get_sessions (Seat *seat)
173 {
174     g_return_val_if_fail (seat != NULL, NULL);
175     return seat->priv->sessions;
176 }
177
178 void
179 seat_set_active_session (Seat *seat, Session *session)
180 {
181     GList *link;
182
183     g_return_if_fail (seat != NULL);
184
185     /* Unlock this session */
186     if (session != seat->priv->active_session && !IS_GREETER (session))
187         session_unlock (session);
188
189     SEAT_GET_CLASS (seat)->set_active_session (seat, session);
190
191     /* Stop any greeters */
192     for (link = seat->priv->sessions; link; link = link->next)
193     {
194         Session *s = link->data;
195
196         if (s == session || session_get_is_stopping (s))
197             continue;
198
199         if (IS_GREETER (s))
200         {
201             g_debug ("Stopping greeter");
202             session_stop (s);
203         }
204     }
205
206     /* Lock previous sessions */
207     if (seat->priv->active_session)
208     {
209         if (session != seat->priv->active_session && !IS_GREETER (seat->priv->active_session))
210             session_lock (seat->priv->active_session);
211         g_object_unref (seat->priv->active_session);
212     }
213     seat->priv->active_session = g_object_ref (session);
214 }
215
216 Session *
217 seat_get_active_session (Seat *seat)
218 {
219     g_return_val_if_fail (seat != NULL, NULL);
220     return SEAT_GET_CLASS (seat)->get_active_session (seat);
221 }
222
223 gboolean
224 seat_get_can_switch (Seat *seat)
225 {
226     g_return_val_if_fail (seat != NULL, FALSE);
227     return seat->priv->can_switch;
228 }
229
230 gboolean
231 seat_get_allow_guest (Seat *seat)
232 {
233     g_return_val_if_fail (seat != NULL, FALSE);
234     return seat_get_boolean_property (seat, "allow-guest") && guest_account_is_installed ();
235 }
236
237 static gboolean
238 run_script (Seat *seat, DisplayServer *display_server, const gchar *script_name, User *user)
239 {
240     Process *script;
241     gboolean result = FALSE;
242   
243     script = process_new ();
244
245     process_set_command (script, script_name);
246
247     /* Set POSIX variables */
248     process_set_clear_environment (script, TRUE);
249     process_set_env (script, "SHELL", "/bin/sh");
250
251     /* Variables required for regression tests */
252     if (g_getenv ("LIGHTDM_TEST_ROOT"))
253     {
254         process_set_env (script, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
255         process_set_env (script, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
256         process_set_env (script, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
257         process_set_env (script, "PATH", g_getenv ("PATH"));
258     }
259     else
260         process_set_env (script, "PATH", "/usr/local/bin:/usr/bin:/bin");
261
262     if (user)
263     {
264         process_set_env (script, "USER", user_get_name (user));
265         process_set_env (script, "LOGNAME", user_get_name (user));
266         process_set_env (script, "HOME", user_get_home_directory (user));
267     }
268     else
269         process_set_env (script, "HOME", "/");
270
271     SEAT_GET_CLASS (seat)->run_script (seat, display_server, script);
272
273     if (process_start (script, TRUE))
274     {
275         int exit_status;
276
277         exit_status = process_get_exit_status (script);
278         if (WIFEXITED (exit_status))
279         {
280             g_debug ("Exit status of %s: %d", script_name, WEXITSTATUS (exit_status));
281             result = WEXITSTATUS (exit_status) == EXIT_SUCCESS;
282         }
283     }
284
285     g_object_unref (script);
286
287     return result;
288 }
289
290 static void
291 seat_real_run_script (Seat *seat, DisplayServer *display_server, Process *process)
292 {  
293 }
294
295 static void
296 emit_upstart_signal (const gchar *signal)
297 {
298     g_return_if_fail (signal != NULL);
299     g_return_if_fail (signal[0] != 0);
300
301     if (getuid () != 0)
302         return;
303
304     gchar *cmd = g_strdup_printf ("initctl -q emit %s DISPLAY_MANAGER=lightdm", signal);
305     g_spawn_command_line_async (cmd, NULL); /* OK if it fails, probably not installed */
306     g_free (cmd);
307 }
308
309 static void
310 check_stopped (Seat *seat)
311 {
312     if (seat->priv->stopping &&
313         !seat->priv->stopped &&
314         g_list_length (seat->priv->display_servers) == 0 &&
315         g_list_length (seat->priv->sessions) == 0)
316     {
317         seat->priv->stopped = TRUE;
318         g_debug ("Seat stopped");
319         g_signal_emit (seat, signals[STOPPED], 0);
320     }
321 }
322
323 static gboolean
324 get_start_local_sessions (Seat *seat)
325 {
326     return SEAT_GET_CLASS (seat)->get_start_local_sessions (seat);
327 }
328
329 static void
330 display_server_stopped_cb (DisplayServer *display_server, Seat *seat)
331 {
332     GList *list, *link;
333     Session *active_session;
334
335     g_debug ("Display server stopped");
336
337     g_signal_handlers_disconnect_matched (display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
338     seat->priv->display_servers = g_list_remove (seat->priv->display_servers, display_server);
339
340     if (seat->priv->stopping || !seat->priv->started)
341     {
342         check_stopped (seat);
343         g_object_unref (display_server);
344         return;
345     }
346
347     /* Stop all sessions on this display server */
348     list = g_list_copy (seat->priv->sessions);
349     for (link = list; link; link = link->next)
350         g_object_ref (link->data);
351     for (link = list; link; link = link->next)
352     {
353         Session *session = link->data;
354
355         if (session_get_display_server (session) != display_server || session_get_is_stopping (session))
356             continue;
357
358         /* Stop seat if this is the only display server and it failed to start a greeter */
359         if (IS_GREETER (session) &&
360             !session_get_is_started (session) &&
361             g_list_length (seat->priv->display_servers) == 0)
362         {
363             g_debug ("Stopping seat, greeter display server failed to start");
364             seat_stop (seat);
365         }
366
367         g_debug ("Stopping session");
368         session_stop (session);
369     }
370     g_list_free_full (list, g_object_unref);
371
372     if (!seat->priv->stopping && get_start_local_sessions (seat))
373     {
374         /* If we were the active session, switch to a greeter */
375         active_session = seat_get_active_session (seat);
376         if (!active_session || session_get_display_server (active_session) == display_server)
377         {
378             g_debug ("Active display server stopped, starting greeter");
379             seat_switch_to_greeter (seat);
380         }
381     }
382
383     g_object_unref (display_server);
384 }
385
386 static gboolean
387 can_share_display_server (Seat *seat, DisplayServer *display_server)
388 {
389     return seat->priv->share_display_server && display_server_get_can_share (display_server);
390 }
391
392 static void
393 switch_to_greeter_from_failed_session (Seat *seat, Session *session)
394 {
395     Greeter *greeter_session;
396
397     greeter_session = create_greeter_session (seat);
398     if (session_get_is_guest (session))
399         greeter_set_hint (greeter_session, "select-guest", "true");
400     else
401         greeter_set_hint (greeter_session, "select-user", session_get_username (session));
402     if (seat->priv->session_to_activate)
403         g_object_unref (seat->priv->session_to_activate);
404     seat->priv->session_to_activate = g_object_ref (greeter_session);
405
406     if (can_share_display_server (seat, session_get_display_server (session)))
407         session_set_display_server (SESSION (greeter_session), session_get_display_server (session));
408     else
409     {
410         DisplayServer *display_server;
411
412         display_server = create_display_server (seat, session_get_session_type (session));
413         if (!display_server_start (display_server))
414         {
415             g_debug ("Failed to start display server for greeter");
416             seat_stop (seat);
417         }
418
419         session_set_display_server (session, display_server);
420     }
421
422     start_session (seat, SESSION (greeter_session));
423
424     /* Stop failed session */
425     session_stop (session);
426 }
427
428 static void
429 start_session (Seat *seat, Session *session)
430 {
431     /* Use system location for greeter log file */
432     if (IS_GREETER (session))
433     {
434         gchar *log_dir, *filename, *log_filename;
435
436         log_dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
437         filename = g_strdup_printf ("%s-greeter.log", display_server_get_name (session_get_display_server (session)));
438         log_filename = g_build_filename (log_dir, filename, NULL);
439         g_free (log_dir);
440         g_free (filename);
441         session_set_log_file (session, log_filename);
442         g_free (log_filename);
443     }
444
445     if (session_start (session))
446         return;
447
448     if (IS_GREETER (session))
449     {
450         g_debug ("Failed to start greeter");
451         display_server_stop (session_get_display_server (session));
452         return;
453     }
454
455     g_debug ("Failed to start session, starting greeter");
456     switch_to_greeter_from_failed_session (seat, session);
457 }
458
459 static void
460 run_session (Seat *seat, Session *session)
461 {
462     const gchar *script;
463
464     if (IS_GREETER (session))
465         script = seat_get_string_property (seat, "greeter-setup-script");
466     else
467         script = seat_get_string_property (seat, "session-setup-script");
468     if (script && !run_script (seat, session_get_display_server (session), script, NULL))
469     {
470         g_debug ("Switching to greeter due to failed setup script");
471         switch_to_greeter_from_failed_session (seat, session);
472         return;
473     }
474
475     if (!IS_GREETER (session))
476     {
477         g_signal_emit (seat, signals[RUNNING_USER_SESSION], 0, session);
478         emit_upstart_signal ("desktop-session-start");
479     }
480
481     session_run (session);
482
483     // FIXME: Wait until the session is ready
484
485     if (session == seat->priv->session_to_activate)
486     {
487         seat_set_active_session (seat, session);
488         g_object_unref (seat->priv->session_to_activate);
489         seat->priv->session_to_activate = NULL;
490     }
491 }
492
493 static void
494 session_authentication_complete_cb (Session *session, Seat *seat)
495 {
496     if (session_get_is_authenticated (session))
497     {
498         g_debug ("Session authenticated, running command");
499         run_session (seat, session);
500     }
501     else if (!IS_GREETER (session))
502     {
503         g_debug ("Switching to greeter due to failed authentication");
504         switch_to_greeter_from_failed_session (seat, session);
505     }
506     else
507     {
508         g_debug ("Stopping session that failed authentication");
509         session_stop (session);
510     }
511 }
512
513 static void
514 session_stopped_cb (Session *session, Seat *seat)
515 {
516     DisplayServer *display_server;
517
518     g_debug ("Session stopped");
519
520     g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
521     seat->priv->sessions = g_list_remove (seat->priv->sessions, session);
522     if (session == seat->priv->active_session)
523     {
524         g_object_unref (seat->priv->active_session);
525         seat->priv->active_session = NULL;
526     }
527     if (session == seat->priv->session_to_activate)
528     {
529         g_object_unref (seat->priv->session_to_activate);
530         seat->priv->session_to_activate = NULL;
531     }
532
533     display_server = session_get_display_server (session);
534     if (!display_server)
535     {
536         g_object_unref (session);
537         return;
538     }
539
540     /* Cleanup */
541     if (!IS_GREETER (session))
542     {
543         const gchar *script;
544         script = seat_get_string_property (seat, "session-cleanup-script");
545         if (script)
546             run_script (seat, display_server, script, session_get_user (session));
547     }
548
549     /* We were waiting for this session, but it didn't start :( */
550     // FIXME: Start a greeter on this?
551     if (session == seat->priv->session_to_activate)
552     {
553         g_object_unref (seat->priv->session_to_activate);
554         seat->priv->session_to_activate = NULL;
555     }
556
557     if (seat->priv->stopping)
558     {
559         check_stopped (seat);
560         g_object_unref (session);
561         return;
562     }
563
564     /* If this is the greeter session then re-use this display server */
565     if (IS_GREETER (session) &&
566         can_share_display_server (seat, display_server) &&
567         greeter_get_start_session (GREETER (session)))
568     {
569         GList *link;
570
571         for (link = seat->priv->sessions; link; link = link->next)
572         {
573             Session *s = link->data;
574
575             /* Skip this session and sessions on other display servers */
576             if (s == session || session_get_display_server (s) != display_server || session_get_is_stopping (s))
577                 continue;
578
579             if (session_get_is_authenticated (s))
580             {
581                 g_debug ("Greeter stopped, running session");
582                 run_session (seat, s);
583             }
584             else
585             {
586                 g_debug ("Greeter stopped, starting session authentication");
587                 start_session (seat, s);
588             }
589             break;
590         }
591     }
592     /* If this is the greeter and nothing else is running then stop the seat */
593     else if (IS_GREETER (session) &&
594         !greeter_get_start_session (GREETER (session)) &&
595         g_list_length (seat->priv->display_servers) == 1 &&
596         g_list_nth_data (seat->priv->display_servers, 0) == display_server)
597     {
598         g_debug ("Stopping seat, failed to start a greeter");
599         seat_stop (seat);
600     }
601     /* If we were the active session, switch to a greeter */
602     else if (!IS_GREETER (session) && session == seat_get_active_session (seat))
603     {
604         g_debug ("Active session stopped, starting greeter");
605         seat_switch_to_greeter (seat);
606     }
607
608     /* Stop the display server if no-longer required */
609     if (display_server && !display_server_get_is_stopping (display_server))
610     {
611         GList *link;
612         int n_sessions = 0;
613
614         for (link = seat->priv->sessions; link; link = link->next)
615         {
616             Session *s = link->data;
617             if (s == session)
618                 continue;
619             if (session_get_display_server (s) == display_server)
620                 n_sessions++;
621         }
622         if (n_sessions == 0)
623         {
624             g_debug ("Stopping display server, no sessions require it");
625             display_server_stop (display_server);
626         }
627     }
628
629     g_signal_emit (seat, signals[SESSION_REMOVED], 0, session);
630     g_object_unref (session);
631 }
632
633 static void
634 set_session_env (Session *session)
635 {
636     /* Connect using the session bus */
637     if (getuid () != 0)
638     {
639         if (g_getenv ("DBUS_SESSION_BUS_ADDRESS"))
640             session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
641         session_set_env (session, "LDM_BUS", "SESSION");
642         if (g_getenv ("LD_PRELOAD"))
643             session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
644         if (g_getenv ("LD_LIBRARY_PATH"))
645             session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
646         if (g_getenv ("PATH"))
647             session_set_env (session, "PATH", g_getenv ("PATH"));
648     }
649
650     /* Variables required for regression tests */
651     if (g_getenv ("LIGHTDM_TEST_ROOT"))
652     {
653         session_set_env (session, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
654         session_set_env (session, "DBUS_SYSTEM_BUS_ADDRESS", g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
655         session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
656         session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
657         session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
658         session_set_env (session, "GI_TYPELIB_PATH", g_getenv ("GI_TYPELIB_PATH"));
659     }
660 }
661
662 static Session *
663 create_session (Seat *seat, gboolean autostart)
664 {
665     Session *session;
666
667     session = SEAT_GET_CLASS (seat)->create_session (seat);
668     seat->priv->sessions = g_list_append (seat->priv->sessions, session);
669     if (autostart)
670         g_signal_connect (session, "authentication-complete", G_CALLBACK (session_authentication_complete_cb), seat);
671     g_signal_connect (session, "stopped", G_CALLBACK (session_stopped_cb), seat);
672
673     set_session_env (session);
674
675     g_signal_emit (seat, signals[SESSION_ADDED], 0, session);
676
677     return session;
678 }
679
680 static gchar **
681 get_session_argv (SessionConfig *session_config, const gchar *session_wrapper)
682 {
683     gboolean result;
684     int argc;
685     gchar **argv, *path;
686     GError *error = NULL;
687
688     /* If configured, run sessions through a wrapper */
689     if (session_wrapper)
690     {
691         argv = g_malloc (sizeof (gchar *) * 3);
692         path = g_find_program_in_path (session_wrapper);
693         argv[0] = path ? path : g_strdup (session_wrapper);
694         argv[1] = g_strdup (session_config_get_command (session_config));
695         argv[2] = NULL;
696         return argv;
697     }
698
699     /* Split command into an array listing and make command absolute */
700     result = g_shell_parse_argv (session_config_get_command (session_config), &argc, &argv, &error);
701     if (error)
702         g_debug ("Invalid session command '%s': %s", session_config_get_command (session_config), error->message);
703     g_clear_error (&error);
704     if (!result)
705         return NULL;
706     path = g_find_program_in_path (argv[0]);
707     if (path)
708     {
709         g_free (argv[0]);
710         argv[0] = path;
711     }
712   
713     return argv;
714 }
715
716 static SessionConfig *
717 find_session_config (const gchar *sessions_dir, const gchar *session_name)
718 {
719     gchar **dirs;
720     SessionConfig *session_config = NULL;
721     int i;
722     GError *error = NULL;
723
724     g_return_val_if_fail (sessions_dir != NULL, NULL);
725     g_return_val_if_fail (session_name != NULL, NULL);
726
727     dirs = g_strsplit (sessions_dir, ":", -1);
728     for (i = 0; dirs[i]; i++)
729     {
730         gchar *filename, *path;
731
732         filename = g_strdup_printf ("%s.desktop", session_name);
733         path = g_build_filename (dirs[i], filename, NULL);
734         g_free (filename);
735         session_config = session_config_new_from_file (path, &error);
736         g_free (path);
737         if (session_config)
738             break;
739
740         if (dirs[i+1] == NULL)
741             g_debug ("Failed to find session configuration %s", session_name);
742         g_clear_error (&error);
743     }
744     g_strfreev (dirs);
745
746     return session_config;
747 }
748
749 static Session *
750 create_user_session (Seat *seat, const gchar *username)
751 {
752     User *user;
753     gchar *sessions_dir;
754     const gchar *session_name, *language;
755     SessionConfig *session_config;
756     Session *session = NULL;
757
758     g_debug ("Creating user session");
759
760     /* Load user preferences */
761     user = accounts_get_user_by_name (username);
762     if (!user)
763     {
764         g_debug ("Can't login unknown user '%s'", username);
765         return NULL;
766     }
767     session_name = user_get_xsession (user);
768     language = user_get_language (user);
769
770     if (!session_name)
771         session_name = seat_get_string_property (seat, "user-session");
772     sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
773     session_config = find_session_config (sessions_dir, session_name);
774     g_free (sessions_dir);
775     if (session_config)
776     {
777         const gchar *desktop_name;
778         gchar **argv;
779
780         session = create_session (seat, TRUE);
781         session_set_session_type (session, session_config_get_session_type (session_config));
782         session_set_env (session, "DESKTOP_SESSION", session_name);
783         session_set_env (session, "GDMSESSION", session_name);
784         desktop_name = session_config_get_desktop_name (session_config);
785         if (desktop_name)
786             session_set_env (session, "XDG_CURRENT_DESKTOP", desktop_name);
787         if (language && language[0] != '\0')
788         {
789             session_set_env (session, "LANG", language);
790             session_set_env (session, "GDM_LANG", language);
791         }
792         session_set_pam_service (session, AUTOLOGIN_SERVICE);
793         session_set_username (session, username);
794         session_set_do_authenticate (session, TRUE);
795         argv = get_session_argv (session_config, seat_get_string_property (seat, "session-wrapper"));
796         session_set_argv (session, argv);
797         g_strfreev (argv);
798
799         g_object_unref (session_config);
800     }
801     else
802         g_debug ("Can't find session '%s'", seat_get_string_property (seat, "user-session"));
803
804
805     g_object_unref (user);
806
807     return session;
808 }
809
810 static Session *
811 create_guest_session (Seat *seat)
812 {
813     gchar *sessions_dir, **argv;
814     SessionConfig *session_config;
815     Session *session;
816
817     sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
818     session_config = find_session_config (sessions_dir, seat_get_string_property (seat, "user-session"));
819     g_free (sessions_dir);
820     if (!session_config)
821     {
822         g_debug ("Can't find session '%s'", seat_get_string_property (seat, "user-session"));
823         return NULL;
824     }
825
826     session = create_session (seat, TRUE);
827     session_set_session_type (session, session_config_get_session_type (session_config));
828     session_set_do_authenticate (session, TRUE);
829     session_set_is_guest (session, TRUE);
830     argv = get_session_argv (session_config, seat_get_string_property (seat, "session-wrapper"));
831     g_object_unref (session_config);
832     session_set_argv (session, argv);
833     g_strfreev (argv);
834   
835     return session;
836 }
837
838 static Session *
839 greeter_create_session_cb (Greeter *greeter, Seat *seat)
840 {
841     Session *session;
842
843     session = create_session (seat, FALSE);
844     session_set_session_type (session, session_get_session_type (SESSION (greeter)));
845     session_set_display_server (session, session_get_display_server (SESSION (greeter)));
846
847     return g_object_ref (session);
848 }
849
850 static void
851 prepend_argv (gchar ***argv, const gchar *value)
852 {
853     gchar **old_argv, **new_argv;
854     gint i;
855
856     old_argv = *argv;
857     new_argv = g_malloc (sizeof (gchar *) * (g_strv_length (*argv) + 2));
858     new_argv[0] = g_strdup (value);
859     for (i = 0; old_argv[i]; i++)
860         new_argv[i + 1] = old_argv[i];
861     new_argv[i + 1] = NULL;
862
863     g_free (*argv);
864     *argv = new_argv;
865 }
866
867 static Session *
868 find_user_session (Seat *seat, const gchar *username)
869 {
870     GList *link;
871
872     if (!username)
873         return NULL;
874
875     for (link = seat->priv->sessions; link; link = link->next)
876     {
877         Session *session = link->data;
878
879         if (!session_get_is_stopping (session) && strcmp (session_get_username (session), username) == 0)
880             return session;
881     }
882
883     return NULL;
884 }
885
886 static gboolean
887 greeter_start_session_cb (Greeter *greeter, SessionType type, const gchar *session_name, Seat *seat)
888 {
889     Session *session, *existing_session;
890     const gchar *username, *language = NULL;
891     SessionConfig *session_config;
892     User *user;
893     gchar *sessions_dir = NULL;
894     gchar **argv;
895     DisplayServer *display_server;
896
897     /* Get the session to use */
898     if (greeter_get_guest_authenticated (greeter))
899     {
900         session = create_guest_session (seat);
901         if (!session)
902             return FALSE;
903         session_set_pam_service (session, AUTOLOGIN_SERVICE);
904     }
905     else
906         session = greeter_get_authentication_session (greeter);
907
908     /* Switch to this session when it is ready */
909     if (seat->priv->session_to_activate)
910         g_object_unref (seat->priv->session_to_activate);
911     seat->priv->session_to_activate = g_object_ref (session);
912
913     /* Return to existing session if it is open */
914     username = session_get_username (session);
915     existing_session = find_user_session (seat, username);
916     if (existing_session && session != existing_session)
917     {
918         g_debug ("Returning to existing user session %s", username);
919         session_stop (session);
920         seat_set_active_session (seat, existing_session);
921         return TRUE;
922     }
923
924     /* Get session command to run */
925     switch (type)
926     {
927     case SESSION_TYPE_LOCAL:
928         sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
929         break;
930     case SESSION_TYPE_REMOTE:
931         sessions_dir = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory");
932         break;
933     }
934
935     /* Load user preferences */
936     user = session_get_user (session);
937     if (user)
938     {
939         if (!session_name)
940             session_name = user_get_xsession (user);
941         language = user_get_language (user);
942     }
943
944     if (!session_name)
945         session_name = seat_get_string_property (seat, "user-session");
946     if (user)
947         user_set_xsession (session_get_user (session), session_name);
948
949     session_config = find_session_config (sessions_dir, session_name);
950     g_free (sessions_dir);
951     if (!session_config)
952     {
953         g_debug ("Can't find session '%s'", seat_get_string_property (seat, "user-session"));
954         return FALSE;
955     }
956
957     session_set_session_type (session, session_config_get_session_type (session_config));
958     argv = get_session_argv (session_config, seat_get_string_property (seat, "session-wrapper"));
959     session_set_argv (session, argv);
960     g_strfreev (argv);
961     session_set_env (session, "DESKTOP_SESSION", session_name);
962     session_set_env (session, "GDMSESSION", session_name);
963     if (language && language[0] != '\0')
964     {
965         session_set_env (session, "LANG", language);
966         session_set_env (session, "GDM_LANG", language);
967     }
968
969     g_object_unref (session_config);
970
971     /* If can re-use the display server, stop the greeter first */
972     display_server = session_get_display_server (SESSION (greeter));
973     if (can_share_display_server (seat, display_server) &&
974         strcmp (display_server_get_session_type (display_server), session_get_session_type (session)) == 0)
975     {
976         g_debug ("Stopping greeter; display server will be re-used for user session");
977
978         /* Run on the same display server after the greeter has stopped */
979         session_set_display_server (session, display_server);
980
981         /* Stop the greeter */
982         session_stop (SESSION (greeter));
983
984         return TRUE;
985     }
986     /* Otherwise start a new display server for this session */
987     else
988     {
989         display_server = create_display_server (seat, session_get_session_type (session));
990         session_set_display_server (session, display_server);
991         if (!display_server_start (display_server))
992         {
993             g_debug ("Failed to start display server for new session");
994             return FALSE;
995         }
996
997         return TRUE;
998     }
999 }
1000
1001 static Greeter *
1002 create_greeter_session (Seat *seat)
1003 {
1004     gchar *sessions_dir, **argv;
1005     SessionConfig *session_config;
1006     Greeter *greeter_session;
1007     gchar *greeter_user;
1008     const gchar *greeter_wrapper;
1009
1010     g_debug ("Creating greeter session");
1011
1012     sessions_dir = config_get_string (config_get_instance (), "LightDM", "greeters-directory");
1013     session_config = find_session_config (sessions_dir, seat_get_string_property (seat, "greeter-session"));
1014     g_free (sessions_dir);
1015     if (!session_config)
1016         return NULL;
1017
1018     argv = get_session_argv (session_config, NULL);
1019     greeter_wrapper = seat_get_string_property (seat, "greeter-wrapper");
1020     if (greeter_wrapper)
1021     {
1022         gchar *path;
1023         path = g_find_program_in_path (greeter_wrapper);
1024         prepend_argv (&argv, path ? path : greeter_wrapper);
1025         g_free (path);
1026     }
1027
1028     greeter_session = SEAT_GET_CLASS (seat)->create_greeter_session (seat);
1029     session_set_session_type (SESSION (greeter_session), session_config_get_session_type (session_config));
1030     seat->priv->sessions = g_list_append (seat->priv->sessions, SESSION (greeter_session));
1031     g_signal_connect (greeter_session, "authentication-complete", G_CALLBACK (session_authentication_complete_cb), seat);
1032     g_signal_connect (greeter_session, "stopped", G_CALLBACK (session_stopped_cb), seat);
1033   
1034     set_session_env (SESSION (greeter_session));
1035
1036     session_set_pam_service (SESSION (greeter_session), GREETER_SERVICE);
1037     greeter_user = config_get_string (config_get_instance (), "LightDM", "greeter-user");
1038     session_set_username (SESSION (greeter_session), greeter_user);
1039     g_free (greeter_user);
1040     session_set_argv (SESSION (greeter_session), argv);
1041     g_strfreev (argv);
1042
1043     greeter_set_pam_services (greeter_session, USER_SERVICE, AUTOLOGIN_SERVICE);
1044     g_signal_connect (greeter_session, "create-session", G_CALLBACK (greeter_create_session_cb), seat);
1045     g_signal_connect (greeter_session, "start-session", G_CALLBACK (greeter_start_session_cb), seat);
1046
1047     /* Set hints to greeter */
1048     greeter_set_hint (greeter_session, "default-session", seat_get_string_property (seat, "user-session"));
1049     greeter_set_allow_guest (greeter_session, seat_get_allow_guest (seat));
1050     greeter_set_hint (greeter_session, "hide-users", seat_get_boolean_property (seat, "greeter-hide-users") ? "true" : "false");
1051     greeter_set_hint (greeter_session, "show-manual-login", seat_get_boolean_property (seat, "greeter-show-manual-login") ? "true" : "false");
1052     greeter_set_hint (greeter_session, "show-remote-login", seat_get_boolean_property (seat, "greeter-show-remote-login") ? "true" : "false");
1053     greeter_set_hint (greeter_session, "has-guest-account", seat_get_allow_guest (seat) && seat_get_boolean_property (seat, "greeter-allow-guest") ? "true" : "false");
1054
1055     g_object_unref (session_config);
1056
1057     return greeter_session;
1058 }
1059
1060 static Session *
1061 find_session_for_display_server (Seat *seat, DisplayServer *display_server)
1062 {
1063     GList *link;
1064
1065     for (link = seat->priv->sessions; link; link = link->next)
1066     {
1067         Session *session = link->data;
1068         if (session_get_display_server (session) == display_server && !session_get_is_stopping (session))
1069             return session;
1070     }
1071
1072     return NULL;
1073 }
1074
1075 static void
1076 display_server_ready_cb (DisplayServer *display_server, Seat *seat)
1077 {
1078     const gchar *script;
1079     Session *session;
1080
1081     /* Run setup script */
1082     script = seat_get_string_property (seat, "display-setup-script");
1083     if (script && !run_script (seat, display_server, script, NULL))
1084     {
1085         g_debug ("Stopping display server due to failed setup script");
1086         display_server_stop (display_server);
1087         return;
1088     }
1089
1090     /* Stop if don't need to run a session */
1091     if (!get_start_local_sessions (seat))
1092         return;
1093
1094     emit_upstart_signal ("login-session-start");
1095
1096     /* Start the session waiting for this display server */
1097     session = find_session_for_display_server (seat, display_server);
1098     if (session)
1099     {
1100         if (session_get_is_authenticated (session))
1101         {
1102             g_debug ("Display server ready, running session");
1103             run_session (seat, session);
1104         }
1105         else
1106         {
1107             g_debug ("Display server ready, starting session authentication");
1108             start_session (seat, session);
1109         }
1110     }
1111     else
1112     {
1113         g_debug ("Stopping not required display server");
1114         display_server_stop (display_server);
1115     }
1116 }
1117
1118 static DisplayServer *
1119 create_display_server (Seat *seat, const gchar *session_type)
1120 {
1121     DisplayServer *display_server;
1122
1123     g_debug ("Creating display server of type %s", session_type);
1124
1125     display_server = SEAT_GET_CLASS (seat)->create_display_server (seat, session_type);
1126     if (!display_server)
1127         return NULL;
1128
1129     seat->priv->display_servers = g_list_append (seat->priv->display_servers, display_server);
1130     g_signal_connect (display_server, "ready", G_CALLBACK (display_server_ready_cb), seat);
1131     g_signal_connect (display_server, "stopped", G_CALLBACK (display_server_stopped_cb), seat);
1132
1133     return display_server;
1134 }
1135
1136 static Greeter *
1137 find_greeter_session (Seat *seat)
1138 {
1139     GList *link;
1140
1141     for (link = seat->priv->sessions; link; link = link->next)
1142     {
1143         Session *session = link->data;
1144         if (!session_get_is_stopping (session) && IS_GREETER (session))
1145             return GREETER (session);
1146     }
1147
1148     return NULL;
1149 }
1150
1151 gboolean
1152 seat_switch_to_greeter (Seat *seat)
1153 {
1154     Greeter *greeter_session;
1155     DisplayServer *display_server;
1156
1157     g_return_val_if_fail (seat != NULL, FALSE);
1158
1159     if (!seat->priv->can_switch)
1160         return FALSE;
1161
1162     /* Switch to greeter if one open (shouldn't be though) */
1163     greeter_session = find_greeter_session (seat);
1164     if (greeter_session)
1165     {
1166         g_debug ("Switching to existing greeter");
1167         seat_set_active_session (seat, SESSION (greeter_session));
1168         return TRUE;
1169     }
1170
1171     greeter_session = create_greeter_session (seat);
1172     if (seat->priv->session_to_activate)
1173         g_object_unref (seat->priv->session_to_activate);
1174     seat->priv->session_to_activate = g_object_ref (greeter_session);
1175
1176     display_server = create_display_server (seat, session_get_session_type (SESSION (greeter_session)));
1177     session_set_display_server (SESSION (greeter_session), display_server);
1178     if (!display_server_start (display_server))
1179         return FALSE;
1180
1181     return TRUE;
1182 }
1183
1184 gboolean
1185 seat_switch_to_user (Seat *seat, const gchar *username, const gchar *session_name)
1186 {
1187     Session *session;
1188     DisplayServer *display_server;
1189
1190     g_return_val_if_fail (seat != NULL, FALSE);
1191     g_return_val_if_fail (username != NULL, FALSE);
1192
1193     if (!seat->priv->can_switch)
1194         return FALSE;
1195
1196     g_debug ("Switching to user %s", username);
1197
1198     session = find_user_session (seat, username);
1199     if (session)
1200     {
1201         g_debug ("Switching to existing user session %s", username);
1202         seat_set_active_session (seat, session);
1203         return TRUE;
1204     }
1205
1206     session = create_user_session (seat, username);
1207     if (!session)
1208         return FALSE;
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 (session);
1212     session_set_pam_service (session, USER_SERVICE);
1213
1214     display_server = create_display_server (seat, session_get_session_type (session));
1215     session_set_display_server (session, display_server);
1216     if (!display_server_start (display_server))
1217         return FALSE;
1218
1219     return FALSE;
1220 }
1221
1222 static Session *
1223 find_guest_session (Seat *seat)
1224 {
1225     GList *link;
1226
1227     for (link = seat->priv->sessions; link; link = link->next)
1228     {
1229         Session *session = link->data;
1230         if (!session_get_is_stopping (session) && session_get_is_guest (session))
1231             return session;
1232     }
1233
1234     return NULL;
1235 }
1236
1237 gboolean
1238 seat_switch_to_guest (Seat *seat, const gchar *session_name)
1239 {
1240     Session *session;
1241     DisplayServer *display_server;
1242
1243     g_return_val_if_fail (seat != NULL, FALSE);
1244
1245     if (!seat->priv->can_switch || !seat_get_allow_guest (seat))
1246         return FALSE;
1247
1248     /* Switch to session if one open */
1249     session = find_guest_session (seat);
1250     if (session)
1251     {
1252         g_debug ("Switching to existing guest account %s", session_get_username (session));
1253         seat_set_active_session (seat, session);
1254         return TRUE;
1255     }
1256
1257     session = create_guest_session (seat);
1258     if (!session)
1259         return FALSE;
1260
1261     display_server = create_display_server (seat, session_get_session_type (session));
1262     if (!display_server_start (display_server))
1263         return FALSE;
1264
1265     if (seat->priv->session_to_activate)
1266         g_object_unref (seat->priv->session_to_activate);
1267     seat->priv->session_to_activate = g_object_ref (session);
1268     session_set_pam_service (session, AUTOLOGIN_SERVICE);
1269     session_set_display_server (session, display_server);
1270
1271     return TRUE;
1272 }
1273
1274 gboolean
1275 seat_lock (Seat *seat, const gchar *username)
1276 {
1277     Greeter *greeter_session;
1278     DisplayServer *display_server;
1279
1280     g_return_val_if_fail (seat != NULL, FALSE);
1281
1282     if (!seat->priv->can_switch)
1283         return FALSE;
1284
1285     g_debug ("Locking seat");
1286
1287     /* Switch to greeter if one open (shouldn't be though) */
1288     greeter_session = find_greeter_session (seat);
1289     if (greeter_session)
1290     {
1291         g_debug ("Switching to existing greeter");
1292         seat_set_active_session (seat, SESSION (greeter_session));
1293         return TRUE;
1294     }
1295
1296     greeter_session = create_greeter_session (seat);
1297     if (!greeter_session)
1298         return FALSE;
1299
1300     display_server = create_display_server (seat, session_get_session_type (SESSION (greeter_session)));
1301     if (!display_server_start (display_server))
1302         return FALSE;
1303
1304     if (seat->priv->session_to_activate)
1305         g_object_unref (seat->priv->session_to_activate);
1306     seat->priv->session_to_activate = g_object_ref (greeter_session);
1307     greeter_set_hint (greeter_session, "lock-screen", "true");
1308     if (username)
1309         greeter_set_hint (greeter_session, "select-user", username);
1310     session_set_display_server (SESSION (greeter_session), display_server);
1311
1312     return TRUE;
1313 }
1314
1315 void
1316 seat_stop (Seat *seat)
1317 {
1318     g_return_if_fail (seat != NULL);
1319
1320     if (seat->priv->stopping)
1321         return;
1322
1323     g_debug ("Stopping seat");
1324     seat->priv->stopping = TRUE;
1325     SEAT_GET_CLASS (seat)->stop (seat);
1326 }
1327
1328 gboolean
1329 seat_get_is_stopping (Seat *seat)
1330 {
1331     g_return_val_if_fail (seat != NULL, FALSE);
1332     return seat->priv->stopping;
1333 }
1334
1335 static gboolean
1336 seat_real_get_start_local_sessions (Seat *seat)
1337 {
1338     return TRUE;
1339 }
1340
1341 static void
1342 seat_real_setup (Seat *seat)
1343 {
1344 }
1345
1346 static gboolean
1347 seat_real_start (Seat *seat)
1348 {
1349     const gchar *autologin_username;
1350     int autologin_timeout;
1351     gboolean autologin_guest;
1352     gboolean autologin_in_background;
1353     Session *session = NULL, *background_session = NULL;
1354
1355     g_debug ("Starting seat");
1356
1357     /* If this display server doesn't have a session running on it, just start it */
1358     if (!get_start_local_sessions (seat))
1359     {
1360         DisplayServer *display_server;
1361         display_server = create_display_server (seat, "x"); // FIXME: Not necessarily an X seat, but not sure what to put here
1362         return display_server_start (display_server);
1363     }
1364
1365     /* Get autologin settings */
1366     autologin_username = seat_get_string_property (seat, "autologin-user");
1367     if (g_strcmp0 (autologin_username, "") == 0)
1368         autologin_username = NULL;
1369     autologin_timeout = seat_get_integer_property (seat, "autologin-user-timeout");
1370     autologin_guest = seat_get_boolean_property (seat, "autologin-guest");
1371     autologin_in_background = seat_get_boolean_property (seat, "autologin-in-background");
1372
1373     /* Autologin if configured */
1374     if (autologin_timeout == 0 || autologin_in_background)
1375     {
1376         if (autologin_guest)
1377             session = create_guest_session (seat);
1378         else if (autologin_username != NULL)
1379             session = create_user_session (seat, autologin_username);
1380
1381         if (session)
1382             session_set_pam_service (session, AUTOLOGIN_SERVICE);
1383
1384         /* Load in background if required */
1385         if (autologin_in_background && session)
1386         {
1387             background_session = session;
1388             session = NULL;
1389         }
1390       
1391         if (session)
1392         {
1393             DisplayServer *display_server;
1394
1395             if (seat->priv->session_to_activate)
1396                 g_object_unref (seat->priv->session_to_activate);
1397             seat->priv->session_to_activate = g_object_ref (session);
1398
1399             display_server = create_display_server (seat, session_get_session_type (session));
1400             session_set_display_server (session, display_server);
1401             if (!display_server || !display_server_start (display_server))
1402             {
1403                 g_debug ("Can't create display server for automatic login");
1404                 session_stop (session);
1405                 if (display_server)
1406                     display_server_stop (display_server);
1407                 session = NULL;
1408             }
1409         }
1410     }
1411
1412     /* Fallback to a greeter */
1413     if (!session)
1414     {
1415         Greeter *greeter_session;
1416         DisplayServer *display_server;
1417
1418         greeter_session = create_greeter_session (seat);
1419         if (!greeter_session)
1420         {
1421             g_debug ("Failed to create greeter session");
1422             return FALSE;
1423         }
1424
1425         if (seat->priv->session_to_activate)
1426             g_object_unref (seat->priv->session_to_activate);
1427         seat->priv->session_to_activate = g_object_ref (greeter_session);
1428         session = SESSION (greeter_session);
1429
1430         if (autologin_timeout)
1431         {
1432             gchar *value;
1433
1434             value = g_strdup_printf ("%d", autologin_timeout);
1435             greeter_set_hint (greeter_session, "autologin-timeout", value);
1436             g_free (value);
1437             if (autologin_username)
1438                 greeter_set_hint (greeter_session, "autologin-user", autologin_username);
1439             if (autologin_guest)
1440                 greeter_set_hint (greeter_session, "autologin-guest", "true");
1441         }
1442
1443         display_server = create_display_server (seat, session_get_session_type (session));
1444         session_set_display_server (session, display_server);
1445         if (!display_server || !display_server_start (display_server))
1446         {
1447             g_debug ("Can't create display server for greeter");
1448             session_stop (session);
1449             if (display_server)
1450                 display_server_stop (display_server);
1451             session = NULL;
1452         }
1453     }
1454
1455     /* Fail if can't start a session */
1456     if (!session)
1457     {
1458         seat_stop (seat);
1459         return FALSE;
1460     }
1461
1462     /* Start background session */
1463     if (background_session)
1464     {
1465         DisplayServer *background_display_server;
1466
1467         background_display_server = create_display_server (seat, session_get_session_type (background_session));
1468         session_set_display_server (background_session, background_display_server);
1469         if (!display_server_start (background_display_server))
1470             g_warning ("Failed to start display server for background session");
1471     }
1472
1473     seat->priv->started = TRUE;
1474     return TRUE;
1475 }
1476
1477 static Greeter *
1478 seat_real_create_greeter_session (Seat *seat)
1479 {
1480     return greeter_new ();
1481 }
1482
1483 static Session *
1484 seat_real_create_session (Seat *seat)
1485 {
1486     return session_new ();
1487 }
1488
1489 static void
1490 seat_real_set_active_session (Seat *seat, Session *session)
1491 {
1492 }
1493
1494 static Session *
1495 seat_real_get_active_session (Seat *seat)
1496 {
1497     return NULL;
1498 }
1499
1500 static void
1501 seat_real_stop (Seat *seat)
1502 {
1503     GList *list, *link;
1504
1505     check_stopped (seat);
1506     if (seat->priv->stopped)
1507         return;
1508
1509     /* Stop all the display servers and sessions on the seat. Copy the list as
1510      * it might be modified if a display server / session stops during this loop */
1511     list = g_list_copy (seat->priv->display_servers);
1512     for (link = list; link; link = link->next)
1513         g_object_ref (link->data);
1514     for (link = list; link; link = link->next)
1515     {
1516         DisplayServer *display_server = link->data;
1517         if (!display_server_get_is_stopping (display_server))
1518         {
1519             g_debug ("Stopping display server");
1520             display_server_stop (display_server);
1521         }
1522     }
1523     g_list_free_full (list, g_object_unref);
1524     list = g_list_copy (seat->priv->sessions);
1525     for (link = list; link; link = link->next)
1526         g_object_ref (link->data);
1527     for (link = list; link; link = link->next)
1528     {
1529         Session *session = link->data;
1530         if (!session_get_is_stopping (session))
1531         {
1532             g_debug ("Stopping session");
1533             session_stop (session);
1534         }
1535     }
1536     g_list_free_full (list, g_object_unref);
1537 }
1538
1539 static void
1540 seat_init (Seat *seat)
1541 {
1542     seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, SEAT_TYPE, SeatPrivate);
1543     seat->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1544     seat->priv->share_display_server = TRUE;
1545 }
1546
1547 static void
1548 seat_finalize (GObject *object)
1549 {
1550     Seat *self;
1551     GList *link;
1552
1553     self = SEAT (object);
1554
1555     g_hash_table_unref (self->priv->properties);
1556     for (link = self->priv->display_servers; link; link = link->next)
1557     {
1558         DisplayServer *display_server = link->data;
1559         g_signal_handlers_disconnect_matched (display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
1560     }  
1561     g_list_free_full (self->priv->display_servers, g_object_unref);
1562     for (link = self->priv->sessions; link; link = link->next)
1563     {
1564         Session *session = link->data;
1565         g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
1566     }
1567     g_list_free_full (self->priv->sessions, g_object_unref);
1568     if (self->priv->active_session)
1569         g_object_unref (self->priv->active_session);
1570     if (self->priv->session_to_activate)
1571         g_object_unref (self->priv->session_to_activate);
1572
1573     G_OBJECT_CLASS (seat_parent_class)->finalize (object);
1574 }
1575
1576 static void
1577 seat_class_init (SeatClass *klass)
1578 {
1579     GObjectClass *object_class = G_OBJECT_CLASS (klass);
1580
1581     klass->get_start_local_sessions = seat_real_get_start_local_sessions;
1582     klass->setup = seat_real_setup;
1583     klass->start = seat_real_start;
1584     klass->create_greeter_session = seat_real_create_greeter_session;
1585     klass->create_session = seat_real_create_session;
1586     klass->set_active_session = seat_real_set_active_session;
1587     klass->get_active_session = seat_real_get_active_session;
1588     klass->run_script = seat_real_run_script;
1589     klass->stop = seat_real_stop;
1590
1591     object_class->finalize = seat_finalize;
1592
1593     g_type_class_add_private (klass, sizeof (SeatPrivate));
1594
1595     signals[SESSION_ADDED] =
1596         g_signal_new ("session-added",
1597                       G_TYPE_FROM_CLASS (klass),
1598                       G_SIGNAL_RUN_LAST,
1599                       G_STRUCT_OFFSET (SeatClass, session_added),
1600                       NULL, NULL,
1601                       NULL,
1602                       G_TYPE_NONE, 1, SESSION_TYPE);
1603     signals[RUNNING_USER_SESSION] =
1604         g_signal_new ("running-user-session",
1605                       G_TYPE_FROM_CLASS (klass),
1606                       G_SIGNAL_RUN_LAST,
1607                       G_STRUCT_OFFSET (SeatClass, running_user_session),
1608                       NULL, NULL,
1609                       NULL,
1610                       G_TYPE_NONE, 1, SESSION_TYPE);
1611     signals[SESSION_REMOVED] =
1612         g_signal_new ("session-removed",
1613                       G_TYPE_FROM_CLASS (klass),
1614                       G_SIGNAL_RUN_LAST,
1615                       G_STRUCT_OFFSET (SeatClass, session_removed),
1616                       NULL, NULL,
1617                       NULL,
1618                       G_TYPE_NONE, 1, SESSION_TYPE);
1619     signals[STOPPED] =
1620         g_signal_new ("stopped",
1621                       G_TYPE_FROM_CLASS (klass),
1622                       G_SIGNAL_RUN_LAST,
1623                       G_STRUCT_OFFSET (SeatClass, stopped),
1624                       NULL, NULL,
1625                       NULL,
1626                       G_TYPE_NONE, 0);
1627 }