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-session.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 typedef struct
32 {
33     /* XDG name for this seat */
34     gchar *name;
35 
36     /* Configuration for this seat */
37     GHashTable *properties;
38 
39     /* TRUE if this seat can run multiple sessions at once */
40     gboolean supports_multi_session;
41 
42     /* TRUE if display server can be shared for sessions */
43     gboolean share_display_server;
44 
45     /* The display servers on this seat */
46     GList *display_servers;
47 
48     /* The sessions on this seat */
49     GList *sessions;
50 
51     /* The last session set to active */
52     Session *active_session;
53 
54     /* The session belonging to the active greeter user */
55     Session *next_session;
56 
57     /* The session to set active when it starts */
58     Session *session_to_activate;
59 
60     /* TRUE once we have started */
61     gboolean started;
62 
63     /* TRUE if stopping this seat (waiting for displays to stop) */
64     gboolean stopping;
65 
66     /* TRUE if stopped */
67     gboolean stopped;
68 
69     /* The greeter to be started to replace the current one */
70     GreeterSession *replacement_greeter;
71 } SeatPrivate;
72 
73 static void seat_logger_iface_init (LoggerInterface *iface);
74 
75 G_DEFINE_TYPE_WITH_CODE (Seat, seat, G_TYPE_OBJECT,
76                          G_ADD_PRIVATE (Seat)
77                          G_IMPLEMENT_INTERFACE (
78                              LOGGER_TYPE, seat_logger_iface_init))
79 
80 typedef struct
81 {
82     gchar *name;
83     GType type;
84 } SeatModule;
85 static GHashTable *seat_modules = NULL;
86 
87 // FIXME: Make a get_display_server() that re-uses display servers if supported
88 static DisplayServer *create_display_server (Seat *seat, Session *session);
89 static gboolean start_display_server (Seat *seat, DisplayServer *display_server);
90 static GreeterSession *create_greeter_session (Seat *seat);
91 static void start_session (Seat *seat, Session *session);
92 
93 static void
free_seat_module(gpointer data)94 free_seat_module (gpointer data)
95 {
96     SeatModule *module = data;
97     g_free (module->name);
98     g_free (module);
99 }
100 
101 void
seat_register_module(const gchar * name,GType type)102 seat_register_module (const gchar *name, GType type)
103 {
104     if (!seat_modules)
105         seat_modules = g_hash_table_new_full (g_str_hash, g_str_equal, free_seat_module, NULL);
106 
107     g_debug ("Registered seat module %s", name);
108 
109     SeatModule *module = g_malloc0 (sizeof (SeatModule));
110     module->name = g_strdup (name);
111     module->type = type;
112     g_hash_table_insert (seat_modules, g_strdup (name), module);
113 }
114 
115 Seat *
seat_new(const gchar * module_name)116 seat_new (const gchar *module_name)
117 {
118     g_return_val_if_fail (module_name != NULL, NULL);
119 
120     SeatModule *m = NULL;
121     if (seat_modules)
122         m = g_hash_table_lookup (seat_modules, module_name);
123     if (!m)
124         return NULL;
125 
126     return g_object_new (m->type, NULL);
127 }
128 
129 void
seat_set_name(Seat * seat,const gchar * name)130 seat_set_name (Seat *seat, const gchar *name)
131 {
132     SeatPrivate *priv = seat_get_instance_private (seat);
133 
134     g_return_if_fail (seat != NULL);
135     g_free (priv->name);
136     priv->name = g_strdup (name);
137 }
138 
139 void
seat_set_property(Seat * seat,const gchar * name,const gchar * value)140 seat_set_property (Seat *seat, const gchar *name, const gchar *value)
141 {
142     SeatPrivate *priv = seat_get_instance_private (seat);
143     g_return_if_fail (seat != NULL);
144     g_hash_table_insert (priv->properties, g_strdup (name), g_strdup (value));
145 }
146 
147 const gchar *
seat_get_string_property(Seat * seat,const gchar * name)148 seat_get_string_property (Seat *seat, const gchar *name)
149 {
150     SeatPrivate *priv = seat_get_instance_private (seat);
151     g_return_val_if_fail (seat != NULL, NULL);
152     return g_hash_table_lookup (priv->properties, name);
153 }
154 
155 gchar **
seat_get_string_list_property(Seat * seat,const gchar * name)156 seat_get_string_list_property (Seat *seat, const gchar *name)
157 {
158     SeatPrivate *priv = seat_get_instance_private (seat);
159     g_return_val_if_fail (seat != NULL, NULL);
160     return g_strsplit (g_hash_table_lookup (priv->properties, name), ";", 0);
161 }
162 
163 gboolean
seat_get_boolean_property(Seat * seat,const gchar * name)164 seat_get_boolean_property (Seat *seat, const gchar *name)
165 {
166     const gchar *value = seat_get_string_property (seat, name);
167     if (!value)
168         return FALSE;
169 
170     /* Count the number of non-whitespace characters */
171     gint length = 0;
172     for (gint i = 0; value[i]; i++)
173         if (!g_ascii_isspace (value[i]))
174             length = i + 1;
175 
176     return strncmp (value, "true", MAX (length, 4)) == 0;
177 }
178 
179 gint
seat_get_integer_property(Seat * seat,const gchar * name)180 seat_get_integer_property (Seat *seat, const gchar *name)
181 {
182     const gchar *value = seat_get_string_property (seat, name);
183     return value ? atoi (value) : 0;
184 }
185 
186 const gchar *
seat_get_name(Seat * seat)187 seat_get_name (Seat *seat)
188 {
189     SeatPrivate *priv = seat_get_instance_private (seat);
190     g_return_val_if_fail (seat != NULL, NULL);
191     return priv->name;
192 }
193 
194 void
seat_set_supports_multi_session(Seat * seat,gboolean supports_multi_session)195 seat_set_supports_multi_session (Seat *seat, gboolean supports_multi_session)
196 {
197     SeatPrivate *priv = seat_get_instance_private (seat);
198     g_return_if_fail (seat != NULL);
199     priv->supports_multi_session = supports_multi_session;
200 }
201 
202 void
seat_set_share_display_server(Seat * seat,gboolean share_display_server)203 seat_set_share_display_server (Seat *seat, gboolean share_display_server)
204 {
205     SeatPrivate *priv = seat_get_instance_private (seat);
206     g_return_if_fail (seat != NULL);
207     priv->share_display_server = share_display_server;
208 }
209 
210 gboolean
seat_start(Seat * seat)211 seat_start (Seat *seat)
212 {
213     SeatPrivate *priv = seat_get_instance_private (seat);
214 
215     g_return_val_if_fail (seat != NULL, FALSE);
216 
217     l_debug (seat, "Starting");
218 
219     SEAT_GET_CLASS (seat)->setup (seat);
220     priv->started = SEAT_GET_CLASS (seat)->start (seat);
221 
222     return priv->started;
223 }
224 
225 GList *
seat_get_sessions(Seat * seat)226 seat_get_sessions (Seat *seat)
227 {
228     SeatPrivate *priv = seat_get_instance_private (seat);
229     g_return_val_if_fail (seat != NULL, NULL);
230     return priv->sessions;
231 }
232 
233 static gboolean
set_greeter_idle(gpointer greeter)234 set_greeter_idle (gpointer greeter)
235 {
236     greeter_idle (GREETER (greeter));
237     return FALSE;
238 }
239 
240 void
seat_set_active_session(Seat * seat,Session * session)241 seat_set_active_session (Seat *seat, Session *session)
242 {
243     SeatPrivate *priv = seat_get_instance_private (seat);
244 
245     g_return_if_fail (seat != NULL);
246 
247     SEAT_GET_CLASS (seat)->set_active_session (seat, session);
248 
249     /* Stop any greeters */
250     for (GList *link = priv->sessions; link; link = link->next)
251     {
252         Session *s = link->data;
253 
254         if (s == session || session_get_is_stopping (s))
255             continue;
256 
257         if (IS_GREETER_SESSION (s))
258         {
259             Greeter *greeter = greeter_session_get_greeter (GREETER_SESSION (s));
260             if (greeter_get_resettable (greeter))
261             {
262                 if (priv->active_session == s)
263                 {
264                     l_debug (seat, "Idling greeter");
265                     /* Do this in an idle callback, because we might very well
266                        be in the middle of responding to a START_SESSION
267                        request by a greeter.  So they won't expect an IDLE
268                        call during that.  Plus, this isn't time-sensitive. */
269                     g_idle_add (set_greeter_idle, greeter);
270                 }
271             }
272             else
273             {
274                 l_debug (seat, "Stopping greeter");
275                 session_stop (s);
276             }
277         }
278     }
279 
280     /* Lock previous sessions */
281     if (priv->active_session && session != priv->active_session && !IS_GREETER_SESSION (priv->active_session))
282         session_lock (priv->active_session);
283 
284     session_activate (session);
285     g_clear_object (&priv->active_session);
286     priv->active_session = g_object_ref (session);
287 }
288 
289 Session *
seat_get_active_session(Seat * seat)290 seat_get_active_session (Seat *seat)
291 {
292     g_return_val_if_fail (seat != NULL, NULL);
293     return SEAT_GET_CLASS (seat)->get_active_session (seat);
294 }
295 
296 Session *
seat_get_next_session(Seat * seat)297 seat_get_next_session (Seat *seat)
298 {
299     SeatPrivate *priv = seat_get_instance_private (seat);
300     g_return_val_if_fail (seat != NULL, NULL);
301     return priv->next_session;
302 }
303 
304 /**
305  * Obtains the active session which lightdm expects to be active.
306  *
307  * This function is different from seat_get_active_session() in that the
308  * later (in the case of local seats) dynamically finds the session that is
309  * really active (based on the active VT), whereas this function returns the
310  * session that lightdm activated last by itself, which may not be the actual
311  * active session (i.e. VT changes).
312  */
313 Session *
seat_get_expected_active_session(Seat * seat)314 seat_get_expected_active_session (Seat *seat)
315 {
316     SeatPrivate *priv = seat_get_instance_private (seat);
317     g_return_val_if_fail (seat != NULL, NULL);
318     return priv->active_session;
319 }
320 
321 /**
322  * Sets the active session which lightdm expects to be active.
323  *
324  * This function is different from seat_set_active_session() in that the
325  * later performs an actual session activation, whereas this function just
326  * updates the active session after the session has been activated by some
327  * means external to lightdm (i.e. VT changes).
328  */
329 void
seat_set_externally_activated_session(Seat * seat,Session * session)330 seat_set_externally_activated_session (Seat *seat, Session *session)
331 {
332     SeatPrivate *priv = seat_get_instance_private (seat);
333     g_return_if_fail (seat != NULL);
334     g_clear_object (&priv->active_session);
335     priv->active_session = g_object_ref (session);
336 }
337 
338 Session *
seat_find_session_by_login1_id(Seat * seat,const gchar * login1_session_id)339 seat_find_session_by_login1_id (Seat *seat, const gchar *login1_session_id)
340 {
341     SeatPrivate *priv = seat_get_instance_private (seat);
342 
343     for (GList *session_link = priv->sessions; session_link; session_link = session_link->next)
344     {
345         Session *session = session_link->data;
346         if (g_strcmp0 (login1_session_id, session_get_login1_session_id (session)) == 0)
347             return session;
348     }
349 
350     return NULL;
351 }
352 
353 gboolean
seat_get_can_switch(Seat * seat)354 seat_get_can_switch (Seat *seat)
355 {
356     SeatPrivate *priv = seat_get_instance_private (seat);
357     g_return_val_if_fail (seat != NULL, FALSE);
358     return seat_get_boolean_property (seat, "allow-user-switching") && priv->supports_multi_session;
359 }
360 
361 gboolean
seat_get_allow_guest(Seat * seat)362 seat_get_allow_guest (Seat *seat)
363 {
364     g_return_val_if_fail (seat != NULL, FALSE);
365     return seat_get_boolean_property (seat, "allow-guest") && guest_account_is_installed ();
366 }
367 
368 static gboolean
run_script(Seat * seat,DisplayServer * display_server,const gchar * script_name,User * user)369 run_script (Seat *seat, DisplayServer *display_server, const gchar *script_name, User *user)
370 {
371     g_autoptr(Process) script = process_new (NULL, NULL);
372 
373     process_set_command (script, script_name);
374 
375     /* Set POSIX variables */
376     process_set_clear_environment (script, TRUE);
377     process_set_env (script, "SHELL", "/bin/sh");
378 
379     if (g_getenv ("LD_PRELOAD"))
380         process_set_env (script, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
381     if (g_getenv ("LD_LIBRARY_PATH"))
382         process_set_env (script, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
383     if (g_getenv ("PATH"))
384         process_set_env (script, "PATH", g_getenv ("PATH"));
385 
386     /* Variables required for regression tests */
387     if (g_getenv ("LIGHTDM_TEST_ROOT"))
388         process_set_env (script, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
389 
390     process_set_env (script, "XDG_SEAT", seat_get_name (seat));
391 
392     if (user)
393     {
394         process_set_env (script, "USER", user_get_name (user));
395         process_set_env (script, "LOGNAME", user_get_name (user));
396         process_set_env (script, "HOME", user_get_home_directory (user));
397     }
398     else
399         process_set_env (script, "HOME", "/");
400 
401     SEAT_GET_CLASS (seat)->run_script (seat, display_server, script);
402 
403     gboolean result = FALSE;
404     if (process_start (script, TRUE))
405     {
406         int exit_status = process_get_exit_status (script);
407         if (WIFEXITED (exit_status))
408         {
409             l_debug (seat, "Exit status of %s: %d", script_name, WEXITSTATUS (exit_status));
410             result = WEXITSTATUS (exit_status) == EXIT_SUCCESS;
411         }
412     }
413 
414     return result;
415 }
416 
417 static void
seat_real_run_script(Seat * seat,DisplayServer * display_server,Process * process)418 seat_real_run_script (Seat *seat, DisplayServer *display_server, Process *process)
419 {
420 }
421 
422 static void
emit_upstart_signal(const gchar * signal)423 emit_upstart_signal (const gchar *signal)
424 {
425     g_return_if_fail (signal != NULL);
426     g_return_if_fail (signal[0] != 0);
427 
428     if (getuid () != 0)
429         return;
430 
431     /* OK if it fails, probably not installed or not running upstart */
432     g_autoptr(GSubprocess) p = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_SILENCE, NULL, "initctl", "-q", "emit", signal, "DISPLAY_MANAGER=lightdm", NULL);
433 }
434 
435 static void
check_stopped(Seat * seat)436 check_stopped (Seat *seat)
437 {
438     SeatPrivate *priv = seat_get_instance_private (seat);
439 
440     if (priv->stopping &&
441         !priv->stopped &&
442         g_list_length (priv->display_servers) == 0 &&
443         g_list_length (priv->sessions) == 0)
444     {
445         priv->stopped = TRUE;
446         l_debug (seat, "Stopped");
447         g_signal_emit (seat, signals[STOPPED], 0);
448     }
449 }
450 
451 static void
display_server_stopped_cb(DisplayServer * display_server,Seat * seat)452 display_server_stopped_cb (DisplayServer *display_server, Seat *seat)
453 {
454     SeatPrivate *priv = seat_get_instance_private (seat);
455 
456     l_debug (seat, "Display server stopped");
457 
458     /* Run a script right after stopping the display server */
459     const gchar *script = seat_get_string_property (seat, "display-stopped-script");
460     if (script)
461         run_script (seat, NULL, script, NULL);
462 
463     g_signal_handlers_disconnect_matched (display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
464     priv->display_servers = g_list_remove (priv->display_servers, display_server);
465 
466     if (priv->stopping || !priv->started)
467     {
468         check_stopped (seat);
469         g_object_unref (display_server);
470         return;
471     }
472 
473     /* Stop all sessions on this display server */
474     GList *list = g_list_copy (priv->sessions);
475     for (GList *link = list; link; link = link->next)
476         g_object_ref (link->data);
477     for (GList *link = list; link; link = link->next)
478     {
479         Session *session = link->data;
480 
481         if (session_get_display_server (session) != display_server || session_get_is_stopping (session))
482             continue;
483 
484         gboolean is_failed_greeter = IS_GREETER_SESSION (session) && !session_get_is_started (session);
485 
486         l_debug (seat, "Stopping session");
487         session_stop (session);
488 
489         /* Stop seat if this is the only display server and it failed to start a greeter */
490         if (is_failed_greeter &&
491             g_list_length (priv->display_servers) == 0)
492         {
493             l_debug (seat, "Stopping; greeter display server failed to start");
494             seat_stop (seat);
495         }
496     }
497     g_list_free_full (list, g_object_unref);
498 
499     if (!priv->stopping)
500     {
501         /* If we were the active session, switch to a greeter */
502         Session *active_session = seat_get_active_session (seat);
503         if (!active_session || session_get_display_server (active_session) == display_server)
504         {
505             l_debug (seat, "Active display server stopped, starting greeter");
506             if (!seat_switch_to_greeter (seat))
507             {
508                 l_debug (seat, "Stopping; failed to start a greeter");
509                 seat_stop (seat);
510             }
511         }
512     }
513 
514     g_object_unref (display_server);
515 }
516 
517 static gboolean
can_share_display_server(Seat * seat,DisplayServer * display_server)518 can_share_display_server (Seat *seat, DisplayServer *display_server)
519 {
520     SeatPrivate *priv = seat_get_instance_private (seat);
521     return priv->share_display_server && display_server_get_can_share (display_server);
522 }
523 
524 static GreeterSession *
find_greeter_session(Seat * seat)525 find_greeter_session (Seat *seat)
526 {
527     SeatPrivate *priv = seat_get_instance_private (seat);
528 
529     for (GList *link = priv->sessions; link; link = link->next)
530     {
531         Session *session = link->data;
532         if (!session_get_is_stopping (session) && IS_GREETER_SESSION (session))
533             return GREETER_SESSION (session);
534     }
535 
536     return NULL;
537 }
538 
539 static GreeterSession *
find_resettable_greeter(Seat * seat)540 find_resettable_greeter (Seat *seat)
541 {
542     SeatPrivate *priv = seat_get_instance_private (seat);
543 
544     for (GList *link = priv->sessions; link; link = link->next)
545     {
546         Session *session = link->data;
547         if (!session_get_is_stopping (session) && IS_GREETER_SESSION (session) &&
548             greeter_get_resettable (greeter_session_get_greeter (GREETER_SESSION (session))))
549             return GREETER_SESSION (session);
550     }
551 
552     return NULL;
553 }
554 
555 static void
set_greeter_hints(Seat * seat,Greeter * greeter)556 set_greeter_hints (Seat *seat, Greeter *greeter)
557 {
558     greeter_clear_hints (greeter);
559     greeter_set_hint (greeter, "default-session", seat_get_string_property (seat, "user-session"));
560     greeter_set_hint (greeter, "hide-users", seat_get_boolean_property (seat, "greeter-hide-users") ? "true" : "false");
561     greeter_set_hint (greeter, "show-manual-login", seat_get_boolean_property (seat, "greeter-show-manual-login") ? "true" : "false");
562     greeter_set_hint (greeter, "show-remote-login", seat_get_boolean_property (seat, "greeter-show-remote-login") ? "true" : "false");
563     greeter_set_hint (greeter, "has-guest-account", seat_get_allow_guest (seat) && seat_get_boolean_property (seat, "greeter-allow-guest") ? "true" : "false");
564 }
565 
566 static void
switch_to_greeter_from_failed_session(Seat * seat,Session * session)567 switch_to_greeter_from_failed_session (Seat *seat, Session *session)
568 {
569     SeatPrivate *priv = seat_get_instance_private (seat);
570 
571     /* Switch to greeter if one open */
572     GreeterSession *greeter_session = find_resettable_greeter (seat);
573     gboolean existing = FALSE;
574     if (greeter_session)
575     {
576         l_debug (seat, "Switching to existing greeter");
577         set_greeter_hints (seat, greeter_session_get_greeter (greeter_session));
578         existing = TRUE;
579     }
580     else
581     {
582         greeter_session = create_greeter_session (seat);
583     }
584     Greeter *greeter = greeter_session_get_greeter (greeter_session);
585 
586     if (session_get_is_guest (session))
587         greeter_set_hint (greeter, "select-guest", "true");
588     else
589         greeter_set_hint (greeter, "select-user", session_get_username (session));
590 
591     if (existing)
592     {
593         greeter_reset (greeter);
594         seat_set_active_session (seat, SESSION (greeter_session));
595     }
596     else
597     {
598         g_clear_object (&priv->session_to_activate);
599         priv->session_to_activate = g_object_ref (SESSION (greeter_session));
600 
601         if (can_share_display_server (seat, session_get_display_server (session)))
602             session_set_display_server (SESSION (greeter_session), session_get_display_server (session));
603         else
604         {
605             DisplayServer *display_server = create_display_server (seat, session);
606             session_set_display_server (session, display_server);
607             if (!start_display_server (seat, display_server))
608             {
609                 l_debug (seat, "Failed to start display server for greeter");
610                 seat_stop (seat);
611             }
612         }
613 
614         start_session (seat, SESSION (greeter_session));
615     }
616 
617     /* Stop failed session */
618     session_stop (session);
619 }
620 
621 static void
start_session(Seat * seat,Session * session)622 start_session (Seat *seat, Session *session)
623 {
624     /* Use system location for greeter log file */
625     if (IS_GREETER_SESSION (session))
626     {
627         g_autofree gchar *log_dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
628         g_autofree gchar *filename = g_strdup_printf ("%s-greeter.log", seat_get_name (seat));
629         g_autofree gchar *log_filename = g_build_filename (log_dir, filename, NULL);
630         gboolean backup_logs = config_get_boolean (config_get_instance (), "LightDM", "backup-logs");
631         session_set_log_file (session, log_filename, backup_logs ? LOG_MODE_BACKUP_AND_TRUNCATE : LOG_MODE_APPEND);
632     }
633 
634     if (session_start (session))
635         return;
636 
637     if (IS_GREETER_SESSION (session))
638     {
639         l_debug (seat, "Failed to start greeter");
640         display_server_stop (session_get_display_server (session));
641         return;
642     }
643 
644     l_debug (seat, "Failed to start session, starting greeter");
645     switch_to_greeter_from_failed_session (seat, session);
646 }
647 
648 static void
run_session(Seat * seat,Session * session)649 run_session (Seat *seat, Session *session)
650 {
651     SeatPrivate *priv = seat_get_instance_private (seat);
652 
653     const gchar *script;
654     if (IS_GREETER_SESSION (session))
655         script = seat_get_string_property (seat, "greeter-setup-script");
656     else
657         script = seat_get_string_property (seat, "session-setup-script");
658     if (script && !run_script (seat, session_get_display_server (session), script, session_get_user (session)))
659     {
660         l_debug (seat, "Switching to greeter due to failed setup script");
661         switch_to_greeter_from_failed_session (seat, session);
662         return;
663     }
664 
665     if (!IS_GREETER_SESSION (session))
666     {
667         g_signal_emit (seat, signals[RUNNING_USER_SESSION], 0, session);
668         emit_upstart_signal ("desktop-session-start");
669     }
670 
671     session_run (session);
672 
673     // FIXME: Wait until the session is ready
674 
675     if (session == priv->session_to_activate)
676     {
677         seat_set_active_session (seat, session);
678         g_clear_object (&priv->session_to_activate);
679     }
680     else if (priv->active_session)
681     {
682         /* Multiple sessions can theoretically be on the same VT (especially
683            if using Mir).  If a new session appears on an existing active VT,
684            logind will mark it as active, while ConsoleKit will re-mark the
685            oldest session as active.  In either case, that may not be the
686            session that we want to be active.  So let's be explicit and
687            re-activate the correct session whenever a new session starts.
688            There's no harm to do this in seats that enforce separate VTs. */
689         session_activate (priv->active_session);
690     }
691 }
692 
693 static Session *
find_user_session(Seat * seat,const gchar * username,Session * ignore_session)694 find_user_session (Seat *seat, const gchar *username, Session *ignore_session)
695 {
696     SeatPrivate *priv = seat_get_instance_private (seat);
697 
698     if (!username)
699         return NULL;
700 
701     for (GList *link = priv->sessions; link; link = link->next)
702     {
703         Session *session = link->data;
704 
705         if (session == ignore_session)
706             continue;
707 
708         if (!session_get_is_stopping (session) && g_strcmp0 (session_get_username (session), username) == 0)
709             return session;
710     }
711 
712     return NULL;
713 }
714 
715 static void
greeter_active_username_changed_cb(Greeter * greeter,GParamSpec * pspec,Seat * seat)716 greeter_active_username_changed_cb (Greeter *greeter, GParamSpec *pspec, Seat *seat)
717 {
718     SeatPrivate *priv = seat_get_instance_private (seat);
719     Session *session = find_user_session (seat, greeter_get_active_username (greeter), priv->active_session);
720 
721     g_clear_object (&priv->next_session);
722     priv->next_session = session ? g_object_ref (session) : NULL;
723 
724     SEAT_GET_CLASS (seat)->set_next_session (seat, session);
725 }
726 
727 static void
session_authentication_complete_cb(Session * session,Seat * seat)728 session_authentication_complete_cb (Session *session, Seat *seat)
729 {
730     if (session_get_is_authenticated (session))
731     {
732         Session *s = find_user_session (seat, session_get_username (session), session);
733         if (s)
734         {
735             l_debug (seat, "Session authenticated, switching to existing user session");
736             seat_set_active_session (seat, s);
737             session_stop (session);
738         }
739         else
740         {
741             l_debug (seat, "Session authenticated, running command");
742             run_session (seat, session);
743         }
744     }
745     else if (!IS_GREETER_SESSION (session))
746     {
747         l_debug (seat, "Switching to greeter due to failed authentication");
748         switch_to_greeter_from_failed_session (seat, session);
749     }
750     else
751     {
752         l_debug (seat, "Stopping session that failed authentication");
753         session_stop (session);
754     }
755 }
756 
757 static void
session_stopped_cb(Session * session,Seat * seat)758 session_stopped_cb (Session *session, Seat *seat)
759 {
760     SeatPrivate *priv = seat_get_instance_private (seat);
761 
762     l_debug (seat, "Session stopped");
763 
764     g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
765     priv->sessions = g_list_remove (priv->sessions, session);
766     if (session == priv->active_session)
767         g_clear_object (&priv->active_session);
768     if (session == priv->next_session)
769         g_clear_object (&priv->next_session);
770     if (session == priv->session_to_activate)
771         g_clear_object (&priv->session_to_activate);
772 
773     DisplayServer *display_server = session_get_display_server (session);
774 
775     /* Cleanup */
776     if (!IS_GREETER_SESSION (session))
777     {
778         const gchar *script = seat_get_string_property (seat, "session-cleanup-script");
779         if (script)
780             run_script (seat, display_server, script, session_get_user (session));
781     }
782 
783     /* We were waiting for this session, but it didn't start :( */
784     // FIXME: Start a greeter on this?
785     if (session == priv->session_to_activate)
786         g_clear_object (&priv->session_to_activate);
787 
788     if (priv->stopping)
789     {
790         check_stopped (seat);
791         g_object_unref (session);
792         return;
793     }
794 
795     /* If there is a pending replacement greeter, start it */
796     if (IS_GREETER_SESSION (session) && priv->replacement_greeter)
797     {
798         GreeterSession *replacement_greeter = priv->replacement_greeter;
799         priv->replacement_greeter = NULL;
800 
801         if (session_get_is_authenticated (SESSION (replacement_greeter)))
802         {
803             l_debug (seat, "Greeter stopped, running session");
804             run_session (seat, SESSION (replacement_greeter));
805         }
806         else
807         {
808             l_debug (seat, "Greeter stopped, starting session authentication");
809             start_session (seat, SESSION (replacement_greeter));
810         }
811 
812         g_object_unref (replacement_greeter);
813     }
814     /* If this is the greeter session then re-use this display server */
815     else if (IS_GREETER_SESSION (session) &&
816         can_share_display_server (seat, display_server) &&
817         greeter_get_start_session (greeter_session_get_greeter (GREETER_SESSION (session))))
818     {
819         for (GList *link = priv->sessions; link; link = link->next)
820         {
821             Session *s = link->data;
822 
823             /* Skip this session and sessions on other display servers */
824             if (s == session || session_get_display_server (s) != display_server || session_get_is_stopping (s))
825                 continue;
826 
827             if (session_get_is_authenticated (s))
828             {
829                 l_debug (seat, "Greeter stopped, running session");
830                 run_session (seat, s);
831             }
832             else
833             {
834                 l_debug (seat, "Greeter stopped, starting session authentication");
835                 start_session (seat, s);
836             }
837             break;
838         }
839     }
840     /* If this is the greeter and nothing else is running then stop the seat */
841     else if (IS_GREETER_SESSION (session) &&
842         !greeter_get_start_session (greeter_session_get_greeter (GREETER_SESSION (session))) &&
843         g_list_length (priv->display_servers) == 1 &&
844         g_list_nth_data (priv->display_servers, 0) == display_server)
845     {
846         l_debug (seat, "Stopping; failed to start a greeter");
847         seat_stop (seat);
848     }
849     /* If we were the active session, switch to a greeter */
850     else if (!IS_GREETER_SESSION (session) && session == seat_get_active_session (seat))
851     {
852         l_debug (seat, "Active session stopped, starting greeter");
853         if (!seat_switch_to_greeter (seat))
854         {
855             l_debug (seat, "Stopping; failed to start a greeter");
856             seat_stop (seat);
857         }
858     }
859 
860     g_signal_emit (seat, signals[SESSION_REMOVED], 0, session);
861     g_object_unref (session);
862 
863     /* Stop the display server if no-longer required */
864     if (display_server && !display_server_get_is_stopping (display_server) &&
865         !SEAT_GET_CLASS (seat)->display_server_is_used (seat, display_server))
866     {
867         l_debug (seat, "Stopping display server, no sessions require it");
868         display_server_stop (display_server);
869     }
870 }
871 
872 static void
set_session_env(Session * session)873 set_session_env (Session *session)
874 {
875     /* Connect using the session bus */
876     if (getuid () != 0)
877     {
878         if (g_getenv ("DBUS_SESSION_BUS_ADDRESS"))
879             session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
880         session_set_env (session, "LDM_BUS", "SESSION");
881     }
882 
883     /* Variables required for regression tests */
884     if (g_getenv ("LIGHTDM_TEST_ROOT"))
885     {
886         session_set_env (session, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
887         session_set_env (session, "DBUS_SYSTEM_BUS_ADDRESS", g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
888         session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
889         session_set_env (session, "GI_TYPELIB_PATH", g_getenv ("GI_TYPELIB_PATH"));
890     }
891 
892     if (g_getenv ("LD_PRELOAD"))
893         session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
894     if (g_getenv ("LD_LIBRARY_PATH"))
895         session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
896 }
897 
898 static Session *
create_session(Seat * seat,gboolean autostart)899 create_session (Seat *seat, gboolean autostart)
900 {
901     SeatPrivate *priv = seat_get_instance_private (seat);
902 
903     Session *session = SEAT_GET_CLASS (seat)->create_session (seat);
904     priv->sessions = g_list_append (priv->sessions, session);
905     if (autostart)
906         g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (session_authentication_complete_cb), seat);
907     g_signal_connect (session, SESSION_SIGNAL_STOPPED, G_CALLBACK (session_stopped_cb), seat);
908 
909     set_session_env (session);
910 
911     g_signal_emit (seat, signals[SESSION_ADDED], 0, session);
912 
913     return session;
914 }
915 
916 static gchar **
get_session_argv(Seat * seat,SessionConfig * session_config,const gchar * session_wrapper)917 get_session_argv (Seat *seat, SessionConfig *session_config, const gchar *session_wrapper)
918 {
919     /* If configured, run sessions through a wrapper */
920     if (session_wrapper)
921     {
922         gchar **argv = g_malloc (sizeof (gchar *) * 3);
923         g_autofree gchar *path = g_find_program_in_path (session_wrapper);
924         argv[0] = path ? g_steal_pointer (&path) : g_strdup (session_wrapper);
925         argv[1] = g_strdup (session_config_get_command (session_config));
926         argv[2] = NULL;
927         return argv;
928     }
929 
930     /* Split command into an array listing and make command absolute */
931     int argc;
932     g_auto(GStrv) argv = NULL;
933     g_autoptr(GError) error = NULL;
934     gboolean result = g_shell_parse_argv (session_config_get_command (session_config), &argc, &argv, &error);
935     if (error)
936         l_debug (seat, "Invalid session command '%s': %s", session_config_get_command (session_config), error->message);
937     if (!result)
938         return NULL;
939     g_autofree gchar *path = g_find_program_in_path (argv[0]);
940     if (path)
941     {
942         g_free (argv[0]);
943         argv[0] = g_steal_pointer (&path);
944     }
945 
946     return g_steal_pointer (&argv);
947 }
948 
949 static SessionConfig *
find_session_config(Seat * seat,const gchar * sessions_dir,const gchar * session_name)950 find_session_config (Seat *seat, const gchar *sessions_dir, const gchar *session_name)
951 {
952     g_return_val_if_fail (sessions_dir != NULL, NULL);
953     g_return_val_if_fail (session_name != NULL, NULL);
954 
955     g_auto(GStrv) dirs = g_strsplit (sessions_dir, ":", -1);
956     for (int i = 0; dirs[i]; i++)
957     {
958         const gchar *default_session_type = "x";
959         if (strcmp (dirs[i], WAYLAND_SESSIONS_DIR) == 0)
960             default_session_type = "wayland";
961 
962         g_autofree gchar *filename = g_strdup_printf ("%s.desktop", session_name);
963         g_autofree gchar *path = g_build_filename (dirs[i], filename, NULL);
964         g_autoptr(GError) error = NULL;
965         SessionConfig *session_config = session_config_new_from_file (path, default_session_type, &error);
966         if (session_config)
967             return session_config;
968     }
969 
970     l_debug (seat, "Failed to find session configuration %s", session_name);
971 
972     return NULL;
973 }
974 
975 static void
configure_session(Session * session,SessionConfig * config,const gchar * session_name,const gchar * language)976 configure_session (Session *session, SessionConfig *config, const gchar *session_name, const gchar *language)
977 {
978     session_set_config (session, config);
979     session_set_env (session, "XDG_SESSION_DESKTOP", session_name);
980     session_set_env (session, "DESKTOP_SESSION", session_name);
981     session_set_env (session, "GDMSESSION", session_name);
982     gchar **desktop_names = session_config_get_desktop_names (config);
983     if (desktop_names)
984     {
985         g_autofree gchar *value = g_strjoinv (":", desktop_names);
986         session_set_env (session, "XDG_CURRENT_DESKTOP", value);
987     }
988     if (language && language[0] != '\0')
989     {
990         session_set_env (session, "LANG", language);
991         session_set_env (session, "GDM_LANG", language);
992     }
993 }
994 
995 static Session *
create_user_session(Seat * seat,const gchar * username,gboolean autostart)996 create_user_session (Seat *seat, const gchar *username, gboolean autostart)
997 {
998     l_debug (seat, "Creating user session");
999 
1000     /* Load user preferences */
1001     g_autoptr(User) user = accounts_get_user_by_name (username);
1002     if (!user)
1003     {
1004         l_debug (seat, "Can't login unknown user '%s'", username);
1005         return NULL;
1006     }
1007     const gchar *session_name = user_get_xsession (user);
1008     const gchar *language = user_get_language (user);
1009 
1010     /* Override session for autologin if configured */
1011     if (autostart)
1012     {
1013         const gchar *autologin_session_name = seat_get_string_property (seat, "autologin-session");
1014         if (autologin_session_name)
1015             session_name = autologin_session_name;
1016     }
1017 
1018     if (!session_name)
1019         session_name = seat_get_string_property (seat, "user-session");
1020     g_autofree gchar *sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
1021     g_autoptr(SessionConfig) session_config = find_session_config (seat, sessions_dir, session_name);
1022     if (!session_config)
1023     {
1024         l_debug (seat, "Can't find session '%s'", session_name);
1025         return NULL;
1026     }
1027 
1028     g_autoptr(Session) session = create_session (seat, autostart);
1029     configure_session (session, session_config, session_name, language);
1030     session_set_username (session, username);
1031     session_set_do_authenticate (session, TRUE);
1032     g_auto(GStrv) argv = get_session_argv (seat, session_config, seat_get_string_property (seat, "session-wrapper"));
1033     session_set_argv (session, argv);
1034 
1035     return g_steal_pointer (&session);
1036 }
1037 
1038 static void
prepend_argv(gchar *** argv,const gchar * value)1039 prepend_argv (gchar ***argv, const gchar *value)
1040 {
1041     gchar **old_argv = *argv;
1042     gchar **new_argv = g_malloc (sizeof (gchar *) * (g_strv_length (*argv) + 2));
1043     new_argv[0] = g_strdup (value);
1044     gint i;
1045     for (i = 0; old_argv[i]; i++)
1046         new_argv[i + 1] = old_argv[i];
1047     new_argv[i + 1] = NULL;
1048 
1049     g_free (*argv);
1050     *argv = new_argv;
1051 }
1052 
1053 static Session *
create_guest_session(Seat * seat,const gchar * session_name)1054 create_guest_session (Seat *seat, const gchar *session_name)
1055 {
1056     if (!session_name)
1057         session_name = seat_get_string_property (seat, "guest-session");
1058     if (!session_name)
1059         session_name = seat_get_string_property (seat, "user-session");
1060     g_autofree gchar *sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
1061     g_autoptr(SessionConfig) session_config = find_session_config (seat, sessions_dir, session_name);
1062     if (!session_config)
1063     {
1064         l_debug (seat, "Can't find session '%s'", session_name);
1065         return NULL;
1066     }
1067 
1068     g_autoptr(Session) session = create_session (seat, TRUE);
1069     configure_session (session, session_config, session_name, NULL);
1070     session_set_do_authenticate (session, TRUE);
1071     session_set_is_guest (session, TRUE);
1072     g_auto(GStrv) argv = get_session_argv (seat, session_config, seat_get_string_property (seat, "session-wrapper"));
1073     const gchar *guest_wrapper = seat_get_string_property (seat, "guest-wrapper");
1074     if (guest_wrapper)
1075     {
1076         g_autofree gchar *path = g_find_program_in_path (guest_wrapper);
1077         prepend_argv (&argv, path ? path : guest_wrapper);
1078     }
1079 
1080     session_set_argv (session, argv);
1081 
1082     return g_steal_pointer (&session);
1083 }
1084 
1085 // FIXME: This is inefficient and we already know the greeter session when we set the callbacks...
1086 static Session *
get_greeter_session(Seat * seat,Greeter * greeter)1087 get_greeter_session (Seat *seat, Greeter *greeter)
1088 {
1089     SeatPrivate *priv = seat_get_instance_private (seat);
1090 
1091     /* Stop any greeters */
1092     for (GList *link = priv->sessions; link; link = link->next)
1093     {
1094         Session *session = link->data;
1095 
1096         if (IS_GREETER_SESSION (session) && greeter_session_get_greeter (GREETER_SESSION (session)))
1097             return session;
1098     }
1099 
1100     return NULL;
1101 }
1102 
1103 static Session *
greeter_create_session_cb(Greeter * greeter,Seat * seat)1104 greeter_create_session_cb (Greeter *greeter, Seat *seat)
1105 {
1106     Session *greeter_session, *session;
1107 
1108     greeter_session = get_greeter_session (seat, greeter);
1109     session = create_session (seat, FALSE);
1110     session_set_config (session, session_get_config (greeter_session));
1111     session_set_display_server (session, session_get_display_server (greeter_session));
1112 
1113     return g_object_ref (session);
1114 }
1115 
1116 static gboolean
greeter_start_session_cb(Greeter * greeter,SessionType type,const gchar * session_name,Seat * seat)1117 greeter_start_session_cb (Greeter *greeter, SessionType type, const gchar *session_name, Seat *seat)
1118 {
1119     SeatPrivate *priv = seat_get_instance_private (seat);
1120 
1121     /* Get the session to use */
1122     Session *session;
1123     if (greeter_get_guest_authenticated (greeter))
1124     {
1125         session = g_object_ref (create_guest_session (seat, session_name));
1126         if (!session)
1127             return FALSE;
1128         session_set_pam_service (session, seat_get_string_property (seat, "pam-autologin-service"));
1129     }
1130     else
1131     {
1132         session = greeter_take_authentication_session (greeter);
1133 
1134         /* Get session command to run */
1135         g_autofree gchar *sessions_dir = NULL;
1136         switch (type)
1137         {
1138         case SESSION_TYPE_LOCAL:
1139             sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
1140             break;
1141         case SESSION_TYPE_REMOTE:
1142             sessions_dir = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory");
1143             break;
1144         }
1145 
1146         /* Load user preferences */
1147         const gchar *language = NULL;
1148         User *user = session_get_user (session);
1149         if (user)
1150         {
1151             const gchar *autologin_username;
1152 
1153             /* Override session for autologin if configured */
1154             autologin_username = seat_get_string_property (seat, "autologin-user");
1155             if (!session_name && g_strcmp0 (user_get_name (user), autologin_username) == 0)
1156                 session_name = seat_get_string_property (seat, "autologin-session");
1157 
1158             if (!session_name)
1159                 session_name = user_get_xsession (user);
1160             language = user_get_language (user);
1161         }
1162 
1163         if (!session_name)
1164             session_name = seat_get_string_property (seat, "user-session");
1165         if (user)
1166             user_set_xsession (session_get_user (session), session_name);
1167 
1168         g_autoptr(SessionConfig) session_config = find_session_config (seat, sessions_dir, session_name);
1169         if (!session_config)
1170         {
1171             l_debug (seat, "Can't find session '%s'", session_name);
1172             return FALSE;
1173         }
1174 
1175         configure_session (session, session_config, session_name, language);
1176         g_auto(GStrv) argv = get_session_argv (seat, session_config, seat_get_string_property (seat, "session-wrapper"));
1177         session_set_argv (session, argv);
1178     }
1179 
1180     /* Switch to this session when it is ready */
1181     g_clear_object (&priv->session_to_activate);
1182     priv->session_to_activate = session;
1183 
1184     /* Return to existing session if it is open */
1185     const gchar *username = session_get_username (session);
1186     Session *existing_session = find_user_session (seat, username, NULL);
1187     if (existing_session && session != existing_session)
1188     {
1189         l_debug (seat, "Returning to existing user session %s", username);
1190         session_stop (session);
1191         session_unlock (existing_session);
1192         seat_set_active_session (seat, existing_session);
1193         return TRUE;
1194     }
1195 
1196     /* If can re-use the display server, stop the greeter first */
1197     Session *greeter_session = get_greeter_session (seat, greeter);
1198     if (greeter_session)
1199     {
1200         DisplayServer *display_server = session_get_display_server (greeter_session);
1201         if (display_server &&
1202             !greeter_get_resettable (greeter) &&
1203             can_share_display_server (seat, display_server) &&
1204             strcmp (display_server_get_session_type (display_server), session_get_session_type (session)) == 0)
1205         {
1206             l_debug (seat, "Stopping greeter; display server will be re-used for user session");
1207 
1208             /* Run on the same display server after the greeter has stopped */
1209             session_set_display_server (session, display_server);
1210 
1211             /* Stop the greeter */
1212             session_stop (greeter_session);
1213 
1214             return TRUE;
1215         }
1216     }
1217 
1218     /* Otherwise start a new display server for this session */
1219     DisplayServer *display_server = create_display_server (seat, session);
1220     session_set_display_server (session, display_server);
1221     if (!start_display_server (seat, display_server))
1222     {
1223         l_debug (seat, "Failed to start display server for new session");
1224         return FALSE;
1225     }
1226 
1227     return TRUE;
1228 }
1229 
1230 static GreeterSession *
create_greeter_session(Seat * seat)1231 create_greeter_session (Seat *seat)
1232 {
1233     SeatPrivate *priv = seat_get_instance_private (seat);
1234 
1235     l_debug (seat, "Creating greeter session");
1236 
1237     g_autofree gchar *sessions_dir = config_get_string (config_get_instance (), "LightDM", "greeters-directory");
1238     g_autoptr(SessionConfig) session_config = find_session_config (seat, sessions_dir, seat_get_string_property (seat, "greeter-session"));
1239     if (!session_config)
1240         return NULL;
1241 
1242     g_auto(GStrv) argv = get_session_argv (seat, session_config, NULL);
1243     const gchar *greeter_wrapper = seat_get_string_property (seat, "greeter-wrapper");
1244     if (greeter_wrapper)
1245     {
1246         g_autofree gchar *path = g_find_program_in_path (greeter_wrapper);
1247         prepend_argv (&argv, path ? path : greeter_wrapper);
1248     }
1249 
1250     GreeterSession *greeter_session = SEAT_GET_CLASS (seat)->create_greeter_session (seat);
1251     Greeter *greeter = greeter_session_get_greeter (greeter_session);
1252     session_set_config (SESSION (greeter_session), session_config);
1253     priv->sessions = g_list_append (priv->sessions, SESSION (greeter_session));
1254     g_signal_connect (greeter, GREETER_SIGNAL_ACTIVE_USERNAME_CHANGED, G_CALLBACK (greeter_active_username_changed_cb), seat);
1255     g_signal_connect (greeter_session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (session_authentication_complete_cb), seat);
1256     g_signal_connect (greeter_session, SESSION_SIGNAL_STOPPED, G_CALLBACK (session_stopped_cb), seat);
1257 
1258     set_session_env (SESSION (greeter_session));
1259     session_set_env (SESSION (greeter_session), "XDG_SESSION_CLASS", "greeter");
1260 
1261     session_set_pam_service (SESSION (greeter_session), seat_get_string_property (seat, "pam-greeter-service"));
1262     if (getuid () == 0)
1263     {
1264         g_autofree gchar *greeter_user = config_get_string (config_get_instance (), "LightDM", "greeter-user");
1265         session_set_username (SESSION (greeter_session), greeter_user);
1266     }
1267     else
1268     {
1269         /* In test mode run the greeter as ourself */
1270         session_set_username (SESSION (greeter_session), user_get_name (accounts_get_current_user ()));
1271     }
1272     session_set_argv (SESSION (greeter_session), argv);
1273 
1274     greeter_set_pam_services (greeter,
1275                               seat_get_string_property (seat, "pam-service"),
1276                               seat_get_string_property (seat, "pam-autologin-service"));
1277     g_signal_connect (greeter, GREETER_SIGNAL_CREATE_SESSION, G_CALLBACK (greeter_create_session_cb), seat);
1278     g_signal_connect (greeter, GREETER_SIGNAL_START_SESSION, G_CALLBACK (greeter_start_session_cb), seat);
1279 
1280     /* Set hints to greeter */
1281     greeter_set_allow_guest (greeter, seat_get_allow_guest (seat));
1282     set_greeter_hints (seat, greeter);
1283 
1284     /* Configure for automatic login */
1285     const gchar *autologin_username = seat_get_string_property (seat, "autologin-user");
1286     if (g_strcmp0 (autologin_username, "") == 0)
1287         autologin_username = NULL;
1288     const gchar *autologin_session = seat_get_string_property (seat, "autologin-session");
1289     if (g_strcmp0 (autologin_session, "") == 0)
1290         autologin_session = NULL;
1291     int autologin_timeout = seat_get_integer_property (seat, "autologin-user-timeout");
1292     gboolean autologin_guest = seat_get_boolean_property (seat, "autologin-guest");
1293     if (autologin_timeout > 0)
1294     {
1295         g_autofree gchar *value = g_strdup_printf ("%d", autologin_timeout);
1296         greeter_set_hint (greeter, "autologin-timeout", value);
1297         if (autologin_username)
1298             greeter_set_hint (greeter, "autologin-user", autologin_username);
1299         if (autologin_session)
1300             greeter_set_hint (greeter, "autologin-session", autologin_session);
1301         if (autologin_guest)
1302             greeter_set_hint (greeter, "autologin-guest", "true");
1303     }
1304 
1305     return greeter_session;
1306 }
1307 
1308 static Session *
find_session_for_display_server(Seat * seat,DisplayServer * display_server)1309 find_session_for_display_server (Seat *seat, DisplayServer *display_server)
1310 {
1311     SeatPrivate *priv = seat_get_instance_private (seat);
1312 
1313     for (GList *link = priv->sessions; link; link = link->next)
1314     {
1315         Session *session = link->data;
1316 
1317         if (session_get_display_server (session) == display_server &&
1318             !session_get_is_stopping (session) &&
1319             !session_get_is_run (session))
1320             return session;
1321     }
1322 
1323     return NULL;
1324 }
1325 
1326 static void
display_server_ready_cb(DisplayServer * display_server,Seat * seat)1327 display_server_ready_cb (DisplayServer *display_server, Seat *seat)
1328 {
1329     /* Run setup script */
1330     const gchar *script = seat_get_string_property (seat, "display-setup-script");
1331     if (script && !run_script (seat, display_server, script, NULL))
1332     {
1333         l_debug (seat, "Stopping display server due to failed setup script");
1334         display_server_stop (display_server);
1335         return;
1336     }
1337 
1338     emit_upstart_signal ("login-session-start");
1339 
1340     /* Start the session waiting for this display server */
1341     Session *session = find_session_for_display_server (seat, display_server);
1342     if (session)
1343     {
1344         if (session_get_is_authenticated (session))
1345         {
1346             l_debug (seat, "Display server ready, running session");
1347             run_session (seat, session);
1348         }
1349         else
1350         {
1351             l_debug (seat, "Display server ready, starting session authentication");
1352             start_session (seat, session);
1353         }
1354     }
1355     else
1356     {
1357         l_debug (seat, "Stopping not required display server");
1358         display_server_stop (display_server);
1359     }
1360 }
1361 
1362 static DisplayServer *
create_display_server(Seat * seat,Session * session)1363 create_display_server (Seat *seat, Session *session)
1364 {
1365     SeatPrivate *priv = seat_get_instance_private (seat);
1366 
1367     l_debug (seat, "Creating display server of type %s", session_get_session_type (session));
1368 
1369     DisplayServer *display_server = SEAT_GET_CLASS (seat)->create_display_server (seat, session);
1370     if (!display_server)
1371         return NULL;
1372 
1373     /* Remember this display server */
1374     if (!g_list_find (priv->display_servers, display_server))
1375     {
1376         priv->display_servers = g_list_append (priv->display_servers, display_server);
1377         g_signal_connect (display_server, DISPLAY_SERVER_SIGNAL_READY, G_CALLBACK (display_server_ready_cb), seat);
1378         g_signal_connect (display_server, DISPLAY_SERVER_SIGNAL_STOPPED, G_CALLBACK (display_server_stopped_cb), seat);
1379     }
1380 
1381     return display_server;
1382 }
1383 
1384 static gboolean
start_display_server(Seat * seat,DisplayServer * display_server)1385 start_display_server (Seat *seat, DisplayServer *display_server)
1386 {
1387     if (display_server_get_is_ready (display_server))
1388     {
1389         display_server_ready_cb (display_server, seat);
1390         return TRUE;
1391     }
1392     else
1393         return display_server_start (display_server);
1394 }
1395 
1396 gboolean
seat_switch_to_greeter(Seat * seat)1397 seat_switch_to_greeter (Seat *seat)
1398 {
1399     SeatPrivate *priv = seat_get_instance_private (seat);
1400 
1401     g_return_val_if_fail (seat != NULL, FALSE);
1402 
1403     if (!seat_get_can_switch (seat) && priv->sessions != NULL)
1404         return FALSE;
1405 
1406     /* Switch to greeter if one open */
1407     GreeterSession *greeter_session = find_greeter_session (seat);
1408     if (greeter_session)
1409     {
1410         l_debug (seat, "Switching to existing greeter");
1411         seat_set_active_session (seat, SESSION (greeter_session));
1412         return TRUE;
1413     }
1414 
1415     greeter_session = create_greeter_session (seat);
1416     if (!greeter_session)
1417         return FALSE;
1418 
1419     g_clear_object (&priv->session_to_activate);
1420     priv->session_to_activate = g_object_ref (SESSION (greeter_session));
1421 
1422     DisplayServer *display_server = create_display_server (seat, SESSION (greeter_session));
1423     if (!display_server) {
1424         g_clear_object (&priv->session_to_activate);
1425         return FALSE;
1426     }
1427     session_set_display_server (SESSION (greeter_session), display_server);
1428 
1429     return start_display_server (seat, display_server);
1430 }
1431 
1432 static void
switch_authentication_complete_cb(Session * session,Seat * seat)1433 switch_authentication_complete_cb (Session *session, Seat *seat)
1434 {
1435     SeatPrivate *priv = seat_get_instance_private (seat);
1436 
1437     /* If authenticated, then unlock existing session or start new one */
1438     if (session_get_is_authenticated (session))
1439     {
1440         Session *s = find_user_session (seat, session_get_username (session), session);
1441         if (s)
1442         {
1443             l_debug (seat, "Session authenticated, switching to existing user session");
1444             session_unlock (s);
1445             seat_set_active_session (seat, s);
1446             session_stop (session);
1447         }
1448         else
1449         {
1450             l_debug (seat, "Session authenticated, starting display server");
1451             g_clear_object (&priv->session_to_activate);
1452             priv->session_to_activate = g_object_ref (session);
1453             DisplayServer *display_server = create_display_server (seat, session);
1454             session_set_display_server (session, display_server);
1455             start_display_server (seat, display_server);
1456         }
1457 
1458         return;
1459     }
1460 
1461     session_stop (session);
1462 
1463     /* See if we already have a greeter up and reuse it if so */
1464     GreeterSession *greeter_session = find_resettable_greeter (seat);
1465     gboolean existing = FALSE;
1466     if (greeter_session)
1467     {
1468         l_debug (seat, "Switching to existing greeter to authenticate session");
1469         set_greeter_hints (seat, greeter_session_get_greeter (greeter_session));
1470         existing = TRUE;
1471     }
1472     else
1473     {
1474         l_debug (seat, "Starting greeter to authenticate session");
1475         greeter_session = create_greeter_session (seat);
1476     }
1477     Greeter *greeter = greeter_session_get_greeter (greeter_session);
1478 
1479     if (session_get_is_guest (session))
1480         greeter_set_hint (greeter, "select-guest", "true");
1481     else
1482         greeter_set_hint (greeter, "select-user", session_get_username (session));
1483 
1484     if (existing)
1485     {
1486         greeter_reset (greeter);
1487         seat_set_active_session (seat, SESSION (greeter_session));
1488     }
1489     else
1490     {
1491         g_clear_object (&priv->session_to_activate);
1492         priv->session_to_activate = g_object_ref (SESSION (greeter_session));
1493 
1494         DisplayServer *display_server = create_display_server (seat, SESSION (greeter_session));
1495         session_set_display_server (SESSION (greeter_session), display_server);
1496         start_display_server (seat, display_server);
1497     }
1498 }
1499 
1500 gboolean
seat_switch_to_user(Seat * seat,const gchar * username,const gchar * session_name)1501 seat_switch_to_user (Seat *seat, const gchar *username, const gchar *session_name)
1502 {
1503     SeatPrivate *priv = seat_get_instance_private (seat);
1504 
1505     g_return_val_if_fail (seat != NULL, FALSE);
1506     g_return_val_if_fail (username != NULL, FALSE);
1507 
1508     if (!seat_get_can_switch (seat))
1509         return FALSE;
1510 
1511     /* If we're already on this session, then ignore */
1512     Session *session = find_user_session (seat, username, NULL);
1513     if (session && session == priv->active_session)
1514         return TRUE;
1515 
1516     l_debug (seat, "Switching to user %s", username);
1517 
1518     /* Attempt to authenticate them */
1519     session = create_user_session (seat, username, FALSE);
1520     g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (switch_authentication_complete_cb), seat);
1521     session_set_pam_service (session, seat_get_string_property (seat, "pam-service"));
1522 
1523     return session_start (session);
1524 }
1525 
1526 static Session *
find_guest_session(Seat * seat)1527 find_guest_session (Seat *seat)
1528 {
1529     SeatPrivate *priv = seat_get_instance_private (seat);
1530 
1531     for (GList *link = priv->sessions; link; link = link->next)
1532     {
1533         Session *session = link->data;
1534         if (!session_get_is_stopping (session) && session_get_is_guest (session))
1535             return session;
1536     }
1537 
1538     return NULL;
1539 }
1540 
1541 gboolean
seat_switch_to_guest(Seat * seat,const gchar * session_name)1542 seat_switch_to_guest (Seat *seat, const gchar *session_name)
1543 {
1544     SeatPrivate *priv = seat_get_instance_private (seat);
1545 
1546     g_return_val_if_fail (seat != NULL, FALSE);
1547 
1548     if (!seat_get_can_switch (seat) || !seat_get_allow_guest (seat))
1549         return FALSE;
1550 
1551     /* Switch to session if one open */
1552     Session *session = find_guest_session (seat);
1553     if (session)
1554     {
1555         l_debug (seat, "Switching to existing guest account %s", session_get_username (session));
1556         seat_set_active_session (seat, session);
1557         return TRUE;
1558     }
1559 
1560     session = create_guest_session (seat, session_name);
1561     if (!session)
1562         return FALSE;
1563 
1564     DisplayServer *display_server = create_display_server (seat, session);
1565 
1566     g_clear_object (&priv->session_to_activate);
1567     priv->session_to_activate = g_object_ref (session);
1568     session_set_pam_service (session, seat_get_string_property (seat, "pam-autologin-service"));
1569     session_set_display_server (session, display_server);
1570 
1571     return start_display_server (seat, display_server);
1572 }
1573 
1574 gboolean
seat_lock(Seat * seat,const gchar * username)1575 seat_lock (Seat *seat, const gchar *username)
1576 {
1577     SeatPrivate *priv = seat_get_instance_private (seat);
1578 
1579     g_return_val_if_fail (seat != NULL, FALSE);
1580 
1581     if (!seat_get_can_switch (seat))
1582         return FALSE;
1583 
1584     // FIXME: If already locked then don't bother...
1585 
1586     l_debug (seat, "Locking");
1587 
1588     /* Switch to greeter we can reuse */
1589     gboolean reset_existing = FALSE;
1590     gboolean reuse_xserver = FALSE;
1591     DisplayServer *display_server = NULL;
1592     GreeterSession *greeter_session = find_resettable_greeter (seat);
1593     if (greeter_session)
1594     {
1595         l_debug (seat, "Switching to existing greeter");
1596         set_greeter_hints (seat, greeter_session_get_greeter (greeter_session));
1597         reset_existing = TRUE;
1598     }
1599     else
1600     {
1601         /* If the existing greeter can't be reused, stop it and reuse its display server */
1602         greeter_session = find_greeter_session (seat);
1603         if (greeter_session)
1604         {
1605             display_server = session_get_display_server (SESSION (greeter_session));
1606             if (!session_get_is_stopping (SESSION (greeter_session)))
1607             {
1608                 l_debug (seat, "Stopping session");
1609                 session_stop (SESSION (greeter_session));
1610             }
1611             reuse_xserver = TRUE;
1612         }
1613 
1614         greeter_session = create_greeter_session (seat);
1615         if (!greeter_session)
1616             return FALSE;
1617     }
1618     Greeter *greeter = greeter_session_get_greeter (greeter_session);
1619 
1620     greeter_set_hint (greeter, "lock-screen", "true");
1621     if (username)
1622         greeter_set_hint (greeter, "select-user", username);
1623 
1624     if (reset_existing)
1625     {
1626         greeter_reset (greeter);
1627         seat_set_active_session (seat, SESSION (greeter_session));
1628         return TRUE;
1629     }
1630     else
1631     {
1632         if (!reuse_xserver)
1633             display_server = create_display_server (seat, SESSION (greeter_session));
1634         session_set_display_server (SESSION (greeter_session), display_server);
1635 
1636         g_clear_object (&priv->session_to_activate);
1637         priv->session_to_activate = g_object_ref (SESSION (greeter_session));
1638 
1639         if (reuse_xserver)
1640         {
1641             g_clear_object (&priv->replacement_greeter);
1642             priv->replacement_greeter = g_object_ref (greeter_session);
1643             return TRUE;
1644         }
1645         else
1646             return start_display_server (seat, display_server);
1647     }
1648 }
1649 
1650 void
seat_stop(Seat * seat)1651 seat_stop (Seat *seat)
1652 {
1653     SeatPrivate *priv = seat_get_instance_private (seat);
1654 
1655     g_return_if_fail (seat != NULL);
1656 
1657     if (priv->stopping)
1658         return;
1659 
1660     l_debug (seat, "Stopping");
1661     priv->stopping = TRUE;
1662     SEAT_GET_CLASS (seat)->stop (seat);
1663 }
1664 
1665 gboolean
seat_get_is_stopping(Seat * seat)1666 seat_get_is_stopping (Seat *seat)
1667 {
1668     SeatPrivate *priv = seat_get_instance_private (seat);
1669     g_return_val_if_fail (seat != NULL, FALSE);
1670     return priv->stopping;
1671 }
1672 
1673 static void
seat_real_setup(Seat * seat)1674 seat_real_setup (Seat *seat)
1675 {
1676 }
1677 
1678 static gboolean
seat_real_start(Seat * seat)1679 seat_real_start (Seat *seat)
1680 {
1681     SeatPrivate *priv = seat_get_instance_private (seat);
1682 
1683     /* Get autologin settings */
1684     const gchar *autologin_username = seat_get_string_property (seat, "autologin-user");
1685     if (g_strcmp0 (autologin_username, "") == 0)
1686         autologin_username = NULL;
1687     int autologin_timeout = seat_get_integer_property (seat, "autologin-user-timeout");
1688     gboolean autologin_guest = seat_get_boolean_property (seat, "autologin-guest");
1689     gboolean autologin_in_background = seat_get_boolean_property (seat, "autologin-in-background");
1690 
1691     /* Autologin if configured */
1692     Session *session = NULL, *background_session = NULL;
1693     if (autologin_timeout == 0 || autologin_in_background)
1694     {
1695         if (autologin_guest)
1696             session = create_guest_session (seat, NULL);
1697         else if (autologin_username != NULL)
1698             session = create_user_session (seat, autologin_username, TRUE);
1699 
1700         if (session)
1701             session_set_pam_service (session, seat_get_string_property (seat, "pam-autologin-service"));
1702 
1703         /* Load in background if required */
1704         if (autologin_in_background && session)
1705         {
1706             background_session = session;
1707             session = NULL;
1708         }
1709 
1710         if (session)
1711         {
1712             g_clear_object (&priv->session_to_activate);
1713             priv->session_to_activate = g_object_ref (session);
1714 
1715             DisplayServer *display_server = create_display_server (seat, session);
1716             session_set_display_server (session, display_server);
1717             if (!display_server || !start_display_server (seat, display_server))
1718             {
1719                 l_debug (seat, "Can't create display server for automatic login");
1720                 session_stop (session);
1721                 if (display_server)
1722                     display_server_stop (display_server);
1723                 session = NULL;
1724             }
1725         }
1726     }
1727 
1728     /* Fallback to a greeter */
1729     if (!session)
1730     {
1731         GreeterSession *greeter_session = create_greeter_session (seat);
1732         if (!greeter_session)
1733         {
1734             l_debug (seat, "Failed to create greeter session");
1735             return FALSE;
1736         }
1737 
1738         g_clear_object (&priv->session_to_activate);
1739         session = SESSION (greeter_session);
1740         priv->session_to_activate = g_object_ref (session);
1741 
1742         DisplayServer *display_server = create_display_server (seat, session);
1743         session_set_display_server (session, display_server);
1744         if (!display_server || !start_display_server (seat, display_server))
1745         {
1746             l_debug (seat, "Can't create display server for greeter");
1747             session_stop (session);
1748             if (display_server)
1749                 display_server_stop (display_server);
1750             session = NULL;
1751         }
1752     }
1753 
1754     /* Fail if can't start a session */
1755     if (!session)
1756     {
1757         seat_stop (seat);
1758         return FALSE;
1759     }
1760 
1761     /* Start background session */
1762     if (background_session)
1763     {
1764         DisplayServer *background_display_server = create_display_server (seat, background_session);
1765         session_set_display_server (background_session, background_display_server);
1766         if (!start_display_server (seat, background_display_server))
1767             l_warning (seat, "Failed to start display server for background session");
1768     }
1769 
1770     return TRUE;
1771 }
1772 
1773 static DisplayServer *
seat_real_create_display_server(Seat * seat,Session * session)1774 seat_real_create_display_server (Seat *seat, Session *session)
1775 {
1776     return NULL;
1777 }
1778 
1779 static gboolean
seat_real_display_server_is_used(Seat * seat,DisplayServer * display_server)1780 seat_real_display_server_is_used (Seat *seat, DisplayServer *display_server)
1781 {
1782     SeatPrivate *priv = seat_get_instance_private (seat);
1783 
1784     for (GList *link = priv->sessions; link; link = link->next)
1785     {
1786         Session *session = link->data;
1787 
1788         DisplayServer *d = session_get_display_server (session);
1789         if (!d)
1790             continue;
1791 
1792         if (d == display_server || display_server_get_parent (d) == display_server)
1793             return TRUE;
1794     }
1795 
1796     return FALSE;
1797 }
1798 
1799 static GreeterSession *
seat_real_create_greeter_session(Seat * seat)1800 seat_real_create_greeter_session (Seat *seat)
1801 {
1802     return greeter_session_new ();
1803 }
1804 
1805 static Session *
create_session_cb(Greeter * greeter,Seat * seat)1806 create_session_cb (Greeter *greeter, Seat *seat)
1807 {
1808     return g_object_ref (create_session (seat, FALSE));
1809 }
1810 
1811 static Greeter *
create_greeter_cb(Session * session,Seat * seat)1812 create_greeter_cb (Session *session, Seat *seat)
1813 {
1814     g_autoptr(Greeter) greeter = greeter_new ();
1815 
1816     greeter_set_pam_services (greeter,
1817                               seat_get_string_property (seat, "pam-service"),
1818                               seat_get_string_property (seat, "pam-autologin-service"));
1819     g_signal_connect (greeter, GREETER_SIGNAL_CREATE_SESSION, G_CALLBACK (create_session_cb), seat);
1820     g_signal_connect (greeter, GREETER_SIGNAL_START_SESSION, G_CALLBACK (greeter_start_session_cb), seat);
1821 
1822     /* Set hints to greeter */
1823     greeter_set_allow_guest (greeter, seat_get_allow_guest (seat));
1824     set_greeter_hints (seat, greeter);
1825 
1826     return g_steal_pointer (&greeter);
1827 }
1828 
1829 static Session *
seat_real_create_session(Seat * seat)1830 seat_real_create_session (Seat *seat)
1831 {
1832     g_autoptr(Session) session = session_new ();
1833     g_signal_connect (session, SESSION_SIGNAL_CREATE_GREETER, G_CALLBACK (create_greeter_cb), seat);
1834 
1835     return g_steal_pointer (&session);
1836 }
1837 
1838 static void
seat_real_set_active_session(Seat * seat,Session * session)1839 seat_real_set_active_session (Seat *seat, Session *session)
1840 {
1841 }
1842 
1843 static void
seat_real_set_next_session(Seat * seat,Session * session)1844 seat_real_set_next_session (Seat *seat, Session *session)
1845 {
1846 }
1847 
1848 static Session *
seat_real_get_active_session(Seat * seat)1849 seat_real_get_active_session (Seat *seat)
1850 {
1851     return NULL;
1852 }
1853 
1854 static void
seat_real_stop(Seat * seat)1855 seat_real_stop (Seat *seat)
1856 {
1857     SeatPrivate *priv = seat_get_instance_private (seat);
1858 
1859     check_stopped (seat);
1860     if (priv->stopped)
1861         return;
1862 
1863     /* Stop all the display servers and sessions on the seat. Copy the list as
1864      * it might be modified if a display server / session stops during this loop */
1865     GList *list = g_list_copy (priv->display_servers);
1866     for (GList *link = list; link; link = link->next)
1867         g_object_ref (link->data);
1868     for (GList *link = list; link; link = link->next)
1869     {
1870         DisplayServer *display_server = link->data;
1871         if (!display_server_get_is_stopping (display_server))
1872         {
1873             l_debug (seat, "Stopping display server");
1874             display_server_stop (display_server);
1875         }
1876     }
1877     g_list_free_full (list, g_object_unref);
1878     list = g_list_copy (priv->sessions);
1879     for (GList *link = list; link; link = link->next)
1880         g_object_ref (link->data);
1881     for (GList *link = list; link; link = link->next)
1882     {
1883         Session *session = link->data;
1884         if (!session_get_is_stopping (session))
1885         {
1886             l_debug (seat, "Stopping session");
1887             session_stop (session);
1888         }
1889     }
1890     g_list_free_full (list, g_object_unref);
1891 }
1892 
1893 static void
seat_init(Seat * seat)1894 seat_init (Seat *seat)
1895 {
1896     SeatPrivate *priv = seat_get_instance_private (seat);
1897 
1898     priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1899     priv->share_display_server = TRUE;
1900 }
1901 
1902 static void
seat_finalize(GObject * object)1903 seat_finalize (GObject *object)
1904 {
1905     Seat *self = SEAT (object);
1906     SeatPrivate *priv = seat_get_instance_private (SEAT (self));
1907 
1908     g_free (priv->name);
1909     g_hash_table_unref (priv->properties);
1910     for (GList *link = priv->display_servers; link; link = link->next)
1911     {
1912         DisplayServer *display_server = link->data;
1913         g_signal_handlers_disconnect_matched (display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
1914     }
1915     g_list_free_full (priv->display_servers, g_object_unref);
1916     for (GList *link = priv->sessions; link; link = link->next)
1917     {
1918         Session *session = link->data;
1919         g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
1920     }
1921     g_list_free_full (priv->sessions, g_object_unref);
1922     g_clear_object (&priv->active_session);
1923     g_clear_object (&priv->next_session);
1924     g_clear_object (&priv->session_to_activate);
1925     g_clear_object (&priv->replacement_greeter);
1926 
1927     G_OBJECT_CLASS (seat_parent_class)->finalize (object);
1928 }
1929 
1930 static void
seat_class_init(SeatClass * klass)1931 seat_class_init (SeatClass *klass)
1932 {
1933     GObjectClass *object_class = G_OBJECT_CLASS (klass);
1934 
1935     klass->setup = seat_real_setup;
1936     klass->start = seat_real_start;
1937     klass->create_display_server = seat_real_create_display_server;
1938     klass->display_server_is_used = seat_real_display_server_is_used;
1939     klass->create_greeter_session = seat_real_create_greeter_session;
1940     klass->create_session = seat_real_create_session;
1941     klass->set_active_session = seat_real_set_active_session;
1942     klass->get_active_session = seat_real_get_active_session;
1943     klass->set_next_session = seat_real_set_next_session;
1944     klass->run_script = seat_real_run_script;
1945     klass->stop = seat_real_stop;
1946 
1947     object_class->finalize = seat_finalize;
1948 
1949     signals[SESSION_ADDED] =
1950         g_signal_new (SEAT_SIGNAL_SESSION_ADDED,
1951                       G_TYPE_FROM_CLASS (klass),
1952                       G_SIGNAL_RUN_LAST,
1953                       G_STRUCT_OFFSET (SeatClass, session_added),
1954                       NULL, NULL,
1955                       NULL,
1956                       G_TYPE_NONE, 1, SESSION_TYPE);
1957     signals[RUNNING_USER_SESSION] =
1958         g_signal_new (SEAT_SIGNAL_RUNNING_USER_SESSION,
1959                       G_TYPE_FROM_CLASS (klass),
1960                       G_SIGNAL_RUN_LAST,
1961                       G_STRUCT_OFFSET (SeatClass, running_user_session),
1962                       NULL, NULL,
1963                       NULL,
1964                       G_TYPE_NONE, 1, SESSION_TYPE);
1965     signals[SESSION_REMOVED] =
1966         g_signal_new (SEAT_SIGNAL_SESSION_REMOVED,
1967                       G_TYPE_FROM_CLASS (klass),
1968                       G_SIGNAL_RUN_LAST,
1969                       G_STRUCT_OFFSET (SeatClass, session_removed),
1970                       NULL, NULL,
1971                       NULL,
1972                       G_TYPE_NONE, 1, SESSION_TYPE);
1973     signals[STOPPED] =
1974         g_signal_new (SEAT_SIGNAL_STOPPED,
1975                       G_TYPE_FROM_CLASS (klass),
1976                       G_SIGNAL_RUN_LAST,
1977                       G_STRUCT_OFFSET (SeatClass, stopped),
1978                       NULL, NULL,
1979                       NULL,
1980                       G_TYPE_NONE, 0);
1981 }
1982 
1983 static gint
seat_real_logprefix(Logger * self,gchar * buf,gulong buflen)1984 seat_real_logprefix (Logger *self, gchar *buf, gulong buflen)
1985 {
1986     return g_snprintf (buf, buflen, "Seat %s: ", seat_get_name (SEAT (self)));
1987 }
1988 
1989 static void
seat_logger_iface_init(LoggerInterface * iface)1990 seat_logger_iface_init (LoggerInterface *iface)
1991 {
1992     iface->logprefix = &seat_real_logprefix;
1993 }
1994