~brian-murray/lightdm/bug-967229

« back to all changes in this revision

Viewing changes to src/display.c

  • Committer: robert.ancell at canonical
  • Date: 2011-02-12 00:48:57 UTC
  • Revision ID: robert.ancell@canonical.com-20110212004857-45gpv6k0m0uf0liv
Update changelog link

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; indent-tabs-mode: nil; tab-width: 4 -*-
2
 
 *
3
 
 * Copyright (C) 2010-2011 Robert Ancell.
 
1
/*
 
2
 * Copyright (C) 2010 Robert Ancell.
4
3
 * Author: Robert Ancell <robert.ancell@canonical.com>
5
 
 *
 
4
 * 
6
5
 * This program is free software: you can redistribute it and/or modify it under
7
6
 * the terms of the GNU General Public License as published by the Free Software
8
7
 * Foundation, either version 3 of the License, or (at your option) any later
11
10
 */
12
11
 
13
12
#include <config.h>
 
13
 
14
14
#include <stdlib.h>
15
15
#include <string.h>
 
16
#include <errno.h>
 
17
#include <pwd.h>
16
18
#include <gio/gdesktopappinfo.h>
17
19
 
18
20
#include "display.h"
19
 
#include "configuration.h"
 
21
#include "display-glue.h"
 
22
#include "pam-session.h"
 
23
#include "theme.h"
20
24
#include "ldm-marshal.h"
21
 
#include "greeter.h"
22
 
 
23
 
enum
24
 
