~ci-train-bot/lightdm/lightdm-ubuntu-zesty-1679

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