{
25
 
    CREATE_SESSION,
26
 
    READY,
27
 
    SWITCH_TO_USER,
28
 
    SWITCH_TO_GUEST,
29
 
    GET_GUEST_USERNAME,
30
 
    DISPLAY_SERVER_READY,
 
25
#include "ck-connector.h"
 
26
 
 
27
/* Length of time in milliseconds to wait for a session to load */
 
28
#define USER_SESSION_TIMEOUT 5000
 
29
 
 
30
/* Length of time in milliseconds to wait for a greeter to quit */
 
31
#define GREETER_QUIT_TIMEOUT 1000
 
32
 
 
33
enum {
31
34
    START_GREETER,
 
35
    END_GREETER,
32
36
    START_SESSION,
33
 
    STOPPED,
 
37
    END_SESSION,
 
38
    EXITED,
 
39
    QUIT_GREETER,
34
40
    LAST_SIGNAL
35
41
};
36
42
static guint signals[LAST_SIGNAL] = { 0 };
37
43
 
 
44
typedef enum
 
45
{
 
46
    SESSION_NONE = 0,
 
47
    SESSION_GREETER_PRE_CONNECT,
 
48
    SESSION_GREETER,
 
49
    SESSION_GREETER_AUTHENTICATED,
 
50
    SESSION_USER
 
51
} SessionType;
 
52
 
38
53
struct DisplayPrivate
39
54
{
40
 
    /* Display server */
41
 
    DisplayServer *display_server;
42
 
 
43
 
    /* Greeter session */
44
 
    gchar *greeter_session;
45
 
 
46
 
    /* TRUE if the user list should be shown */
47
 
    gboolean greeter_hide_users;
48
 
 
49
 
    /* TRUE if a manual login option should be shown */
50
 
    gboolean greeter_show_manual_login;
51
 
 
52
 
    /* TRUE if a remote login option should be shown */
53
 
    gboolean greeter_show_remote_login;
54
 
 
55
 
    /* TRUE if the greeter is a lock screen */
56
 
    gboolean greeter_is_lock;
57
 
 
58
 
    /* Session requested to log into */
59
 
    SessionType user_session_type;
60
 
    gchar *user_session;
 
55
    gint index;
 
56
 
 
57
    /* X server */
 
58
    XServer *xserver;
 
59
  
 
60
    /* Number of times have logged in */
 
61
    gint login_count;
 
62
 
 
63
    /* Language to use in greeter/sessions */
 
64
    gchar *default_language;
 
65
 
 
66
    /* Layout to use in greeter/sessions */
 
67
    gchar *default_layout;
 
68
 
 
69
    /* User to run greeter as */
 
70
    gchar *greeter_user;
 
71
 
 
72
    /* Theme to use */
 
73
    gchar *greeter_theme;
61
74
 
62
75
    /* Program to run sessions through */
63
76
    gchar *session_wrapper;
64
77
 
65
 
    /* TRUE if in a user session */
66
 
    gboolean in_user_session;
67
 
 
68
 
    /* TRUE if have got an X server / started a greeter */
69
 
    gboolean is_ready;
70
 
 
71
 
    /* Session process */
72
 
    Session *session;
73
 
 
74
 
    /* Communication link to greeter */
75
 
    Greeter *greeter;
76
 
 
77
 
    /* User that should be automatically logged in */
78
 
    gchar *autologin_user;
79
 
    gboolean autologin_guest;
80
 
    gint autologin_timeout;
81
 
 
82
 
    /* TRUE if start greeter if fail to login */
83
 
    gboolean start_greeter_if_fail;
84
 
 
85
 
    /* Hint to select user in greeter */
86
 
    gchar *select_user_hint;
87
 
    gboolean select_guest_hint;
88
 
 
89
 
    /* TRUE if allowed to log into guest account */
90
 
    gboolean allow_guest;
91
 
 
92
 
    /* TRUE if greeter is to show the guest account */
93
 
    gboolean greeter_allow_guest;
94
 
 
95
 
    /* TRUE if stopping the display (waiting for dispaly server, greeter and session to stop) */
96
 
    gboolean stopping;
97
 
 
98
 
    /* TRUE if stopped */
99
 
    gboolean stopped;
 
78
    /* PAM service to authenticate against */
 
79
    gchar *pam_service;
 
80
 
 
81
    /* Greeter session process */
 
82
    Session *greeter_session;
 
83
    gboolean greeter_connected;
 
84
    guint greeter_quit_timeout;
 
85
    PAMSession *greeter_pam_session;
 
86
    CkConnector *greeter_ck_session;
 
87
 
 
88
    gboolean supports_transitions;
 
89
 
 
90
    /* User session process */
 
91
    Session *user_session;
 
92
    guint user_session_timer;
 
93
    PAMSession *user_pam_session;
 
94
    CkConnector *user_ck_session;
 
95
 
 
96
    /* Current D-Bus call context */
 
97
    DBusGMethodInvocation *dbus_context;
 
98
 
 
99
    /* Default login hint */
 
100
    gchar *default_user;
 
101
    gint timeout;
 
102
 
 
103
    /* Default session */
 
104
    gchar *default_session;
100
105
};
101
106
 
102
 
/* PAM services to use */
103
 
#define GREETER_SERVICE   "lightdm-greeter"
104
 
#define USER_SERVICE      "lightdm"
105
 
#define AUTOLOGIN_SERVICE "lightdm-autologin"
106
 
 
107
107
G_DEFINE_TYPE (Display, display, G_TYPE_OBJECT);
108
108
 
109
 
static void greeter_session_stopped_cb (Session *session, Display *display);
110
 
static void user_session_stopped_cb (Session *session, Display *display);
 
109
static void start_greeter (Display *display);
111
110
 
 
111
// FIXME: Remove the index, it is an external property
112
112
Display *
113
 
display_new (DisplayServer *display_server)
114
 
{
115
 
    Display *display = g_object_new (DISPLAY_TYPE, NULL);
116
 
 
117
 
    display->priv->display_server = g_object_ref (display_server);
118
 
 
119
 
    return display;
120
 
}
121
 
 
122
 
DisplayServer *
123
 
display_get_display_server (Display *display)
124
 
{
125
 
    g_return_val_if_fail (display != NULL, NULL);
126
 
    return display->priv->display_server;
127
 
}
128
 
 
129
 
const gchar *
130
 
display_get_username (Display *display)
131
 
{
132
 
    g_return_val_if_fail (display != NULL, NULL);
133
 
 
134
 
    if (!display->priv->session || !display->priv->in_user_session)
135
 
        return NULL;
136
 
 
137
 
    return session_get_username (display->priv->session);
138
 
}
139
 
 
140
 
Session *
141
 
display_get_session (Display *display)
142
 
{
143
 
    g_return_val_if_fail (display != NULL, NULL);
144
 
    return display->priv->session;
145
 
}
146
 
 
147
 
void
148
 
display_set_greeter_session (Display *display, const gchar *greeter_session)
149
 
{
150
 
    g_return_if_fail (display != NULL);
151
 
    g_free (display->priv->greeter_session);
152
 
    display->priv->greeter_session = g_strdup (greeter_session);
 
113
display_new (gint index)
 
114
{
 
115
    Display *self = g_object_new (DISPLAY_TYPE, NULL);
 
116
 
 
117
    self->priv->index = index;
 
118
    self->priv->pam_service = g_strdup (DEFAULT_PAM_SERVICE);
 
119
 
 
120
    return self;
 
121
}
 
122
 
 
123
gint
 
124
display_get_index (Display *display)
 
125
{
 
126
    return display->priv->index;
153
127
}
154
128
 
155
129
void
156
130
display_set_session_wrapper (Display *display, const gchar *session_wrapper)
157
131
{
158
 
    g_return_if_fail (display != NULL);
159
132
    g_free (display->priv->session_wrapper);
160
 
    display->priv->session_wrapper = g_strdup (session_wrapper);
161
 
}
162
 
 
163
 
void
164
 
display_set_allow_guest (Display *display, gboolean allow_guest)
165
 
{
166
 
    g_return_if_fail (display != NULL);
167
 
    display->priv->allow_guest = allow_guest;
168
 
}
169
 
 
170
 
void
171
 
display_set_greeter_allow_guest (Display *display, gboolean greeter_allow_guest)
172
 
{
173
 
    g_return_if_fail (display != NULL);
174
 
    display->priv->greeter_allow_guest = greeter_allow_guest;
175
 
}
176
 
 
177
 
void
178
 
display_set_autologin_user (Display *display, const gchar *username, gboolean is_guest, gint timeout)
179
 
{
180
 
    g_return_if_fail (display != NULL);
181
 
    g_free (display->priv->autologin_user);
182
 
    display->priv->autologin_user = g_strdup (username);
183
 
    display->priv->autologin_guest = is_guest;
184
 
    display->priv->autologin_timeout = timeout;
185
 
}
186
 
 
187
 
void
188
 
display_set_select_user_hint (Display *display, const gchar *username, gboolean is_guest)
189
 
{
190
 
    g_return_if_fail (display != NULL);
191
 
    g_free (display->priv->select_user_hint);
192
 
    display->priv->select_user_hint = g_strdup (username);
193
 
    display->priv->select_guest_hint = is_guest;
194
 
}
195
 
 
196
 
void
197
 
display_set_hide_users_hint (Display *display, gboolean hide_users)
198
 
{
199
 
    g_return_if_fail (display != NULL);
200
 
    display->priv->greeter_hide_users = hide_users;
201
 
}
202
 
 
203
 
void
204
 
display_set_show_manual_login_hint (Display *display, gboolean show_manual_login)
205
 
{
206
 
    g_return_if_fail (display != NULL);
207
 
    display->priv->greeter_show_manual_login = show_manual_login;
208
 
}
209
 
 
210
 
void
211
 
display_set_show_remote_login_hint (Display *display, gboolean show_remote_login)
212
 
{
213
 
    g_return_if_fail (display != NULL);
214
 
    display->priv->greeter_show_remote_login = show_remote_login;
215
 
}
216
 
 
217
 
void
218
 
display_set_lock_hint (Display *display, gboolean is_lock)
219
 
{
220
 
    g_return_if_fail (display != NULL);
221
 
    display->priv->greeter_is_lock = is_lock;
222
 
}
223
 
 
224
 
void
225
 
display_set_user_session (Display *display, SessionType type, const gchar *session_name)
226
 
{
227
 
    g_return_if_fail (display != NULL);
228
 
    g_free (display->priv->user_session);
229
 
    display->priv->user_session_type = type;
230
 
    display->priv->user_session = g_strdup (session_name);
 
133
    display->priv->session_wrapper = g_strdup (session_wrapper);  
 
134
}
 
135
 
 
136
const gchar *
 
137
display_get_session_wrapper (Display *display)
 
138
{
 
139
    return display->priv->session_wrapper;
 
140
}
 
141
 
 
142
void
 
143
display_set_default_user (Display *display, const gchar *username)
 
144
{
 
145
    g_free (display->priv->default_user);
 
146
    display->priv->default_user = g_strdup (username);
 
147
}
 
148
 
 
149
const gchar *
 
150
display_get_default_user (Display *display)
 
151
{
 
152
    return display->priv->default_user;
 
153
}
 
154
 
 
155
void
 
156
display_set_default_user_timeout (Display *display, gint timeout)
 
157
{
 
158
    display->priv->timeout = timeout;  
 
159
}
 
160
 
 
161
gint
 
162
display_get_default_user_timeout (Display *display)
 
163
{
 
164
    return display->priv->timeout;
 
165
}
 
166
 
 
167
void
 
168
display_set_greeter_user (Display *display, const gchar *username)
 
169
{
 
170
    g_free (display->priv->greeter_user);
 
171
    if (username && username[0] != '\0')
 
172
        display->priv->greeter_user = g_strdup (username);
 
173
    else
 
174
        display->priv->greeter_user = NULL;
 
175
}
 
176
 
 
177
const gchar *
 
178
display_get_greeter_user (Display *display)
 
179
{
 
180
    return display->priv->greeter_user;  
 
181
}
 
182
 
 
183
const gchar *
 
184
display_get_session_user (Display *display)
 
185
{
 
186
    if (display->priv->user_session)
 
187
        return pam_session_get_username (display->priv->user_pam_session);
 
188
    else
 
189
        return NULL;
 
190
}
 
191
 
 
192
void
 
193
display_set_greeter_theme (Display *display, const gchar *greeter_theme)
 
194
{
 
195
    g_free (display->priv->greeter_theme);
 
196
    display->priv->greeter_theme = g_strdup (greeter_theme);
 
197
}
 
198
 
 
199
const gchar *
 
200
display_get_greeter_theme (Display *display)
 
201
{
 
202
    return display->priv->greeter_theme;
 
203
}
 
204
 
 
205
void
 
206
display_set_default_language (Display *display, const gchar *language)
 
207
{
 
208
    g_free (display->priv->default_language);
 
209
    display->priv->default_language = g_strdup (language);
 
210
}
 
211
 
 
212
const gchar *
 
213
display_get_default_language (Display *display)
 
214
{
 
215
    return display->priv->default_language;
 
216
}
 
217
 
 
218
void
 
219
display_set_default_layout (Display *display, const gchar *layout)
 
220
{
 
221
    g_free (display->priv->default_layout);
 
222
    display->priv->default_layout = g_strdup (layout);
 
223
}
 
224
 
 
225
const gchar *
 
226
display_get_default_layout (Display *display)
 
227
{
 
228
    return display->priv->default_layout;
 
229
}
 
230
 
 
231
void
 
232
display_set_default_session (Display *display, const gchar *session)
 
233
{
 
234
    g_free (display->priv->default_session);
 
235
    display->priv->default_session = g_strdup (session);
 
236
}
 
237
 
 
238
const gchar *
 
239
display_get_default_session (Display *display)
 
240
{
 
241
    return display->priv->default_session;
 
242
}
 
243
 
 
244
void
 
245
display_set_pam_service (Display *display, const gchar *service)
 
246
{
 
247
    g_free (display->priv->pam_service);
 
248
    display->priv->pam_service = g_strdup (service);
 
249
}
 
250
 
 
251
const gchar *
 
252
display_get_pam_service (Display *display)
 
253
{
 
254
    return display->priv->pam_service;
 
255
}
 
256
 
 
257
void
 
258
display_set_xserver (Display *display, XServer *xserver)
 
259
{
 
260
    if (display->priv->xserver)
 
261
        g_object_unref (display->priv->xserver);
 
262
    display->priv->xserver = g_object_ref (xserver);  
 
263
}
 
264
 
 
265
XServer *
 
266
display_get_xserver (Display *display)
 
267
{
 
268
    return display->priv->xserver;
 
269
}
 
270
 
 
271
static struct passwd *
 
272
get_user_info (const gchar *username)
 
273
{
 
274
    struct passwd *user_info;
 
275
 
 
276
    errno = 0;
 
277
    user_info = getpwnam (username);
 
278
    if (!user_info)
 
279
    {
 
280
        if (errno == 0)
 
281
            g_warning ("Unable to get information on user %s: User does not exist", username);
 
282
        else
 
283
            g_warning ("Unable to get information on user %s: %s", username, strerror (errno));
 
284
    }
 
285
 
 
286
    return user_info;
 
287
}
 
288
 
 
289
static CkConnector *
 
290
start_ck_session (Display *display, const gchar *session_type, const gchar *username)
 
291
{
 
292
    CkConnector *session;
 
293
    DBusError error;
 
294
    char *display_device = NULL;
 
295
    const gchar *address, *hostname = "";
 
296
    struct passwd *user_info;
 
297
    gboolean is_local = TRUE;
 
298
    gboolean result;
 
299
 
 
300
    session = ck_connector_new ();
 
301
 
 
302
    user_info = get_user_info (username);
 
303
    if (!user_info)
 
304
        return session;
 
305
 
 
306
    if (xserver_get_vt (display->priv->xserver) >= 0)
 
307
        display_device = g_strdup_printf ("/dev/tty%d", xserver_get_vt (display->priv->xserver));
 
308
 
 
309
    dbus_error_init (&error);
 
310
    address = xserver_get_address (display->priv->xserver);
 
311
    result = ck_connector_open_session_with_parameters (session, &error,
 
312
                                                        "unix-user", &user_info->pw_uid,
 
313
                                                        "session-type", &session_type,
 
314
                                                        "x11-display", &address,
 
315
                                                        "x11-display-device", display_device ? &display_device : NULL,
 
316
                                                        "remote-host-name", &hostname,
 
317
                                                        "is-local", &is_local,
 
318
                                                        NULL);
 
319
    g_free (display_device);
 
320
 
 
321
    if (!result)
 
322
    {
 
323
        g_warning ("Failed to open CK session: %s: %s", error.name, error.message);
 
324
        ck_connector_unref (session);
 
325
        return NULL;
 
326
    }
 
327
 
 
328
    return session;
231
329
}
232
330
 
233
331
static void
234
 
display_set_is_ready (Display *display)
235
 
{
236
 
    if (display->priv->is_ready)
237
 
        return;
238
 
 
239
 
    display->priv->is_ready = TRUE;
240
 
    g_signal_emit (display, signals[READY], 0);
241
 
}
242
 
 
243
 
static gboolean
244
 
switch_to_user (Display *display, User *user)
245
 
{
246
 
    gboolean result;
247
 
    g_signal_emit (display, signals[SWITCH_TO_USER], 0, user, &result);
248
 
    return result;
249
 
}
250
 
 
251
 
static gboolean
252
 
switch_to_guest (Display *display)
253
 
{
254
 
    gboolean result;
255
 
    g_signal_emit (display, signals[SWITCH_TO_GUEST], 0, &result);
256
 
    return result;
257
 
}
258
 
 
259
 
static gchar *
260
 
get_guest_username (Display *display)
261
 
{
262
 
    gchar *username;
263
 
    g_signal_emit (display, signals[GET_GUEST_USERNAME], 0, &username);
264
 
    return username;
265
 
}
266
 
 
267
 
static Session *
268
 
create_session (Display *display)
269
 
{
270
 
    Session *session;
271
 
 
272
 
    g_signal_emit (display, signals[CREATE_SESSION], 0, &session);
 
332
end_ck_session (CkConnector *session)
 
333
{
273
334
    if (!session)
274
 
        return NULL;
275
 
 
276
 
    /* Connect using the session bus */
277
 
    if (getuid () != 0)
278
 
    {
279
 
        if (g_getenv ("DBUS_SESSION_BUS_ADDRESS"))
280
 
            session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
281
 
        session_set_env (session, "LDM_BUS", "SESSION");
282
 
        if (g_getenv ("LD_PRELOAD"))
283
 
            session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
284
 
        if (g_getenv ("LD_LIBRARY_PATH"))
285
 
            session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
286
 
        if (g_getenv ("PATH"))
287
 
            session_set_env (session, "PATH", g_getenv ("PATH"));
288
 
    }
289
 
 
290
 
    /* Variables required for regression tests */
291
 
    if (g_getenv ("LIGHTDM_TEST_ROOT"))
292
 
    {
293
 
        session_set_env (session, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
294
 
        session_set_env (session, "DBUS_SYSTEM_BUS_ADDRESS", g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
295
 
        session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
296
 
        session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
297
 
        session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
298
 
        session_set_env (session, "GI_TYPELIB_PATH", g_getenv ("GI_TYPELIB_PATH"));
299
 
    }
300
 
 
301
 
    return session;
302
 
}
303
 
 
304
 
static void
305
 
destroy_session (Display *display)
306
 
{
307
 
    if (!display->priv->session)
308
 
        return;
309
 
 
310
 
    g_signal_handlers_disconnect_matched (display->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
311
 
    session_stop (display->priv->session);
312
 
    g_object_unref (display->priv->session);
313
 
    display->priv->session = NULL;
314
 
}
315
 
 
316
 
static void
317
 
greeter_authentication_complete_cb (Session *session, Display *display)
318
 
{
319
 
    gboolean result = FALSE;
320
 
 
321
 
    if (display->priv->stopping)
322
 
        return;
323
 
 
324
 
    if (session_get_is_authenticated (session))
325
 
    {
326
 
        g_debug ("Greeter authorized");
327
 
        g_signal_emit (display, signals[START_GREETER], 0, &result);
328
 
        result = !result;
329
 
    }
330
 
    else
331
 
        g_debug ("Greeter failed authentication");
332
 
 
333
 
    if (!result)
334
 
    {
335
 
        g_debug ("Greeter failed to start");
336
 
        display_stop (display);
337
 
    }
338
 
}
339
 
 
340
 
static void
341
 
greeter_connected_cb (Greeter *greeter, Display *display)
342
 
{
343
 
    // FIXME: Should wait for greeter to signal completely ready if it supports it
344
 
    g_debug ("Greeter connected, display is ready");
345
 
    display_set_is_ready (display);
346
 
}
347
 
 
348
 
static Session *
349
 
greeter_start_authentication_cb (Greeter *greeter, const gchar *username, Display *display)
350
 
{
351
 
    return create_session (display);
352
 
}
353
 
 
354
 
static gboolean
355
 
greeter_start_session_cb (Greeter *greeter, SessionType type, const gchar *session_name, Display *display)
356
 
{
357
 
    /* If no session requested, use the previous one */
358
 
    if (!session_name && !greeter_get_guest_authenticated (greeter))
359
 
    {
360
 
        User *user;
361
 
 
362
 
        user = session_get_user (greeter_get_authentication_session (greeter));
363
 
        type = SESSION_TYPE_LOCAL;
364
 
        session_name = user_get_xsession (user);
365
 
    }
366
 
 
367
 
    /* If a session was requested, override the default */
368
 
    if (session_name)
369
 
    {
370
 
        g_debug ("Using session %s", session_name);
371
 
        display_set_user_session (display, type, session_name);
372
 
    }
373
 
 
374
 
    /* Stop this display if that session already exists and can switch to it */
375
 
    if (greeter_get_guest_authenticated (greeter))
376
 
    {
377
 
        if (switch_to_guest (display))
378
 
            return TRUE;
379
 
 
380
 
        /* Set to login as guest */
381
 
        display_set_autologin_user (display, NULL, TRUE, 0);
382
 
    }
383
 
    else
384
 
    {
385
 
        if (switch_to_user (display, session_get_user (greeter_get_authentication_session (display->priv->greeter))))
386
 
            return TRUE;
387
 
    }
388
 
 
389
 
    /* Stop the greeter, the session will start when the greeter has quit */
390
 
    g_debug ("Stopping greeter");
391
 
    session_stop (display->priv->session);
392
 
 
393
 
    return TRUE;
394
 
}
395
 
 
396
 
static gboolean
397
 
start_greeter (Display *display)
398
 
{
399
 
    gchar *greeter_user;
400
 
    gboolean result;
401
 
 
402
 
    destroy_session (display);
403
 
    display->priv->session = create_session (display);
404
 
    session_set_class (display->priv->session, XDG_SESSION_CLASS_GREETER);
405
 
    g_signal_connect (display->priv->session, "authentication-complete", G_CALLBACK (greeter_authentication_complete_cb), display);
406
 
 
407
 
    /* Make communication link to greeter that will run on this session */
408
 
    display->priv->greeter = greeter_new (display->priv->session, USER_SERVICE, AUTOLOGIN_SERVICE);
409
 
    g_signal_connect (G_OBJECT (display->priv->greeter), "connected", G_CALLBACK (greeter_connected_cb), display);
410
 
    g_signal_connect (G_OBJECT (display->priv->greeter), "start-authentication", G_CALLBACK (greeter_start_authentication_cb), display);
411
 
    g_signal_connect (G_OBJECT (display->priv->greeter), "start-session", G_CALLBACK (greeter_start_session_cb), display);
412
 
    if (display->priv->autologin_timeout)
413
 
    {
414
 
        gchar *value = g_strdup_printf ("%d", display->priv->autologin_timeout);
415
 
        greeter_set_hint (display->priv->greeter, "autologin-timeout", value);
416
 
        g_free (value);
417
 
        if (display->priv->autologin_user)
418
 
            greeter_set_hint (display->priv->greeter, "autologin-user", display->priv->autologin_user);
419
 
        else if (display->priv->autologin_guest)
420
 
            greeter_set_hint (display->priv->greeter, "autologin-guest", "true");
421
 
    }
422
 
    if (display->priv->select_user_hint)
423
 
        greeter_set_hint (display->priv->greeter, "select-user", display->priv->select_user_hint);
424
 
    else if (display->priv->select_guest_hint)
425
 
        greeter_set_hint (display->priv->greeter, "select-guest", "true");
426
 
    greeter_set_hint (display->priv->greeter, "default-session", display->priv->user_session);
427
 
    greeter_set_allow_guest (display->priv->greeter, display->priv->allow_guest);
428
 
    greeter_set_hint (display->priv->greeter, "has-guest-account", (display->priv->allow_guest && display->priv->greeter_allow_guest) ? "true" : "false");
429
 
    greeter_set_hint (display->priv->greeter, "hide-users", display->priv->greeter_hide_users ? "true" : "false");
430
 
    greeter_set_hint (display->priv->greeter, "show-manual-login", display->priv->greeter_show_manual_login ? "true" : "false");
431
 
    greeter_set_hint (display->priv->greeter, "show-remote-login", display->priv->greeter_show_remote_login ? "true" : "false");
432
 
    if (display->priv->greeter_is_lock)
433
 
        greeter_set_hint (display->priv->greeter, "lock-screen", "true");
434
 
 
435
 
    /* Run greeter as unprivileged user */
436
 
    if (getuid () != 0)
437
 
    {
438
 
        User *user;
439
 
        user = accounts_get_current_user ();
440
 
        greeter_user = g_strdup (user_get_name (user));
441
 
        g_object_unref (user);
442
 
    }
443
 
    else
444
 
    {
445
 
        greeter_user = config_get_string (config_get_instance (), "LightDM", "greeter-user");
446
 
        if (!greeter_user)
447
 
        {
448
 
            g_warning ("Greeter must not be run as root");
449
 
            display_stop (display);
450
 
            return FALSE;
451
 
        }
452
 
    }
453
 
 
454
 
    g_signal_connect_after (display->priv->session, "stopped", G_CALLBACK (greeter_session_stopped_cb), display);
455
 
    result = greeter_start (display->priv->greeter, GREETER_SERVICE, greeter_user);
456
 
    g_free (greeter_user);
457
 
 
458
 
    if (!result)
459
 
        display_stop (display);
460
 
 
461
 
    return result;
462
 
}
463
 
 
464
 
static void
465
 
autologin_authentication_complete_cb (Session *session, Display *display)
466
 
{
467
 
    gboolean result = FALSE;
468
 
 
469
 
    if (display->priv->stopping)
470
 
        return;
471
 
 
472
 
    if (session_get_is_authenticated (session))
473
 
    {
474
 
        const gchar *session_name;
475
 
 
476
 
        g_debug ("Autologin user %s authorized", session_get_username (session));
477
 
 
478
 
        session_name = user_get_xsession (session_get_user (session));
479
 
        if (session_name)
480
 
        {
481
 
            g_debug ("Autologin using session %s", session_name);
482
 
            display_set_user_session (display, SESSION_TYPE_LOCAL, session_name);
483
 
        }
484
 
 
485
 
        g_signal_emit (display, signals[START_SESSION], 0, &result);
486
 
        result = !result;
487
 
    }
488
 
    else
489
 
        g_debug ("Autologin failed authentication");
490
 
 
491
 
    if (!result)
492
 
    {
493
 
        if (display->priv->start_greeter_if_fail)
494
 
            start_greeter (display);
495
 
        else
496
 
            display_stop (display);
497
 
    }
498
 
}
499
 
 
500
 
static gboolean
501
 
autologin (Display *display, const gchar *username, const gchar *service, gboolean start_greeter_if_fail, gboolean is_guest)
502
 
{
503
 
    display->priv->start_greeter_if_fail = start_greeter_if_fail;
504
 
 
505
 
    display->priv->in_user_session = TRUE;
506
 
    destroy_session (display);
507
 
    display->priv->session = create_session (display);
508
 
    g_signal_connect (display->priv->session, "authentication-complete", G_CALLBACK (autologin_authentication_complete_cb), display);
509
 
    g_signal_connect_after (display->priv->session, "stopped", G_CALLBACK (user_session_stopped_cb), display);
510
 
    return session_start (display->priv->session, service, username, TRUE, FALSE, is_guest);
511
 
}
512
 
 
513
 
static gboolean
514
 
autologin_guest (Display *display, const gchar *service, gboolean start_greeter_if_fail)
515
 
{
516
 
    gchar *username;
517
 
    gboolean result;
518
 
 
519
 
    username = get_guest_username (display);
520
 
    if (!username)
521
 
    {
522
 
        g_debug ("Can't autologin guest, no guest account");
523
 
        return FALSE;
524
 
    }
525
 
 
526
 
    result = autologin (display, username, service, start_greeter_if_fail, TRUE);
527
 
    g_free (username);
528
 
 
529
 
    return result;
530
 
}
531
 
 
532
 
static gchar **
533
 
get_session_command (const gchar *filename, const gchar *session_wrapper)
534
 
{
535
 
    GKeyFile *session_desktop_file;
536
 
    gboolean result;
537
 
    int argc;
538
 
    gchar *command = NULL, **argv, *path;
 
335
        return;
 
336
    ck_connector_close_session (session, NULL); // FIXME: Handle errors
 
337
    ck_connector_unref (session);
 
338
}
 
339
 
 
340
static void
 
341
run_script (const gchar *script)
 
342
{
 
343
    // FIXME
 
344
}
 
345
 
 
346
static void
 
347
end_user_session (Display *display, gboolean clean_exit)
 
348
{
 
349
    run_script ("PostSession");
 
350
 
 
351
    g_signal_emit (display, signals[END_SESSION], 0, display->priv->user_session);
 
352
  
 
353
    if (display->priv->user_session_timer)
 
354
    {
 
355
        g_source_remove (display->priv->user_session_timer);
 
356
        display->priv->user_session_timer = 0;
 
357
    }
 
358
 
 
359
    g_object_unref (display->priv->user_session);
 
360
    display->priv->user_session = NULL;
 
361
 
 
362
    pam_session_end (display->priv->user_pam_session);
 
363
    g_object_unref (display->priv->user_pam_session);
 
364
    display->priv->user_pam_session = NULL;
 
365
 
 
366
    end_ck_session (display->priv->user_ck_session);
 
367
    display->priv->user_ck_session = NULL;
 
368
 
 
369
    if (!clean_exit)
 
370
        g_warning ("Session exited unexpectedly");
 
371
 
 
372
    xserver_disconnect_clients (display->priv->xserver);
 
373
}
 
374
 
 
375
static void
 
376
user_session_exited_cb (Session *session, gint status, Display *display)
 
377
{
 
378
    end_user_session (display, status == 0);
 
379
}
 
380
 
 
381
static void
 
382
user_session_killed_cb (Session *session, gint status, Display *display)
 
383
{
 
384
    end_user_session (display, FALSE);
 
385
}
 
386
 
 
387
static void set_env_from_pam_session (Session *session, PAMSession *pam_session)
 
388
{
 
389
    gchar **pam_env;
 
390
 
 
391
    pam_env = pam_session_get_envlist (pam_session);
 
392
    if (pam_env)
 
393
    {
 
394
        int i;
 
395
        for (i = 0; pam_env[i]; i++)
 
396
        {
 
397
            g_debug ("pam_env[%d]=%s", i, pam_env[i]);
 
398
            gchar **pam_env_vars = g_strsplit (pam_env[i], "=", 2);
 
399
            if (pam_env_vars && pam_env_vars[0] && pam_env_vars[1])
 
400
                session_set_env (session, pam_env_vars[0], pam_env_vars[1]);
 
401
            else
 
402
                g_warning ("Can't parse PAM environment variable %s", pam_env[i]);
 
403
            g_strfreev (pam_env_vars);
 
404
        }
 
405
        g_strfreev (pam_env);
 
406
    }
 
407
}
 
408
 
 
409
static void
 
410
start_user_session (Display *display, const gchar *session, const gchar *language)
 
411
{
 
412
    gchar *filename, *path;
 
413
    struct passwd *user_info;
 
414
    GKeyFile *dmrc_file, *session_desktop_file;
 
415
    gboolean have_dmrc = FALSE, result;
539
416
    GError *error = NULL;
540
417
 
541
 
    /* Read the command from the .desktop file */
 
418
    run_script ("PreSession");
 
419
 
 
420
    g_debug ("Launching '%s' session for user %s", session, pam_session_get_username (display->priv->user_pam_session));
 
421
    display->priv->login_count++;
 
422
 
 
423
    /* Load the users login settings (~/.dmrc) */
 
424
    dmrc_file = g_key_file_new ();
 
425
    user_info = get_user_info (pam_session_get_username (display->priv->user_pam_session));
 
426
    if (user_info)
 
427
    {
 
428
        /* Load from the user directory, if this fails (e.g. the user directory
 
429
         * is not yet mounted) then load from the cache */
 
430
        path = g_build_filename (user_info->pw_dir, ".dmrc", NULL);
 
431
        have_dmrc = g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, NULL);
 
432
        g_free (path);
 
433
    }
 
434
 
 
435
    /* If no .dmrc, then load from the cache */
 
436
    if (!have_dmrc)
 
437
    {
 
438
        filename = g_strdup_printf ("%s.dmrc", user_info->pw_name);
 
439
        path = g_build_filename (CACHE_DIR, "dmrc", filename, NULL);
 
440
        g_free (filename);
 
441
        if (!g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, &error))
 
442
            g_warning ("Failed to load .dmrc file %s: %s", path, error->message);
 
443
        g_clear_error (&error);
 
444
        g_free (path);
 
445
    }
 
446
  
 
447
    /* Update the .dmrc with changed settings */
 
448
    g_key_file_set_string (dmrc_file, "Desktop", "Session", session);
 
449
    if (language)
 
450
        g_key_file_set_string (dmrc_file, "Desktop", "Language", language);
 
451
    else if (!g_key_file_has_key (dmrc_file, "Desktop", "Language", NULL))
 
452
        g_key_file_set_string (dmrc_file, "Desktop", "Language", display->priv->default_language);
 
453
    if (!g_key_file_has_key (dmrc_file, "Desktop", "Layout", NULL))
 
454
        g_key_file_set_string (dmrc_file, "Desktop", "Layout", display->priv->default_layout);
 
455
 
 
456
    filename = g_strdup_printf ("%s.desktop", session);
 
457
    path = g_build_filename (XSESSIONS_DIR, filename, NULL);
 
458
    g_free (filename);
 
459
 
542
460
    session_desktop_file = g_key_file_new ();
543
 
    result = g_key_file_load_from_file (session_desktop_file, filename, G_KEY_FILE_NONE, &error);
544
 
    if (error)
545
 
        g_debug ("Failed to load session file %s: %s", filename, error->message);
 
461
    result = g_key_file_load_from_file (session_desktop_file, path, G_KEY_FILE_NONE, &error);
 
462
    g_free (path);
 
463
 
 
464
    if (!result)
 
465
        g_warning ("Failed to load session file %s: %s:", path, error->message);
546
466
    g_clear_error (&error);
 
467
 
547
468
    if (result)
548
469
    {
549
 
        command = g_key_file_get_string (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL);
550
 
        if (!command)
551
 
            g_debug ("No command in session file %s", filename);
 
470
        gchar *session_command;
 
471
 
 
472
        session_command = g_key_file_get_string (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL);
 
473
        if (!session_command)
 
474
            g_warning ("No command in session file %s", path);
 
475
 
 
476
        display->priv->supports_transitions = g_key_file_get_boolean (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, "X-LightDM-Supports-Transitions", NULL);
 
477
 
 
478
        if (session_command)
 
479
        {
 
480
            gchar *session_language, *layout;
 
481
            gchar *data;
 
482
            gsize length;
 
483
 
 
484
            if (display->priv->session_wrapper)
 
485
            {
 
486
                gchar *old_command = session_command;
 
487
                session_command = g_strdup_printf ("%s '%s'", display->priv->session_wrapper, session_command);
 
488
                g_free (old_command);
 
489
            }
 
490
            display->priv->user_session = session_new (pam_session_get_username (display->priv->user_pam_session), session_command);
 
491
 
 
492
            session_language = g_key_file_get_string (dmrc_file, "Desktop", "Language", NULL);
 
493
 
 
494
            layout = g_key_file_get_string (dmrc_file, "Desktop", "Layout", NULL);
 
495
 
 
496
            g_signal_connect (G_OBJECT (display->priv->user_session), "exited", G_CALLBACK (user_session_exited_cb), display);
 
497
            g_signal_connect (G_OBJECT (display->priv->user_session), "killed", G_CALLBACK (user_session_killed_cb), display);
 
498
            session_set_env (display->priv->user_session, "DISPLAY", xserver_get_address (display->priv->xserver));
 
499
            if (display->priv->user_ck_session)
 
500
                session_set_env (display->priv->user_session, "XDG_SESSION_COOKIE", ck_connector_get_cookie (display->priv->user_ck_session));
 
501
            session_set_env (display->priv->user_session, "DESKTOP_SESSION", session); // FIXME: Apparently deprecated?
 
502
            session_set_env (display->priv->user_session, "GDMSESSION", session); // FIXME: Not cross-desktop
 
503
            session_set_env (display->priv->user_session, "PATH", "/usr/local/bin:/usr/bin:/bin");                
 
504
            session_set_env (display->priv->user_session, "LANG", session_language);
 
505
            session_set_env (display->priv->user_session, "GDM_LANG", session_language); // FIXME: Not cross-desktop
 
506
            session_set_env (display->priv->user_session, "GDM_KEYBOARD_LAYOUT", layout); // FIXME: Not cross-desktop
 
507
            set_env_from_pam_session (display->priv->user_session, display->priv->user_pam_session);
 
508
 
 
509
            g_signal_emit (display, signals[START_SESSION], 0, display->priv->user_session);
 
510
 
 
511
            session_start (display->priv->user_session);
 
512
 
 
513
            data = g_key_file_to_data (dmrc_file, &length, NULL);
 
514
 
 
515
            /* Update the users .dmrc */
 
516
            if (user_info)
 
517
            {
 
518
                path = g_build_filename (user_info->pw_dir, ".dmrc", NULL);
 
519
                g_file_set_contents (path, data, length, NULL);
 
520
                chown (path, user_info->pw_uid, user_info->pw_gid);
 
521
                g_free (path);
 
522
            }
 
523
 
 
524
            /* Update the .dmrc cache */
 
525
            path = g_build_filename (CACHE_DIR, "dmrc", NULL);          
 
526
            g_mkdir_with_parents (path, 0700);
 
527
            g_free (path);
 
528
            filename = g_strdup_printf ("%s.dmrc", pam_session_get_username (display->priv->user_pam_session));
 
529
            path = g_build_filename (CACHE_DIR, "dmrc", filename, NULL);
 
530
            g_file_set_contents (path, data, length, NULL);
 
531
            g_free (path);
 
532
 
 
533
            g_free (data);
 
534
            g_free (session_language); 
 
535
            g_free (layout);         
 
536
        }
 
537
 
 
538
        g_free (session_command);
552
539
    }
 
540
 
553
541
    g_key_file_free (session_desktop_file);
554
 
 
555
 
    if (!command)
556
 
        return NULL;
557
 
 
558
 
    /* If configured, run sessions through a wrapper */
559
 
    if (session_wrapper)
 
542
    g_key_file_free (dmrc_file);  
 
543
}
 
544
 
 
545
static void
 
546
start_default_session (Display *display, const gchar *session, const gchar *language)
 
547
{
 
548
    /* Don't need to check authentication, just authorize */
 
549
    if (display->priv->user_pam_session)
 
550
        pam_session_end (display->priv->user_pam_session);    
 
551
    display->priv->user_pam_session = pam_session_new (display->priv->pam_service, display->priv->default_user);
 
552
    pam_session_authorize (display->priv->user_pam_session);
 
553
 
 
554
    display->priv->user_ck_session = start_ck_session (display, "", pam_session_get_username (display->priv->user_pam_session));
 
555
    start_user_session (display, session, language);
 
556
}
 
557
 
 
558
static void
 
559
end_greeter_session (Display *display, gboolean clean_exit)
 
560
{  
 
561
    gboolean greeter_connected;
 
562
  
 
563
    if (display->priv->greeter_quit_timeout)
560
564
    {
561
 
        argv = g_malloc (sizeof (gchar *) * 3);
562
 
        path = g_find_program_in_path (session_wrapper);
563
 
        argv[0] = path ? path : g_strdup (session_wrapper);
564
 
        argv[1] = command;
565
 
        argv[2] = NULL;
566
 
        return argv;
 
565
        g_source_remove (display->priv->greeter_quit_timeout);
 
566
        display->priv->greeter_quit_timeout = 0;
567
567
    }
568
568
 
569
 
    /* Split command into an array listing and make command absolute */
570
 
    result = g_shell_parse_argv (command, &argc, &argv, &error);
571
 
    if (error)
572
 
        g_debug ("Invalid session command '%s': %s", command, error->message);
 
569
    g_signal_emit (display, signals[END_GREETER], 0, display->priv->greeter_session);
 
570
 
 
571
    greeter_connected = display->priv->greeter_connected;
 
572
 
 
573
    g_object_unref (display->priv->greeter_session);
 
574
    display->priv->greeter_session = NULL;
 
575
    display->priv->greeter_connected = FALSE;
 
576
 
 
577
    pam_session_end (display->priv->greeter_pam_session);
 
578
    g_object_unref (display->priv->greeter_pam_session);
 
579
    display->priv->greeter_pam_session = NULL;
 
580
 
 
581
    end_ck_session (display->priv->greeter_ck_session);
 
582
    display->priv->greeter_ck_session = NULL;
 
583
 
 
584
    if (!clean_exit)
 
585
        g_warning ("Greeter failed");
 
586
    else if (!greeter_connected)
 
587
        g_warning ("Greeter quit before connecting");
 
588
    else if (!display->priv->user_session)
 
589
        g_warning ("Greeter quit before session started");
 
590
    else
 
591
        return;
 
592
 
 
593
    // FIXME: Issue with greeter, don't want to start a new one, report error to user
 
594
}
 
595
 
 
596
static void
 
597
greeter_session_exited_cb (Session *session, gint status, Display *display)
 
598
{
 
599
    end_greeter_session (display, status == 0);
 
600
}
 
601
 
 
602
static void
 
603
greeter_session_killed_cb (Session *session, gint status, Display *display)
 
604
{
 
605
    end_greeter_session (display, FALSE);
 
606
}
 
607
 
 
608
static void
 
609
start_greeter (Display *display)
 
610
{
 
611
    GKeyFile *theme;
 
612
    GError *error = NULL;
 
613
  
 
614
    theme = load_theme (display->priv->greeter_theme, &error);
 
615
    if (!theme)
 
616
        g_warning ("Failed to find theme %s: %s", display->priv->greeter_theme, error->message);
573
617
    g_clear_error (&error);
574
 
    g_free (command);
575
 
    if (!result)
576
 
        return NULL;
577
 
    path = g_find_program_in_path (argv[0]);
578
 
    if (path)
579
 
    {
580
 
        g_free (argv[0]);
581
 
        argv[0] = path;
582
 
    }
583
 
  
584
 
    return argv;
585
 
}
586
 
 
587
 
static void
588
 
greeter_session_stopped_cb (Session *session, Display *display)
589
 
{
590
 
    gboolean result = FALSE;
591
 
 
592
 
    g_debug ("Greeter quit");
593
 
 
594
 
    g_signal_handlers_disconnect_matched (display->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
595
 
    g_object_unref (display->priv->session);
596
 
    display->priv->session = NULL;
597
 
 
598
 
    if (display->priv->stopping)
599
 
    {
600
 
        display_stop (display);
601
 
        return;
602
 
    }
603
 
 
604
 
    if (!display->priv->display_server)
605
 
        return;
606
 
 
607
 
    /* Start the session for the authenticated user */
608
 
    if (greeter_get_start_session (display->priv->greeter))
609
 
    {
610
 
        /* If guest, then start a new autologin guest session (so can setup account) */
611
 
        if (greeter_get_guest_authenticated (display->priv->greeter))
612
 
            result = autologin_guest (display, AUTOLOGIN_SERVICE, FALSE);
613
 
        /* Otherwise, use the session the greeter has authenticated */
 
618
 
 
619
    if (theme)
 
620
    {
 
621
        gchar *command;
 
622
        gchar *username = NULL;
 
623
 
 
624
        g_debug ("Starting greeter %s as user %s", display->priv->greeter_theme,
 
625
                 display->priv->greeter_user ? display->priv->greeter_user : "<current>");
 
626
 
 
627
        command = theme_get_command (theme);
 
628
      
 
629
        if (display->priv->greeter_user)
 
630
            username = display->priv->greeter_user;
614
631
        else
615
632
        {
616
 
            destroy_session (display);
617
 
            display->priv->session = g_object_ref (greeter_get_authentication_session (display->priv->greeter));
618
 
            g_signal_connect_after (display->priv->session, "stopped", G_CALLBACK (user_session_stopped_cb), display);
619
 
            display->priv->in_user_session = TRUE;
620
 
            g_signal_emit (display, signals[START_SESSION], 0, &result);
621
 
            result = !result;
622
 
        }
623
 
    }
624
 
 
625
 
    /* Destroy the greeter */
626
 
    g_signal_handlers_disconnect_matched (display->priv->greeter, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
627
 
    g_object_unref (display->priv->greeter);
628
 
    display->priv->greeter = NULL;
629
 
 
630
 
    if (!result)
631
 
    {
632
 
        g_debug ("Failed to start greeter");
633
 
        display_stop (display);
634
 
    }
635
 
}
636
 
 
637
 
static gboolean
638
 
display_start_greeter (Display *display)
639
 
{
640
 
    gchar *log_dir, *filename, *log_filename, *sessions_dir, *path;
641
 
    gchar **argv;
642
 
 
643
 
    /* Log the output of the greeter to a system location */
644
 
    log_dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
645
 
    filename = g_strdup_printf ("%s-greeter.log", display_server_get_name (display->priv->display_server));
646
 
    log_filename = g_build_filename (log_dir, filename, NULL);
647
 
    g_free (log_dir);
648
 
    g_free (filename);
649
 
    g_debug ("Logging to %s", log_filename);
650
 
    session_set_log_file (display->priv->session, log_filename);
651
 
    g_free (log_filename);
652
 
 
653
 
    /* Load the greeter session information */
654
 
    sessions_dir = config_get_string (config_get_instance (), "LightDM", "xgreeters-directory");
655
 
    filename = g_strdup_printf ("%s.desktop", display->priv->greeter_session);
656
 
    path = g_build_filename (sessions_dir, filename, NULL);
657
 
    g_free (sessions_dir);
658
 
    g_free (filename);
659
 
    argv = get_session_command (path, NULL);
660
 
    g_free (path);
661
 
    if (!argv)
662
 
        return TRUE;
663
 
 
664
 
    session_run (display->priv->session, argv);
665
 
 
 
633
            struct passwd *user_info;
 
634
            user_info = getpwuid (getuid ());
 
635
            if (!user_info)
 
636
            {
 
637
                g_warning ("Unable to determine current username: %s", strerror (errno));
 
638
                return;
 
639
            }
 
640
            username = user_info->pw_name;
 
641
        }
 
642
 
 
643
        display->priv->greeter_pam_session = pam_session_new (display->priv->pam_service, username);
 
644
        pam_session_authorize (display->priv->greeter_pam_session);
 
645
 
 
646
        display->priv->greeter_ck_session = start_ck_session (display,
 
647
                                                              "LoginWindow",
 
648
                                                              username);
 
649
 
 
650
        display->priv->greeter_connected = FALSE;
 
651
        display->priv->greeter_session = session_new (username, command);
 
652
        g_signal_connect (G_OBJECT (display->priv->greeter_session), "exited", G_CALLBACK (greeter_session_exited_cb), display);
 
653
        g_signal_connect (G_OBJECT (display->priv->greeter_session), "killed", G_CALLBACK (greeter_session_killed_cb), display);
 
654
        session_set_env (display->priv->greeter_session, "DISPLAY", xserver_get_address (display->priv->xserver));
 
655
        if (display->priv->greeter_ck_session)
 
656
            session_set_env (display->priv->greeter_session, "XDG_SESSION_COOKIE", ck_connector_get_cookie (display->priv->greeter_ck_session));
 
657
        set_env_from_pam_session (display->priv->greeter_session, display->priv->greeter_pam_session);
 
658
 
 
659
        g_signal_emit (display, signals[START_GREETER], 0, display->priv->greeter_session);
 
660
 
 
661
        session_start (display->priv->greeter_session);
 
662
 
 
663
        g_free (command);
 
664
        g_key_file_free (theme);
 
665
    }
 
666
}
 
667
 
 
668
#define TYPE_MESSAGE dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID)
 
669
 
 
670
static void
 
671
pam_messages_cb (PAMSession *session, int num_msg, const struct pam_message **msg, Display *display)
 
672
{
 
673
    GPtrArray *request;
 
674
    int i;
 
675
    DBusGMethodInvocation *context;
 
676
 
 
677
    /* Respond to d-bus query with messages */
 
678
    request = g_ptr_array_new ();
 
679
    for (i = 0; i < num_msg; i++)
 
680
    {
 
681
        GValue value = { 0 };
 
682
      
 
683
        g_value_init (&value, TYPE_MESSAGE);
 
684
        g_value_take_boxed (&value, dbus_g_type_specialized_construct (TYPE_MESSAGE));
 
685
        // FIXME: Need to convert to UTF-8
 
686
        dbus_g_type_struct_set (&value, 0, msg[i]->msg_style, 1, msg[i]->msg, G_MAXUINT);
 
687
        g_ptr_array_add (request, g_value_get_boxed (&value));
 
688
    }
 
689
 
 
690
    context = display->priv->dbus_context;
 
691
    display->priv->dbus_context = NULL;
 
692
    dbus_g_method_return (context, 0, request);
 
693
}
 
694
 
 
695
static void
 
696
authenticate_result_cb (PAMSession *session, int result, Display *display)
 
697
{
 
698
    GPtrArray *request;
 
699
    DBusGMethodInvocation *context;
 
700
 
 
701
    g_debug ("Authenticate result for user %s: %s", pam_session_get_username (display->priv->user_pam_session), pam_session_strerror (display->priv->user_pam_session, result));
 
702
 
 
703
    if (result == PAM_SUCCESS)
 
704
    {
 
705
        run_script ("PostLogin");
 
706
        pam_session_authorize (session);
 
707
    }
 
708
 
 
709
    /* Respond to D-Bus request */
 
710
    request = g_ptr_array_new ();
 
711
    context = display->priv->dbus_context;
 
712
    display->priv->dbus_context = NULL;
 
713
 
 
714
    dbus_g_method_return (context, result, request);
 
715
}
 
716
 
 
717
static void
 
718
session_started_cb (PAMSession *session, Display *display)
 
719
{
 
720
    display->priv->user_ck_session = start_ck_session (display, "", pam_session_get_username (display->priv->user_pam_session));
 
721
}
 
722
 
 
723
gboolean
 
724
display_connect (Display *display,
 
725
                 const gchar **theme,
 
726
                 const gchar **language, const gchar **layout, const gchar **session,
 
727
                 const gchar **username, gint *delay, GError *error)
 
728
{
 
729
    if (!display->priv->greeter_connected)
 
730
    {
 
731
        display->priv->greeter_connected = TRUE;
 
732
        g_debug ("Greeter connected");
 
733
    }
 
734
 
 
735
    *theme = g_build_filename (THEME_DIR, display->priv->greeter_theme, "index.theme", NULL);
 
736
    *language = g_strdup (display->priv->default_language);
 
737
    *layout = g_strdup (display->priv->default_layout);
 
738
    *session = g_strdup (display->priv->default_session);
 
739
    *username = g_strdup (display->priv->default_user);
 
740
    *delay = display->priv->timeout;
 
741
 
 
742
    return TRUE;
 
743
}
 
744
 
 
745
gboolean
 
746
display_start_authentication (Display *display, const gchar *username, DBusGMethodInvocation *context)
 
747
{
 
748
    GError *error = NULL;
 
749
 
 
750
    // FIXME: Only allow calls from the correct greeter
 
751
 
 
752
    if (!display->priv->greeter_session || display->priv->user_session)
 
753
    {
 
754
        dbus_g_method_return_error (context, NULL);
 
755
        return TRUE;
 
756
    }
 
757
 
 
758
    /* Abort existing authentication */
 
759
    if (display->priv->user_pam_session)
 
760
    {
 
761
        g_signal_handlers_disconnect_matched (display->priv->user_pam_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
 
762
        pam_session_end (display->priv->user_pam_session);
 
763
        if (display->priv->dbus_context)
 
764
            dbus_g_method_return_error (display->priv->dbus_context, NULL);
 
765
 
 
766
        g_object_unref (display->priv->user_pam_session);
 
767
    }
 
768
 
 
769
    g_debug ("Greeter start authentication for %s", username);
 
770
 
 
771
    /* Store D-Bus request to respond to */
 
772
    display->priv->dbus_context = context;
 
773
 
 
774
    display->priv->user_pam_session = pam_session_new (display->priv->pam_service, username);
 
775
    g_signal_connect (G_OBJECT (display->priv->user_pam_session), "got-messages", G_CALLBACK (pam_messages_cb), display);
 
776
    g_signal_connect (G_OBJECT (display->priv->user_pam_session), "authentication-result", G_CALLBACK (authenticate_result_cb), display);
 
777
    g_signal_connect (G_OBJECT (display->priv->user_pam_session), "started", G_CALLBACK (session_started_cb), display);
 
778
 
 
779
    if (!pam_session_start (display->priv->user_pam_session, &error))
 
780
    {
 
781
        g_warning ("Failed to start authentication: %s", error->message);
 
782
        display->priv->dbus_context = NULL;
 
783
        dbus_g_method_return_error (context, NULL);
 
784
        return FALSE;
 
785
    }
 
786
    g_clear_error (&error);
 
787
 
 
788
    return TRUE;
 
789
}
 
790
 
 
791
gboolean
 
792
display_continue_authentication (Display *display, gchar **secrets, DBusGMethodInvocation *context)
 
793
{
 
794
    int num_messages;
 
795
    const struct pam_message **messages;
 
796
    struct pam_response *response;
 
797
    int i, j, n_secrets = 0;
 
798
 
 
799
    /* Not connected */
 
800
    if (!display->priv->greeter_connected)
 
801
    {
 
802
        dbus_g_method_return_error (context, NULL);
 
803
        return TRUE;
 
804
    }
 
805
 
 
806
    /* Not in authorization */
 
807
    if (display->priv->user_pam_session == NULL)
 
808
    {
 
809
        dbus_g_method_return_error (context, NULL);
 
810
        return TRUE;
 
811
    }
 
812
 
 
813
    /* Already in another call */
 
814
    if (display->priv->dbus_context != NULL)
 
815
    {
 
816
        dbus_g_method_return_error (context, NULL);
 
817
        return TRUE;
 
818
    }
 
819
 
 
820
    // FIXME: Only allow calls from the correct greeter
 
821
 
 
822
    num_messages = pam_session_get_num_messages (display->priv->user_pam_session);
 
823
    messages = pam_session_get_messages (display->priv->user_pam_session);
 
824
 
 
825
    /* Check correct number of responses */
 
826
    for (i = 0; i < num_messages; i++)
 
827
    {
 
828
        int msg_style = messages[i]->msg_style;
 
829
        if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
 
830
            n_secrets++;
 
831
    }
 
832
    if (g_strv_length (secrets) != n_secrets)
 
833
    {
 
834
        pam_session_end (display->priv->user_pam_session);
 
835
        // FIXME: Throw error
 
836
        return FALSE;
 
837
    }
 
838
 
 
839
    g_debug ("Continue authentication");
 
840
 
 
841
    /* Build response */
 
842
    response = calloc (num_messages, sizeof (struct pam_response));  
 
843
    for (i = 0, j = 0; i < num_messages; i++)
 
844
    {
 
845
        int msg_style = messages[i]->msg_style;
 
846
        if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
 
847
        {
 
848
            response[i].resp = strdup (secrets[j]); // FIXME: Need to convert from UTF-8
 
849
            j++;
 
850
        }
 
851
    }
 
852
 
 
853
    display->priv->dbus_context = context;
 
854
    pam_session_respond (display->priv->user_pam_session, response);
 
855
 
 
856
    return TRUE;
 
857
}
 
858
 
 
859
static gboolean
 
860
quit_greeter_cb (gpointer data)
 
861
{
 
862
    Display *display = data;
 
863
    g_warning ("Greeter did not quit, sending kill signal");
 
864
    session_stop (display->priv->greeter_session);
 
865
    display->priv->greeter_quit_timeout = 0;
 
866
    return TRUE;
 
867
}
 
868
 
 
869
static void
 
870
quit_greeter (Display *display)
 
871
{
 
872
    g_signal_emit (display, signals[QUIT_GREETER], 0);
 
873
    if (display->priv->greeter_quit_timeout)
 
874
        g_source_remove (display->priv->greeter_quit_timeout);
 
875
    display->priv->greeter_quit_timeout = g_timeout_add (GREETER_QUIT_TIMEOUT, quit_greeter_cb, display);
 
876
}
 
877
 
 
878
static gboolean
 
879
session_timeout_cb (Display *display)
 
880
{
 
881
    g_warning ("Session has not indicated it is ready, stopping greeter anyway");
 
882
 
 
883
    /* Stop the greeter */
 
884
    quit_greeter (display);
 
885
 
 
886
    display->priv->user_session_timer = 0;
666
887
    return FALSE;
667
888
}
668
889
 
669
 
static void
670
 
user_session_stopped_cb (Session *session, Display *display)
671
 
{
672
 
    g_debug ("User session quit");
673
 
 
674
 
    g_signal_handlers_disconnect_matched (display->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
675
 
    g_object_unref (display->priv->session);
676
 
    display->priv->session = NULL;
677
 
 
678
 
    /* This display has ended */
679
 
    display_stop (display);
680
 
}
681
 
 
682
 
static void
683
 
prepend_argv (gchar ***argv, const gchar *value)
684
 
{
685
 
    gchar **old_argv, **new_argv;
686
 
    gint i;
687
 
 
688
 
    old_argv = *argv;
689
 
    new_argv = g_malloc (sizeof (gchar *) * (g_strv_length (*argv) + 2));
690
 
    new_argv[0] = g_strdup (value);
691
 
    for (i = 0; old_argv[i]; i++)
692
 
        new_argv[i + 1] = old_argv[i];
693
 
    new_argv[i + 1] = NULL;
694
 
 
695
 
    g_free (*argv);
696
 
    *argv = new_argv;
697
 
}
698
 
 
699
 
static gboolean
700
 
display_start_session (Display *display)
701
 
{
702
 
    User *user;
703
 
    gchar *filename, *sessions_dir, *path;
704
 
    gchar **argv;
705
 
 
706
 
    user = session_get_user (display->priv->session);
707
 
 
708
 
    /* Find the command to run for the selected session */
709
 
    if (display->priv->user_session_type == SESSION_TYPE_LOCAL)
 
890
gboolean
 
891
display_login (Display *display, gchar *username, gchar *session, gchar *language, GError *error)
 
892
{
 
893
    if (display->priv->user_session != NULL)
710
894
    {
711
 
        sessions_dir = config_get_string (config_get_instance (), "LightDM", "xsessions-directory");
712
 
 
713
 
        /* Store this session name so we automatically use it next time */
714
 
        user_set_xsession (user, display->priv->user_session);
 
895
        g_warning ("Ignoring request to log in when already logged in");
 
896
        return TRUE;
715
897
    }
716
 
    else
717
 
        sessions_dir = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory");
718
 
    filename = g_strdup_printf ("%s.desktop", display->priv->user_session);
719
 
    path = g_build_filename (sessions_dir, filename, NULL);
720
 
    g_free (sessions_dir);
721
 
    g_free (filename);
722
 
    argv = get_session_command (path, display->priv->session_wrapper);
723
 
    g_free (path);
724
 
    if (!argv)
725
 
        return TRUE;
 
898
 
 
899
    g_debug ("Greeter login for user %s on session %s", username, session);
726
900
  
727
 
    session_set_env (display->priv->session, "DESKTOP_SESSION", display->priv->user_session); // FIXME: Apparently deprecated?
728
 
    session_set_env (display->priv->session, "GDMSESSION", display->priv->user_session); // FIXME: Not cross-desktop
729
 
 
730
 
    /* Run a guest session through the wrapper covered by MAC */
731
 
    if (display->priv->autologin_guest)
732
 
    {
733
 
        gchar *wrapper = g_build_filename (PKGLIBEXEC_DIR, "lightdm-guest-session-wrapper", NULL);
734
 
        g_debug ("Running guest session through wrapper: %s", wrapper);
735
 
        prepend_argv (&argv, wrapper);
736
 
        g_free (wrapper);
737
 
    }
738
 
 
739
 
    g_debug ("Starting session %s as user %s", display->priv->user_session, session_get_username (display->priv->session));
740
 
 
741
 
    session_run (display->priv->session, argv);
742
 
    g_strfreev (argv);
743
 
 
744
 
    // FIXME: Wait for session to indicate it is ready (maybe)
745
 
    display_set_is_ready (display);
746
 
 
747
 
    return FALSE;
748
 
}
749
 
 
750
 
static void
751
 
display_server_stopped_cb (DisplayServer *server, Display *display)
752
 
{
753
 
    g_debug ("Display server stopped");
754
 
 
755
 
    g_signal_handlers_disconnect_matched (display->priv->display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
756
 
    g_object_unref (display->priv->display_server);
757
 
    display->priv->display_server = NULL;
758
 
 
759
 
    /* Stop this display, it will be restarted by the seat if necessary */
760
 
    display_stop (display);
761
 
}
762
 
 
763
 
static void
764
 
display_server_ready_cb (DisplayServer *display_server, Display *display)
765
 
{
766
 
    gboolean result = FALSE;
767
 
 
768
 
    g_signal_emit (display, signals[DISPLAY_SERVER_READY], 0, &result);
769
 
    if (!result)
770
 
    {
771
 
        display_stop (display);
772
 
        return;
773
 
    }
 
901
    /* Default session requested */
 
902
    if (strcmp (session, "") == 0)
 
903
        session = display->priv->default_session;
 
904
 
 
905
    /* Default language requested */
 
906
    if (strcmp (language, "") == 0)
 
907
        language = NULL;
 
908
 
 
909
    if (display->priv->default_user && strcmp (username, display->priv->default_user) == 0)
 
910
        start_default_session (display, session, language);
 
911
    else if (display->priv->user_pam_session &&
 
912
             pam_session_get_in_session (display->priv->user_pam_session) &&
 
913
             strcmp (username, pam_session_get_username (display->priv->user_pam_session)) == 0)
 
914
        start_user_session (display, session, language);
 
915
    else
 
916
    {
 
917
        g_warning ("Ignoring request for login with unauthenticated user");
 
918
        return FALSE;
 
919
    }
 
920
 
 
921
    /* Stop session, waiting for user session to indicate it is ready (if supported) */
 
922
    // FIXME: Hard-coded timeout
 
923
    if (display->priv->supports_transitions)
 
924
        display->priv->user_session_timer = g_timeout_add (USER_SESSION_TIMEOUT, (GSourceFunc) session_timeout_cb, display);
 
925
    else
 
926
        quit_greeter (display);
 
927
 
 
928
    return TRUE;
 
929
}
 
930
 
 
931
static void
 
932
xserver_exit_cb (XServer *server, Display *display)
 
933
{
 
934
    g_object_unref (display->priv->xserver);
 
935
    display->priv->xserver = NULL;
 
936
    g_signal_emit (display, signals[EXITED], 0);
 
937
}
 
938
 
 
939
static void
 
940
xserver_ready_cb (XServer *xserver, Display *display)
 
941
{
 
942
    run_script ("Init"); // FIXME: Async
774
943
 
775
944
    /* Don't run any sessions on local terminals */
776
 
    if (!display_server_get_start_local_sessions (display_server))
 
945
    if (xserver_get_server_type (xserver) == XSERVER_TYPE_LOCAL_TERMINAL)
777
946
        return;
778
947
 
779
 
    /* Automatically start requested user session */
780
 
    result = FALSE;
781
 
    if (display->priv->autologin_timeout == 0 && display->priv->autologin_guest)
782
 
    {
783
 
        g_debug ("Automatically logging in as guest");
784
 
        result = autologin_guest (display, AUTOLOGIN_SERVICE, TRUE);
785
 
    }
786
 
    else if (display->priv->autologin_timeout == 0 && display->priv->autologin_user)
787
 
    {
788
 
        g_debug ("Automatically logging in user %s", display->priv->autologin_user);
789
 
        result = autologin (display, display->priv->autologin_user, AUTOLOGIN_SERVICE, TRUE, FALSE);
790
 
    }
791
 
    else if (display->priv->select_user_hint)
792
 
    {
793
 
        g_debug ("Logging in user %s", display->priv->select_user_hint);
794
 
        result = autologin (display, display->priv->select_user_hint, USER_SERVICE, TRUE, FALSE);
795
 
    }
796
 
 
797
 
    /* If no session started, start a greeter */
798
 
    if (!result)
799
 
    {
800
 
        g_debug ("Starting greeter");      
801
 
        result = start_greeter (display);
802
 
    }
803
 
 
804
 
    /* If nothing started, then the display can't work */
805
 
    if (!result)
806
 
        display_stop (display);
 
948
    /* If have user then automatically login the first time */
 
949
    if (display->priv->default_user && display->priv->timeout == 0 && display->priv->login_count == 0)
 
950
        start_default_session (display, display->priv->default_session, NULL);
 
951
    else
 
952
        start_greeter (display);
807
953
}
808
954
 
809
955
gboolean
810
956
display_start (Display *display)
811
957
{
812
 
    g_return_val_if_fail (display != NULL, FALSE);
813
 
 
814
 
    g_signal_connect (G_OBJECT (display->priv->display_server), "ready", G_CALLBACK (display_server_ready_cb), display);
815
 
    g_signal_connect (G_OBJECT (display->priv->display_server), "stopped", G_CALLBACK (display_server_stopped_cb), display);
816
 
 
817
 
    if (!display_server_start (display->priv->display_server))
818
 
        return FALSE;
819
 
 
820
 
    return TRUE;
821
 
}
822
 
 
823
 
void
824
 
display_stop (Display *display)
825
 
{
826
 
    g_return_if_fail (display != NULL);
827
 
 
828
 
    if (display->priv->stopped)
829
 
        return;
830
 
 
831
 
    if (!display->priv->stopping)
832
 
    {
833
 
        g_debug ("Stopping display");
834
 
        display->priv->stopping = TRUE;
835
 
    }
836
 
 
837
 
    /* Stop the session first */
838
 
    if (display->priv->session)
839
 
    {
840
 
        session_stop (display->priv->session);
841
 
        if (display->priv->session && !session_get_is_stopped (display->priv->session))
842
 
            return;
843
 
        g_signal_handlers_disconnect_matched (display->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
844
 
        g_object_unref (display->priv->session);
845
 
        display->priv->session = NULL;
846
 
    }
847
 
 
848
 
    /* Stop the display server after that */
849
 
    if (display->priv->display_server)
850
 
    {
851
 
        display_server_stop (display->priv->display_server);
852
 
        if (display->priv->display_server && !display_server_get_is_stopped (display->priv->display_server))
853
 
            return;
854
 
        g_signal_handlers_disconnect_matched (display->priv->display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
855
 
        g_object_unref (display->priv->display_server);
856
 
        display->priv->display_server = NULL;
857
 
    }
858
 
 
859
 
    display->priv->stopped = TRUE;
860
 
    g_debug ("Display stopped");
861
 
    g_signal_emit (display, signals[STOPPED], 0);
862
 
}
863
 
 
864
 
gboolean
865
 
display_get_is_ready (Display *display)
866
 
{
867
 
    g_return_val_if_fail (display != NULL, FALSE);
868
 
 
869
 
    return display->priv->is_ready;
870
 
}
871
 
 
872
 
void
873
 
display_lock (Display *display)
874
 
{
875
 
    g_return_if_fail (display != NULL);
876
 
 
877
 
    if (!display->priv->session)
878
 
        return;
879
 
 
880
 
    g_debug ("Locking display");
881
 
 
882
 
    session_lock (display->priv->session);
883
 
}
884
 
 
885
 
void
886
 
display_unlock (Display *display)
887
 
{
888
 
    g_return_if_fail (display != NULL);
889
 
 
890
 
    if (!display->priv->session)
891
 
        return;
892
 
 
893
 
    g_debug ("Unlocking display");
894
 
 
895
 
    session_unlock (display->priv->session);
896
 
}
897
 
 
898
 
static gboolean
899
 
display_real_switch_to_user (Display *display, User *user)
900
 
{
901
 
    return FALSE;
902
 
}
903
 
 
904
 
static gboolean
905
 
display_real_switch_to_guest (Display *display)
906
 
{
907
 
    return FALSE;
908
 
}
909
 
 
910
 
static gchar *
911
 
display_real_get_guest_username (Display *display)
912
 
{
913
 
    return NULL;
 
958
    g_return_val_if_fail (display->priv->xserver != NULL, FALSE);
 
959
    g_signal_connect (G_OBJECT (display->priv->xserver), "ready", G_CALLBACK (xserver_ready_cb), display);
 
960
    g_signal_connect (G_OBJECT (display->priv->xserver), "exited", G_CALLBACK (xserver_exit_cb), display);
 
961
    return xserver_start (display->priv->xserver);
914
962
}
915
963
 
916
964
static void
917
965
display_init (Display *display)
918
966
{
919
967
    display->priv = G_TYPE_INSTANCE_GET_PRIVATE (display, DISPLAY_TYPE, DisplayPrivate);
 
968
    if (strcmp (GREETER_USER, "") != 0)
 
969
        display->priv->greeter_user = g_strdup (GREETER_USER);
 
970
    display->priv->greeter_theme = g_strdup (GREETER_THEME);
 
971
    display->priv->default_language = getenv ("LANG") ? g_strdup (getenv ("LANG")) : g_strdup ("C");
 
972
    display->priv->default_layout = g_strdup ("us"); // FIXME: Is there a better default to get?
 
973
    display->priv->default_session = g_strdup (DEFAULT_SESSION);
920
974
}
921
975
 
922
976
static void
926
980
 
927
981
    self = DISPLAY (object);
928
982
 
929
 
    if (self->priv->display_server)
930
 
    {
931
 
        g_signal_handlers_disconnect_matched (self->priv->display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
932
 
        g_object_unref (self->priv->display_server);
933
 
    }
934
 
    g_free (self->priv->greeter_session);
935
 
    if (self->priv->greeter)
936
 
    {
937
 
        g_signal_handlers_disconnect_matched (self->priv->greeter, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
938
 
        g_object_unref (self->priv->greeter);
939
 
    }
940
 
    g_free (self->priv->session_wrapper);
941
 
    if (self->priv->session)
942
 
    {
943
 
        g_signal_handlers_disconnect_matched (self->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);      
944
 
        g_object_unref (self->priv->session);
945
 
    }
946
 
    g_free (self->priv->autologin_user);
947
 
    g_free (self->priv->select_user_hint);
948
 
    g_free (self->priv->user_session);
949
 
 
950
 
    G_OBJECT_CLASS (display_parent_class)->finalize (object);
 
983
    if (self->priv->greeter_session)
 
984
        g_object_unref (self->priv->greeter_session);
 
985
    if (self->priv->user_session_timer)
 
986
        g_source_remove (self->priv->user_session_timer);
 
987
    if (self->priv->user_session)
 
988
        g_object_unref (self->priv->user_session);
 
989
    if (self->priv->user_pam_session)
 
990
        g_object_unref (self->priv->user_pam_session);
 
991
    end_ck_session (self->priv->greeter_ck_session);
 
992
    end_ck_session (self->priv->user_ck_session);
 
993
    if (self->priv->xserver)  
 
994
        g_object_unref (self->priv->xserver);
 
995
    g_free (self->priv->greeter_user);
 
996
    g_free (self->priv->greeter_theme);
 
997
    g_free (self->priv->default_user);
 
998
    g_free (self->priv->default_language);
 
999
    g_free (self->priv->default_layout);
 
1000
    g_free (self->priv->default_session);
951
1001
}
952
1002
 
953
1003
static void
955
1005
{
956
1006
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
957
1007
 
958
 
    klass->switch_to_user = display_real_switch_to_user;
959
 
    klass->switch_to_guest = display_real_switch_to_guest;
960
 
    klass->get_guest_username = display_real_get_guest_username;
961
 
    klass->start_greeter = display_start_greeter;
962
 
    klass->start_session = display_start_session;
963
1008
    object_class->finalize = display_finalize;
964
1009
 
965
1010
    g_type_class_add_private (klass, sizeof (DisplayPrivate));
966
1011
 
967
 
    signals[CREATE_SESSION] =
968
 
        g_signal_new ("create-session",
969
 
                      G_TYPE_FROM_CLASS (klass),
970
 
                      G_SIGNAL_RUN_LAST,
971
 
                      G_STRUCT_OFFSET (DisplayClass, create_session),
972
 
                      NULL, NULL,
973
 
                      ldm_marshal_OBJECT__VOID,
974
 
                      SESSION_TYPE, 0);
975
 
    signals[READY] =
976
 
        g_signal_new ("ready",
977
 
                      G_TYPE_FROM_CLASS (klass),
978
 
                      G_SIGNAL_RUN_LAST,
979
 
                      G_STRUCT_OFFSET (DisplayClass, ready),
980
 
                      NULL, NULL,
981
 
                      g_cclosure_marshal_VOID__VOID,
982
 
                      G_TYPE_NONE, 0);
983
 
    signals[SWITCH_TO_USER] =
984
 
        g_signal_new ("switch-to-user",
985
 
                      G_TYPE_FROM_CLASS (klass),
986
 
                      G_SIGNAL_RUN_LAST,
987
 
                      G_STRUCT_OFFSET (DisplayClass, switch_to_user),
988
 
                      g_signal_accumulator_true_handled,
989
 
                      NULL,
990
 
                      ldm_marshal_BOOLEAN__OBJECT,
991
 
                      G_TYPE_BOOLEAN, 1, USER_TYPE);
992
 
    signals[SWITCH_TO_GUEST] =
993
 
        g_signal_new ("switch-to-guest",
994
 
                      G_TYPE_FROM_CLASS (klass),
995
 
                      G_SIGNAL_RUN_LAST,
996
 
                      G_STRUCT_OFFSET (DisplayClass, switch_to_guest),
997
 
                      g_signal_accumulator_true_handled,
998
 
                      NULL,
999
 
                      ldm_marshal_BOOLEAN__VOID,
1000
 
                      G_TYPE_BOOLEAN, 0);
1001
 
    signals[GET_GUEST_USERNAME] =
1002
 
        g_signal_new ("get-guest-username",
1003
 
                      G_TYPE_FROM_CLASS (klass),
1004
 
                      G_SIGNAL_RUN_LAST,
1005
 
                      G_STRUCT_OFFSET (DisplayClass, get_guest_username),
1006
 
                      g_signal_accumulator_first_wins,
1007
 
                      NULL,
1008
 
                      ldm_marshal_STRING__VOID,
1009
 
                      G_TYPE_STRING, 0);
1010
 
    signals[DISPLAY_SERVER_READY] =
1011
 
        g_signal_new ("display-server-ready",
1012
 
                      G_TYPE_FROM_CLASS (klass),
1013
 
                      G_SIGNAL_RUN_LAST,
1014
 
                      G_STRUCT_OFFSET (DisplayClass, display_server_ready),
1015
 
                      NULL, NULL,
1016
 
                      ldm_marshal_BOOLEAN__VOID,
1017
 
                      G_TYPE_BOOLEAN, 0);
1018
1012
    signals[START_GREETER] =
1019
1013
        g_signal_new ("start-greeter",
1020
1014
                      G_TYPE_FROM_CLASS (klass),
1021
1015
                      G_SIGNAL_RUN_LAST,
1022
1016
                      G_STRUCT_OFFSET (DisplayClass, start_greeter),
1023
 
                      g_signal_accumulator_true_handled, NULL,
1024
 
                      ldm_marshal_BOOLEAN__VOID,
1025
 
                      G_TYPE_BOOLEAN, 0);
 
1017
                      NULL, NULL,
 
1018
                      g_cclosure_marshal_VOID__OBJECT,
 
1019
                      G_TYPE_NONE, 1, SESSION_TYPE);
 
1020
 
 
1021
    signals[END_GREETER] =
 
1022
        g_signal_new ("end-greeter",
 
1023
                      G_TYPE_FROM_CLASS (klass),
 
1024
                      G_SIGNAL_RUN_LAST,
 
1025
                      G_STRUCT_OFFSET (DisplayClass, end_greeter),
 
1026
                      NULL, NULL,
 
1027
                      g_cclosure_marshal_VOID__OBJECT,
 
1028
                      G_TYPE_NONE, 1, SESSION_TYPE);
 
1029
  
1026
1030
    signals[START_SESSION] =
1027
1031
        g_signal_new ("start-session",
1028
1032
                      G_TYPE_FROM_CLASS (klass),
1029
1033
                      G_SIGNAL_RUN_LAST,
1030
1034
                      G_STRUCT_OFFSET (DisplayClass, start_session),
1031
 
                      g_signal_accumulator_true_handled, NULL,
1032
 
                      ldm_marshal_BOOLEAN__VOID,
1033
 
                      G_TYPE_BOOLEAN, 0);
1034
 
    signals[STOPPED] =
1035
 
        g_signal_new ("stopped",
1036
 
                      G_TYPE_FROM_CLASS (klass),
1037
 
                      G_SIGNAL_RUN_LAST,
1038
 
                      G_STRUCT_OFFSET (DisplayClass, stopped),
1039
 
                      NULL, NULL,
1040
 
                      g_cclosure_marshal_VOID__VOID,
1041
 
                      G_TYPE_NONE, 0);
 
1035
                      NULL, NULL,
 
1036
                      g_cclosure_marshal_VOID__OBJECT,
 
1037
                      G_TYPE_NONE, 1, SESSION_TYPE);
 
1038
 
 
1039
    signals[END_SESSION] =
 
1040
        g_signal_new ("end-session",
 
1041
                      G_TYPE_FROM_CLASS (klass),
 
1042
                      G_SIGNAL_RUN_LAST,
 
1043
                      G_STRUCT_OFFSET (DisplayClass, end_session),
 
1044
                      NULL, NULL,
 
1045
                      g_cclosure_marshal_VOID__OBJECT,
 
1046
                      G_TYPE_NONE, 1, SESSION_TYPE);
 
1047
 
 
1048
    signals[EXITED] =
 
1049
        g_signal_new ("exited",
 
1050
                      G_TYPE_FROM_CLASS (klass),
 
1051
                      G_SIGNAL_RUN_LAST,
 
1052
                      G_STRUCT_OFFSET (DisplayClass, exited),
 
1053
                      NULL, NULL,
 
1054
                      g_cclosure_marshal_VOID__VOID,
 
1055
                      G_TYPE_NONE, 0);
 
1056
 
 
1057
    signals[QUIT_GREETER] =
 
1058
        g_signal_new ("quit_greeter",
 
1059
                      G_TYPE_FROM_CLASS (klass),
 
1060
                      G_SIGNAL_RUN_LAST,
 
1061
                      G_STRUCT_OFFSET (DisplayClass, quit_greeter),
 
1062
                      NULL, NULL,
 
1063
                      g_cclosure_marshal_VOID__VOID,
 
1064
                      G_TYPE_NONE, 0);
 
1065
 
 
1066
    dbus_g_object_type_install_info (DISPLAY_TYPE, &dbus_glib_display_object_info);
1042
1067
}