source: proiecte/PPPP/gdm/daemon/gdm-session-direct.c @ 134

Last change on this file since 134 was 134, checked in by (none), 14 years ago

gdm sources with the modifications for webcam

File size: 92.8 KB
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
4 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include "config.h"
23
24#include <dirent.h>
25#include <errno.h>
26#include <fcntl.h>
27
28#include <stdlib.h>
29#include <string.h>
30#include <sys/resource.h>
31#include <sys/socket.h>
32#include <sys/types.h>
33#include <sys/wait.h>
34#include <unistd.h>
35#include <pwd.h>
36#include <grp.h>
37
38#include <locale.h>
39
40#include <glib.h>
41#include <glib/gi18n.h>
42#include <glib/gstdio.h>
43#include <glib-object.h>
44
45#include <dbus/dbus-glib.h>
46#include <dbus/dbus-glib-lowlevel.h>
47
48#include "gdm-session-direct.h"
49#include "gdm-session.h"
50#include "gdm-session-private.h"
51#include "gdm-session-direct-glue.h"
52
53#include "gdm-session-record.h"
54#include "gdm-session-worker-job.h"
55
56#define GDM_SESSION_DBUS_PATH         "/org/gnome/DisplayManager/Session"
57#define GDM_SESSION_DBUS_INTERFACE    "org.gnome.DisplayManager.Session"
58#define GDM_SESSION_DBUS_ERROR_CANCEL "org.gnome.DisplayManager.Session.Error.Cancel"
59
60#ifndef GDM_SESSION_DEFAULT_PATH
61#define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin"
62#endif
63
64struct _GdmSessionDirectPrivate
65{
66        /* per open scope */
67        char                *selected_session;
68        char                *saved_session;
69        char                *selected_language;
70        char                *saved_language;
71        char                *selected_layout;
72        char                *saved_layout;
73        char                *selected_user;
74        char                *user_x11_authority_file;
75
76        DBusMessage         *message_pending_reply;
77        DBusConnection      *worker_connection;
78
79        GdmSessionWorkerJob *job;
80        GPid                 session_pid;
81        guint32              is_authenticated : 1;
82        guint32              is_running : 1;
83
84        /* object lifetime scope */
85        char                *id;
86        char                *display_id;
87        char                *display_name;
88        char                *display_hostname;
89        char                *display_device;
90        char                *display_x11_authority_file;
91        gboolean             display_is_local;
92
93        DBusServer          *server;
94        char                *server_address;
95        GHashTable          *environment;
96        DBusGConnection     *connection;
97};
98
99enum {
100        PROP_0,
101        PROP_DISPLAY_ID,
102        PROP_DISPLAY_NAME,
103        PROP_DISPLAY_HOSTNAME,
104        PROP_DISPLAY_IS_LOCAL,
105        PROP_DISPLAY_DEVICE,
106        PROP_DISPLAY_X11_AUTHORITY_FILE,
107        PROP_USER_X11_AUTHORITY_FILE,
108};
109
110static void     gdm_session_iface_init          (GdmSessionIface      *iface);
111
112G_DEFINE_TYPE_WITH_CODE (GdmSessionDirect,
113                         gdm_session_direct,
114                         G_TYPE_OBJECT,
115                         G_IMPLEMENT_INTERFACE (GDM_TYPE_SESSION,
116                                                gdm_session_iface_init))
117
118static gboolean
119send_dbus_message (DBusConnection *connection,
120                   DBusMessage    *message)
121{
122        gboolean is_connected;
123        gboolean sent;
124
125        g_return_val_if_fail (message != NULL, FALSE);
126
127        if (connection == NULL) {
128                g_warning ("There is no valid connection");
129                return FALSE;
130        }
131
132        is_connected = dbus_connection_get_is_connected (connection);
133        if (! is_connected) {
134                g_warning ("Not connected!");
135                return FALSE;
136        }
137
138        sent = dbus_connection_send (connection, message, NULL);
139
140        return sent;
141}
142
143static void
144send_dbus_string_signal (GdmSessionDirect *session,
145                         const char *name,
146                         const char *text)
147{
148        DBusMessage    *message;
149        DBusMessageIter iter;
150
151        g_return_if_fail (session != NULL);
152
153        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
154                                           GDM_SESSION_DBUS_INTERFACE,
155                                           name);
156
157        dbus_message_iter_init_append (message, &iter);
158        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &text);
159
160        if (! send_dbus_message (session->priv->worker_connection, message)) {
161                g_debug ("GdmSessionDirect: Could not send %s signal",
162                         name ? name : "(null)");
163        }
164
165        dbus_message_unref (message);
166}
167
168static void
169send_dbus_void_signal (GdmSessionDirect *session,
170                       const char       *name)
171{
172        DBusMessage *message;
173
174        g_return_if_fail (session != NULL);
175
176        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
177                                           GDM_SESSION_DBUS_INTERFACE,
178                                           name);
179
180        if (! send_dbus_message (session->priv->worker_connection, message)) {
181                g_debug ("GdmSessionDirect: Could not send %s signal", name);
182        }
183
184        dbus_message_unref (message);
185}
186
187static void
188on_authentication_failed (GdmSession *session,
189                          const char *message)
190{
191        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
192        gdm_session_record_failed (impl->priv->session_pid,
193                                   impl->priv->selected_user,
194                                   impl->priv->display_hostname,
195                                   impl->priv->display_name,
196                                   impl->priv->display_device);
197}
198
199static void
200on_session_started (GdmSession *session)
201{
202        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
203        gdm_session_record_login (impl->priv->session_pid,
204                                  impl->priv->selected_user,
205                                  impl->priv->display_hostname,
206                                  impl->priv->display_name,
207                                  impl->priv->display_device);
208}
209
210static void
211on_session_start_failed (GdmSession *session,
212                         const char *message)
213{
214        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
215        gdm_session_record_login (impl->priv->session_pid,
216                                  impl->priv->selected_user,
217                                  impl->priv->display_hostname,
218                                  impl->priv->display_name,
219                                  impl->priv->display_device);
220}
221
222static void
223on_session_exited (GdmSession *session,
224                   int        exit_code)
225{
226        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
227        gdm_session_record_logout (impl->priv->session_pid,
228                                   impl->priv->selected_user,
229                                   impl->priv->display_hostname,
230                                   impl->priv->display_name,
231                                   impl->priv->display_device);
232}
233
234static DBusHandlerResult
235gdm_session_direct_handle_setup_complete (GdmSessionDirect *session,
236                                          DBusConnection   *connection,
237                                          DBusMessage      *message)
238{
239        DBusMessage *reply;
240
241        g_debug ("GdmSessionDirect: Emitting 'setup-complete' signal");
242
243        reply = dbus_message_new_method_return (message);
244        dbus_connection_send (connection, reply, NULL);
245        dbus_message_unref (reply);
246
247        _gdm_session_setup_complete (GDM_SESSION (session));
248
249        return DBUS_HANDLER_RESULT_HANDLED;
250}
251
252static DBusHandlerResult
253gdm_session_direct_handle_setup_failed (GdmSessionDirect *session,
254                                        DBusConnection   *connection,
255                                        DBusMessage      *message)
256{
257        DBusMessage *reply;
258        DBusError    error;
259        const char  *text;
260
261        dbus_error_init (&error);
262        if (! dbus_message_get_args (message, &error,
263                                     DBUS_TYPE_STRING, &text,
264                                     DBUS_TYPE_INVALID)) {
265                g_warning ("ERROR: %s", error.message);
266        }
267
268        reply = dbus_message_new_method_return (message);
269        dbus_connection_send (connection, reply, NULL);
270        dbus_message_unref (reply);
271
272        g_debug ("GdmSessionDirect: Emitting 'setup-failed' signal");
273
274        _gdm_session_setup_failed (GDM_SESSION (session), text);
275
276        return DBUS_HANDLER_RESULT_HANDLED;
277}
278
279
280static DBusHandlerResult
281gdm_session_direct_handle_reset_complete (GdmSessionDirect *session,
282                                          DBusConnection   *connection,
283                                          DBusMessage      *message)
284{
285        DBusMessage *reply;
286
287        g_debug ("GdmSessionDirect: Emitting 'reset-complete' signal");
288
289        reply = dbus_message_new_method_return (message);
290        dbus_connection_send (connection, reply, NULL);
291        dbus_message_unref (reply);
292
293        _gdm_session_reset_complete (GDM_SESSION (session));
294
295        return DBUS_HANDLER_RESULT_HANDLED;
296}
297
298static DBusHandlerResult
299gdm_session_direct_handle_reset_failed (GdmSessionDirect *session,
300                                        DBusConnection   *connection,
301                                        DBusMessage      *message)
302{
303        DBusMessage *reply;
304        DBusError    error;
305        const char  *text;
306
307        dbus_error_init (&error);
308        if (! dbus_message_get_args (message, &error,
309                                     DBUS_TYPE_STRING, &text,
310                                     DBUS_TYPE_INVALID)) {
311                g_warning ("ERROR: %s", error.message);
312        }
313
314        reply = dbus_message_new_method_return (message);
315        dbus_connection_send (connection, reply, NULL);
316        dbus_message_unref (reply);
317
318        g_debug ("GdmSessionDirect: Emitting 'reset-failed' signal");
319
320        _gdm_session_reset_failed (GDM_SESSION (session), text);
321
322        return DBUS_HANDLER_RESULT_HANDLED;
323}
324
325static DBusHandlerResult
326gdm_session_direct_handle_authenticated (GdmSessionDirect *session,
327                                         DBusConnection   *connection,
328                                         DBusMessage      *message)
329{
330        DBusMessage *reply;
331
332        g_debug ("GdmSessionDirect: Emitting 'authenticated' signal");
333
334        reply = dbus_message_new_method_return (message);
335        dbus_connection_send (connection, reply, NULL);
336        dbus_message_unref (reply);
337
338        session->priv->is_authenticated = TRUE;
339        _gdm_session_authenticated (GDM_SESSION (session));
340
341        return DBUS_HANDLER_RESULT_HANDLED;
342}
343
344static DBusHandlerResult
345gdm_session_direct_handle_authentication_failed (GdmSessionDirect *session,
346                                                 DBusConnection   *connection,
347                                                 DBusMessage      *message)
348{
349        DBusMessage *reply;
350        DBusError    error;
351        const char  *text;
352
353        dbus_error_init (&error);
354        if (! dbus_message_get_args (message, &error,
355                                     DBUS_TYPE_STRING, &text,
356                                     DBUS_TYPE_INVALID)) {
357                g_warning ("ERROR: %s", error.message);
358        }
359
360        reply = dbus_message_new_method_return (message);
361        dbus_connection_send (connection, reply, NULL);
362        dbus_message_unref (reply);
363
364        g_debug ("GdmSessionDirect: Emitting 'authentication-failed' signal");
365
366        session->priv->is_authenticated = FALSE;
367        _gdm_session_authentication_failed (GDM_SESSION (session), text);
368
369        return DBUS_HANDLER_RESULT_HANDLED;
370}
371
372static DBusHandlerResult
373gdm_session_direct_handle_authorized (GdmSessionDirect *session,
374                                      DBusConnection   *connection,
375                                      DBusMessage      *message)
376{
377        DBusMessage *reply;
378
379        g_debug ("GdmSessionDirect: Emitting 'authorized' signal");
380
381        reply = dbus_message_new_method_return (message);
382        dbus_connection_send (connection, reply, NULL);
383        dbus_message_unref (reply);
384
385        _gdm_session_authorized (GDM_SESSION (session));
386
387        return DBUS_HANDLER_RESULT_HANDLED;
388}
389
390static DBusHandlerResult
391gdm_session_direct_handle_authorization_failed (GdmSessionDirect *session,
392                                                DBusConnection   *connection,
393                                                DBusMessage      *message)
394{
395        DBusMessage *reply;
396        DBusError    error;
397        const char  *text;
398
399        dbus_error_init (&error);
400        if (! dbus_message_get_args (message, &error,
401                                     DBUS_TYPE_STRING, &text,
402                                     DBUS_TYPE_INVALID)) {
403                g_warning ("ERROR: %s", error.message);
404        }
405
406        reply = dbus_message_new_method_return (message);
407        dbus_connection_send (connection, reply, NULL);
408        dbus_message_unref (reply);
409
410        g_debug ("GdmSessionDirect: Emitting 'authorization-failed' signal");
411
412        _gdm_session_authorization_failed (GDM_SESSION (session), text);
413
414        return DBUS_HANDLER_RESULT_HANDLED;
415}
416
417static DBusHandlerResult
418gdm_session_direct_handle_accredited (GdmSessionDirect *session,
419                                      DBusConnection   *connection,
420                                      DBusMessage      *message)
421{
422        DBusMessage *reply;
423
424        g_debug ("GdmSessionDirect: Emitting 'accredited' signal");
425
426        reply = dbus_message_new_method_return (message);
427        dbus_connection_send (connection, reply, NULL);
428        dbus_message_unref (reply);
429
430        _gdm_session_accredited (GDM_SESSION (session));
431
432        return DBUS_HANDLER_RESULT_HANDLED;
433}
434
435static DBusHandlerResult
436gdm_session_direct_handle_accreditation_failed (GdmSessionDirect *session,
437                                                DBusConnection   *connection,
438                                                DBusMessage      *message)
439{
440        DBusMessage *reply;
441        DBusError    error;
442        const char  *text;
443
444        dbus_error_init (&error);
445        if (! dbus_message_get_args (message, &error,
446                                     DBUS_TYPE_STRING, &text,
447                                     DBUS_TYPE_INVALID)) {
448                g_warning ("ERROR: %s", error.message);
449        }
450
451        reply = dbus_message_new_method_return (message);
452        dbus_connection_send (connection, reply, NULL);
453        dbus_message_unref (reply);
454
455        g_debug ("GdmSessionDirect: Emitting 'accreditation-failed' signal");
456
457        _gdm_session_accreditation_failed (GDM_SESSION (session), text);
458
459        return DBUS_HANDLER_RESULT_HANDLED;
460}
461
462static const char **
463get_system_session_dirs (void)
464{
465        static const char *search_dirs[] = {
466                "/etc/X11/sessions/",
467                DMCONFDIR "/Sessions/",
468                DATADIR "/xsessions/",
469                DATADIR "/gdm/BuiltInSessions/",
470                NULL
471        };
472
473        return search_dirs;
474}
475
476static gboolean
477is_prog_in_path (const char *prog)
478{
479        char    *f;
480        gboolean ret;
481
482        f = g_find_program_in_path (prog);
483        ret = (f != NULL);
484        g_free (f);
485        return ret;
486}
487
488static gboolean
489get_session_command_for_file (const char *file,
490                              char      **command)
491{
492        GKeyFile   *key_file;
493        GError     *error;
494        char       *full_path;
495        char       *exec;
496        gboolean    ret;
497        gboolean    res;
498
499        exec = NULL;
500        ret = FALSE;
501        if (command != NULL) {
502                *command = NULL;
503        }
504
505        key_file = g_key_file_new ();
506
507        g_debug ("GdmSessionDirect: looking for session file '%s'", file);
508
509        error = NULL;
510        full_path = NULL;
511        res = g_key_file_load_from_dirs (key_file,
512                                         file,
513                                         get_system_session_dirs (),
514                                         &full_path,
515                                         G_KEY_FILE_NONE,
516                                         &error);
517        if (! res) {
518                g_debug ("GdmSessionDirect: File '%s' not found: %s", file, error->message);
519                g_error_free (error);
520                if (command != NULL) {
521                        *command = NULL;
522                }
523                goto out;
524        }
525
526        error = NULL;
527        res = g_key_file_get_boolean (key_file,
528                                      G_KEY_FILE_DESKTOP_GROUP,
529                                      G_KEY_FILE_DESKTOP_KEY_HIDDEN,
530                                      &error);
531        if (error == NULL && res) {
532                g_debug ("GdmSessionDirect: Session %s is marked as hidden", file);
533                goto out;
534        }
535
536        exec = g_key_file_get_string (key_file,
537                                      G_KEY_FILE_DESKTOP_GROUP,
538                                      G_KEY_FILE_DESKTOP_KEY_TRY_EXEC,
539                                      NULL);
540        if (exec != NULL) {
541                res = is_prog_in_path (exec);
542                g_free (exec);
543
544                if (! res) {
545                        g_debug ("GdmSessionDirect: Command not found: %s",
546                                 G_KEY_FILE_DESKTOP_KEY_TRY_EXEC);
547                        goto out;
548                }
549        }
550
551        error = NULL;
552        exec = g_key_file_get_string (key_file,
553                                      G_KEY_FILE_DESKTOP_GROUP,
554                                      G_KEY_FILE_DESKTOP_KEY_EXEC,
555                                      &error);
556        if (error != NULL) {
557                g_debug ("GdmSessionDirect: %s key not found: %s",
558                         G_KEY_FILE_DESKTOP_KEY_EXEC,
559                         error->message);
560                g_error_free (error);
561                goto out;
562        }
563
564        if (command != NULL) {
565                *command = g_strdup (exec);
566        }
567        ret = TRUE;
568
569out:
570        g_free (exec);
571
572        return ret;
573}
574
575static gboolean
576get_session_command_for_name (const char *name,
577                              char      **command)
578{
579        gboolean res;
580        char    *filename;
581
582        filename = g_strdup_printf ("%s.desktop", name);
583
584        command = NULL;
585        res = get_session_command_for_file (filename, command);
586        g_free (filename);
587
588        return res;
589}
590
591static const char *
592get_default_language_name (GdmSessionDirect *session)
593{
594    if (session->priv->saved_language != NULL) {
595                return session->priv->saved_language;
596    }
597
598    return setlocale (LC_MESSAGES, NULL);
599}
600
601static const char *
602get_default_layout_name (GdmSessionDirect *session)
603{
604    if (session->priv->saved_layout != NULL) {
605                return session->priv->saved_layout;
606    }
607
608    return "us";
609}
610
611static char *
612get_fallback_session_name (void)
613{
614        const char  **search_dirs;
615        int           i;
616        char         *name;
617
618        name = g_strdup ("gnome");
619        if (get_session_command_for_name (name, NULL)) {
620                return name;
621        }
622
623        search_dirs = get_system_session_dirs ();
624        for (i = 0; search_dirs[i] != NULL; i++) {
625                GDir *dir;
626                const char *base_name;
627
628                dir = g_dir_open (search_dirs[i], 0, NULL);
629
630                if (dir == NULL) {
631                        continue;
632                }
633
634                do {
635                        base_name = g_dir_read_name (dir);
636
637                        if (base_name == NULL) {
638                                break;
639                        }
640
641                        if (!g_str_has_suffix (base_name, ".desktop")) {
642                                continue;
643                        }
644
645                        if (get_session_command_for_file (base_name, NULL)) {
646                                g_free (name);
647
648                                name = g_strndup (base_name,
649                                                  strlen (base_name) -
650                                                  strlen (".desktop"));
651                                break;
652                        }
653                } while (base_name != NULL);
654
655                g_dir_close (dir);
656        }
657
658        return name;
659}
660
661static const char *
662get_default_session_name (GdmSessionDirect *session)
663{
664        if (session->priv->saved_session != NULL) {
665                return session->priv->saved_session;
666        }
667
668        return get_fallback_session_name ();
669}
670
671static void
672gdm_session_direct_defaults_changed (GdmSessionDirect *session)
673{
674        _gdm_session_default_language_name_changed (GDM_SESSION (session),
675                                                    get_default_language_name (session));
676        _gdm_session_default_layout_name_changed (GDM_SESSION (session),
677                                                  get_default_layout_name (session));
678        _gdm_session_default_session_name_changed (GDM_SESSION (session),
679                                                   get_default_session_name (session));
680}
681
682static void
683gdm_session_direct_select_user (GdmSession *session,
684                                const char *text)
685{
686        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
687
688        g_debug ("GdmSessionDirect: Setting user: '%s'", text);
689
690        g_free (impl->priv->selected_user);
691        impl->priv->selected_user = g_strdup (text);
692
693        g_free (impl->priv->saved_session);
694        impl->priv->saved_session = NULL;
695
696        g_free (impl->priv->saved_language);
697        impl->priv->saved_language = NULL;
698
699        g_free (impl->priv->saved_layout);
700        impl->priv->saved_layout = NULL;
701}
702
703static DBusHandlerResult
704gdm_session_direct_handle_username_changed (GdmSessionDirect *session,
705                                            DBusConnection   *connection,
706                                            DBusMessage      *message)
707{
708        DBusMessage *reply;
709        DBusError    error;
710        const char  *text;
711
712        dbus_error_init (&error);
713        if (! dbus_message_get_args (message, &error,
714                                     DBUS_TYPE_STRING, &text,
715                                     DBUS_TYPE_INVALID)) {
716                g_warning ("ERROR: %s", error.message);
717        }
718
719        reply = dbus_message_new_method_return (message);
720        dbus_connection_send (connection, reply, NULL);
721        dbus_message_unref (reply);
722
723        g_debug ("GdmSessionDirect: changing username from '%s' to '%s'",
724                 session->priv->selected_user != NULL ? session->priv->selected_user : "<unset>",
725                 (strlen (text)) ? text : "<unset>");
726
727        gdm_session_direct_select_user (GDM_SESSION (session), (strlen (text) > 0) ? g_strdup (text) : NULL);
728
729        _gdm_session_selected_user_changed (GDM_SESSION (session), session->priv->selected_user);
730
731        gdm_session_direct_defaults_changed (session);
732
733        return DBUS_HANDLER_RESULT_HANDLED;
734}
735
736static void
737cancel_pending_query (GdmSessionDirect *session)
738{
739        DBusMessage *reply;
740
741        if (session->priv->message_pending_reply == NULL) {
742                return;
743        }
744
745        g_debug ("GdmSessionDirect: Cancelling pending query");
746
747        reply = dbus_message_new_error (session->priv->message_pending_reply,
748                                        GDM_SESSION_DBUS_ERROR_CANCEL,
749                                        "Operation cancelled");
750        dbus_connection_send (session->priv->worker_connection, reply, NULL);
751        dbus_connection_flush (session->priv->worker_connection);
752
753        dbus_message_unref (reply);
754        dbus_message_unref (session->priv->message_pending_reply);
755        session->priv->message_pending_reply = NULL;
756}
757
758static void
759answer_pending_query (GdmSessionDirect *session,
760                      const char       *answer)
761{
762        DBusMessage    *reply;
763        DBusMessageIter iter;
764
765        g_assert (session->priv->message_pending_reply != NULL);
766
767        reply = dbus_message_new_method_return (session->priv->message_pending_reply);
768        dbus_message_iter_init_append (reply, &iter);
769        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &answer);
770
771        dbus_connection_send (session->priv->worker_connection, reply, NULL);
772        dbus_message_unref (reply);
773
774        dbus_message_unref (session->priv->message_pending_reply);
775        session->priv->message_pending_reply = NULL;
776}
777
778static void
779set_pending_query (GdmSessionDirect *session,
780                   DBusMessage      *message)
781{
782        g_assert (session->priv->message_pending_reply == NULL);
783
784        session->priv->message_pending_reply = dbus_message_ref (message);
785}
786
787static DBusHandlerResult
788gdm_session_direct_handle_info_query (GdmSessionDirect *session,
789                                      DBusConnection   *connection,
790                                      DBusMessage      *message)
791{
792        DBusError    error;
793        const char  *text;
794
795        dbus_error_init (&error);
796        if (! dbus_message_get_args (message, &error,
797                                     DBUS_TYPE_STRING, &text,
798                                     DBUS_TYPE_INVALID)) {
799                g_warning ("ERROR: %s", error.message);
800        }
801
802        set_pending_query (session, message);
803
804        g_debug ("GdmSessionDirect: Emitting 'info-query' signal");
805        _gdm_session_info_query (GDM_SESSION (session), text);
806
807        return DBUS_HANDLER_RESULT_HANDLED;
808}
809
810static DBusHandlerResult
811gdm_session_direct_handle_secret_info_query (GdmSessionDirect *session,
812                                             DBusConnection   *connection,
813                                             DBusMessage      *message)
814{
815        DBusError    error;
816        const char  *text;
817
818        dbus_error_init (&error);
819        if (! dbus_message_get_args (message, &error,
820                                     DBUS_TYPE_STRING, &text,
821                                     DBUS_TYPE_INVALID)) {
822                g_warning ("ERROR: %s", error.message);
823        }
824
825        set_pending_query (session, message);
826
827        g_debug ("GdmSessionDirect: Emitting 'secret-info-query' signal");
828        _gdm_session_secret_info_query (GDM_SESSION (session), text);
829
830        return DBUS_HANDLER_RESULT_HANDLED;
831}
832
833static DBusHandlerResult
834gdm_session_direct_handle_info (GdmSessionDirect *session,
835                                DBusConnection   *connection,
836                                DBusMessage      *message)
837{
838        DBusMessage *reply;
839        DBusError    error;
840        const char  *text;
841
842        dbus_error_init (&error);
843        if (! dbus_message_get_args (message, &error,
844                                     DBUS_TYPE_STRING, &text,
845                                     DBUS_TYPE_INVALID)) {
846                g_warning ("ERROR: %s", error.message);
847        }
848
849        reply = dbus_message_new_method_return (message);
850        dbus_connection_send (connection, reply, NULL);
851        dbus_message_unref (reply);
852
853        g_debug ("GdmSessionDirect: Emitting 'info' signal");
854        _gdm_session_info (GDM_SESSION (session), text);
855
856        return DBUS_HANDLER_RESULT_HANDLED;
857}
858
859static DBusHandlerResult
860gdm_session_direct_handle_cancel_pending_query (GdmSessionDirect *session,
861                                                DBusConnection   *connection,
862                                                DBusMessage      *message)
863{
864        DBusMessage *reply;
865
866        g_debug ("GdmSessionDirect: worker cancelling pending query");
867        cancel_pending_query (session);
868
869        reply = dbus_message_new_method_return (message);
870        dbus_connection_send (connection, reply, NULL);
871        dbus_message_unref (reply);
872
873        return DBUS_HANDLER_RESULT_HANDLED;
874}
875
876static DBusHandlerResult
877gdm_session_direct_handle_problem (GdmSessionDirect *session,
878                                   DBusConnection   *connection,
879                                   DBusMessage      *message)
880{
881        DBusMessage *reply;
882        DBusError    error;
883        const char  *text;
884
885        dbus_error_init (&error);
886        if (! dbus_message_get_args (message, &error,
887                                     DBUS_TYPE_STRING, &text,
888                                     DBUS_TYPE_INVALID)) {
889                g_warning ("ERROR: %s", error.message);
890        }
891
892        reply = dbus_message_new_method_return (message);
893        dbus_connection_send (connection, reply, NULL);
894        dbus_message_unref (reply);
895
896        g_debug ("GdmSessionDirect: Emitting 'problem' signal");
897        _gdm_session_problem (GDM_SESSION (session), text);
898
899        return DBUS_HANDLER_RESULT_HANDLED;
900}
901
902static DBusHandlerResult
903gdm_session_direct_handle_session_started (GdmSessionDirect *session,
904                                           DBusConnection   *connection,
905                                           DBusMessage      *message)
906{
907        DBusMessage *reply;
908        DBusError    error;
909        int          pid;
910
911        pid = 0;
912
913        g_debug ("GdmSessionDirect: Handling SessionStarted");
914
915        dbus_error_init (&error);
916        if (! dbus_message_get_args (message, &error,
917                                     DBUS_TYPE_INT32, &pid,
918                                     DBUS_TYPE_INVALID)) {
919                g_warning ("ERROR: %s", error.message);
920        }
921
922        reply = dbus_message_new_method_return (message);
923        dbus_connection_send (connection, reply, NULL);
924        dbus_message_unref (reply);
925
926        g_debug ("GdmSessionDirect: Emitting 'session-started' signal with pid '%d'",
927                 pid);
928
929        session->priv->session_pid = pid;
930        session->priv->is_running = TRUE;
931
932        _gdm_session_session_started (GDM_SESSION (session), pid);
933
934        return DBUS_HANDLER_RESULT_HANDLED;
935}
936
937static DBusHandlerResult
938gdm_session_direct_handle_start_failed (GdmSessionDirect *session,
939                                        DBusConnection   *connection,
940                                        DBusMessage      *message)
941{
942        DBusMessage *reply;
943        DBusError    error;
944        const char  *text;
945
946        dbus_error_init (&error);
947        if (! dbus_message_get_args (message, &error,
948                                     DBUS_TYPE_STRING, &text,
949                                     DBUS_TYPE_INVALID)) {
950                g_warning ("ERROR: %s", error.message);
951        }
952
953        reply = dbus_message_new_method_return (message);
954        dbus_connection_send (connection, reply, NULL);
955        dbus_message_unref (reply);
956
957        g_debug ("GdmSessionDirect: Emitting 'session-start-failed' signal");
958        _gdm_session_session_start_failed (GDM_SESSION (session), text);
959
960        return DBUS_HANDLER_RESULT_HANDLED;
961}
962
963static DBusHandlerResult
964gdm_session_direct_handle_session_exited (GdmSessionDirect *session,
965                                          DBusConnection   *connection,
966                                          DBusMessage      *message)
967{
968        DBusMessage *reply;
969        DBusError    error;
970        int          code;
971
972        dbus_error_init (&error);
973        if (! dbus_message_get_args (message, &error,
974                                     DBUS_TYPE_INT32, &code,
975                                     DBUS_TYPE_INVALID)) {
976                g_warning ("ERROR: %s", error.message);
977        }
978
979        reply = dbus_message_new_method_return (message);
980        dbus_connection_send (connection, reply, NULL);
981        dbus_message_unref (reply);
982
983        g_debug ("GdmSessionDirect: Emitting 'session-exited' signal with exit code '%d'",
984                 code);
985
986        session->priv->is_running = FALSE;
987        _gdm_session_session_exited (GDM_SESSION (session), code);
988
989        return DBUS_HANDLER_RESULT_HANDLED;
990}
991
992static DBusHandlerResult
993gdm_session_direct_handle_session_died (GdmSessionDirect *session,
994                                        DBusConnection   *connection,
995                                        DBusMessage      *message)
996{
997        DBusMessage *reply;
998        DBusError    error;
999        int          code;
1000
1001        dbus_error_init (&error);
1002        if (! dbus_message_get_args (message, &error,
1003                                     DBUS_TYPE_INT32, &code,
1004                                     DBUS_TYPE_INVALID)) {
1005                g_warning ("ERROR: %s", error.message);
1006        }
1007
1008        reply = dbus_message_new_method_return (message);
1009        dbus_connection_send (connection, reply, NULL);
1010        dbus_message_unref (reply);
1011
1012        g_debug ("GdmSessionDirect: Emitting 'session-died' signal with signal number '%d'",
1013                 code);
1014
1015        session->priv->is_running = FALSE;
1016        _gdm_session_session_died (GDM_SESSION (session), code);
1017
1018        return DBUS_HANDLER_RESULT_HANDLED;
1019}
1020
1021static DBusHandlerResult
1022gdm_session_direct_handle_saved_language_name_read (GdmSessionDirect *session,
1023                                                    DBusConnection   *connection,
1024                                                    DBusMessage      *message)
1025{
1026        DBusMessage *reply;
1027        DBusError    error;
1028        const char  *language_name;
1029
1030        dbus_error_init (&error);
1031        if (! dbus_message_get_args (message, &error,
1032                                     DBUS_TYPE_STRING, &language_name,
1033                                     DBUS_TYPE_INVALID)) {
1034                g_warning ("ERROR: %s", error.message);
1035        }
1036
1037        reply = dbus_message_new_method_return (message);
1038        dbus_connection_send (connection, reply, NULL);
1039        dbus_message_unref (reply);
1040
1041        if (strcmp (language_name,
1042                    get_default_language_name (session)) != 0) {
1043                g_free (session->priv->saved_language);
1044                session->priv->saved_language = g_strdup (language_name);
1045
1046                _gdm_session_default_language_name_changed (GDM_SESSION (session),
1047                                                            language_name);
1048        }
1049
1050
1051        return DBUS_HANDLER_RESULT_HANDLED;
1052}
1053
1054static DBusHandlerResult
1055gdm_session_direct_handle_saved_layout_name_read (GdmSessionDirect *session,
1056                                                  DBusConnection   *connection,
1057                                                  DBusMessage      *message)
1058{
1059        DBusMessage *reply;
1060        DBusError    error;
1061        const char  *layout_name;
1062
1063        dbus_error_init (&error);
1064        if (! dbus_message_get_args (message, &error,
1065                                     DBUS_TYPE_STRING, &layout_name,
1066                                     DBUS_TYPE_INVALID)) {
1067                g_warning ("ERROR: %s", error.message);
1068        }
1069
1070        reply = dbus_message_new_method_return (message);
1071        dbus_connection_send (connection, reply, NULL);
1072        dbus_message_unref (reply);
1073
1074        if (strcmp (layout_name,
1075                    get_default_layout_name (session)) != 0) {
1076                g_free (session->priv->saved_layout);
1077                session->priv->saved_layout = g_strdup (layout_name);
1078
1079                _gdm_session_default_layout_name_changed (GDM_SESSION (session),
1080                                                          layout_name);
1081        }
1082
1083
1084        return DBUS_HANDLER_RESULT_HANDLED;
1085}
1086
1087static DBusHandlerResult
1088gdm_session_direct_handle_saved_session_name_read (GdmSessionDirect *session,
1089                                                   DBusConnection   *connection,
1090                                                   DBusMessage      *message)
1091{
1092        DBusMessage *reply;
1093        DBusError    error;
1094        const char  *session_name;
1095
1096        dbus_error_init (&error);
1097        if (! dbus_message_get_args (message, &error,
1098                                     DBUS_TYPE_STRING, &session_name,
1099                                     DBUS_TYPE_INVALID)) {
1100                g_warning ("ERROR: %s", error.message);
1101        }
1102
1103        reply = dbus_message_new_method_return (message);
1104        dbus_connection_send (connection, reply, NULL);
1105        dbus_message_unref (reply);
1106
1107        if (! get_session_command_for_name (session_name, NULL)) {
1108                /* ignore sessions that don't exist */
1109                g_debug ("GdmSessionDirect: not using invalid .dmrc session: %s", session_name);
1110                g_free (session->priv->saved_session);
1111                session->priv->saved_session = NULL;
1112                goto out;
1113        }
1114
1115        if (strcmp (session_name,
1116                    get_default_session_name (session)) != 0) {
1117                g_free (session->priv->saved_session);
1118                session->priv->saved_session = g_strdup (session_name);
1119
1120                _gdm_session_default_session_name_changed (GDM_SESSION (session),
1121                                                           session_name);
1122        }
1123 out:
1124        return DBUS_HANDLER_RESULT_HANDLED;
1125}
1126
1127static DBusHandlerResult
1128session_worker_message (DBusConnection *connection,
1129                        DBusMessage    *message,
1130                        void           *user_data)
1131{
1132        GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data);
1133
1134        if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "InfoQuery")) {
1135                return gdm_session_direct_handle_info_query (session, connection, message);
1136        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SecretInfoQuery")) {
1137                return gdm_session_direct_handle_secret_info_query (session, connection, message);
1138        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Info")) {
1139                return gdm_session_direct_handle_info (session, connection, message);
1140        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Problem")) {
1141                return gdm_session_direct_handle_problem (session, connection, message);
1142        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "CancelPendingQuery")) {
1143                return gdm_session_direct_handle_cancel_pending_query (session, connection, message);
1144        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupComplete")) {
1145                return gdm_session_direct_handle_setup_complete (session, connection, message);
1146        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SetupFailed")) {
1147                return gdm_session_direct_handle_setup_failed (session, connection, message);
1148        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetComplete")) {
1149                return gdm_session_direct_handle_reset_complete (session, connection, message);
1150        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "ResetFailed")) {
1151                return gdm_session_direct_handle_reset_failed (session, connection, message);
1152        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authenticated")) {
1153                return gdm_session_direct_handle_authenticated (session, connection, message);
1154        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthenticationFailed")) {
1155                return gdm_session_direct_handle_authentication_failed (session, connection, message);
1156        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Authorized")) {
1157                return gdm_session_direct_handle_authorized (session, connection, message);
1158        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AuthorizationFailed")) {
1159                return gdm_session_direct_handle_authorization_failed (session, connection, message);
1160        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "Accredited")) {
1161                return gdm_session_direct_handle_accredited (session, connection, message);
1162        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "AccreditationFailed")) {
1163                return gdm_session_direct_handle_accreditation_failed (session, connection, message);
1164        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "UsernameChanged")) {
1165                return gdm_session_direct_handle_username_changed (session, connection, message);
1166        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionStarted")) {
1167                return gdm_session_direct_handle_session_started (session, connection, message);
1168        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "StartFailed")) {
1169                return gdm_session_direct_handle_start_failed (session, connection, message);
1170        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionExited")) {
1171                return gdm_session_direct_handle_session_exited (session, connection, message);
1172        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SessionDied")) {
1173                return gdm_session_direct_handle_session_died (session, connection, message);
1174        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLanguageNameRead")) {
1175                return gdm_session_direct_handle_saved_language_name_read (session, connection, message);
1176        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedLayoutNameRead")) {
1177                return gdm_session_direct_handle_saved_layout_name_read (session, connection, message);
1178        } else if (dbus_message_is_method_call (message, GDM_SESSION_DBUS_INTERFACE, "SavedSessionNameRead")) {
1179                return gdm_session_direct_handle_saved_session_name_read (session, connection, message);
1180        }
1181
1182        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1183}
1184
1185static DBusHandlerResult
1186do_introspect (DBusConnection *connection,
1187               DBusMessage    *message)
1188{
1189        DBusMessage *reply;
1190        GString     *xml;
1191        char        *xml_string;
1192
1193        g_debug ("GdmSessionDirect: Do introspect");
1194
1195        /* standard header */
1196        xml = g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
1197                            "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
1198                            "<node>\n"
1199                            "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
1200                            "    <method name=\"Introspect\">\n"
1201                            "      <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
1202                            "    </method>\n"
1203                            "  </interface>\n");
1204
1205        /* interface */
1206        xml = g_string_append (xml,
1207                               "  <interface name=\"org.gnome.DisplayManager.Session\">\n"
1208                               "    <method name=\"SetupComplete\">\n"
1209                               "    </method>\n"
1210                               "    <method name=\"SetupFailed\">\n"
1211                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
1212                               "    </method>\n"
1213                               "    <method name=\"ResetComplete\">\n"
1214                               "    </method>\n"
1215                               "    <method name=\"ResetFailed\">\n"
1216                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
1217                               "    </method>\n"
1218                               "    <method name=\"Authenticated\">\n"
1219                               "    </method>\n"
1220                               "    <method name=\"AuthenticationFailed\">\n"
1221                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
1222                               "    </method>\n"
1223                               "    <method name=\"Authorized\">\n"
1224                               "    </method>\n"
1225                               "    <method name=\"AuthorizationFailed\">\n"
1226                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
1227                               "    </method>\n"
1228                               "    <method name=\"Accredited\">\n"
1229                               "    </method>\n"
1230                               "    <method name=\"AccreditationFailed\">\n"
1231                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
1232                               "    </method>\n"
1233                               "    <method name=\"CancelPendingQuery\">\n"
1234                               "    </method>\n"
1235                               "    <method name=\"InfoQuery\">\n"
1236                               "      <arg name=\"query\" direction=\"in\" type=\"s\"/>\n"
1237                               "      <arg name=\"answer\" direction=\"out\" type=\"s\"/>\n"
1238                               "    </method>\n"
1239                               "    <method name=\"SecretInfoQuery\">\n"
1240                               "      <arg name=\"query\" direction=\"in\" type=\"s\"/>\n"
1241                               "      <arg name=\"answer\" direction=\"out\" type=\"s\"/>\n"
1242                               "    </method>\n"
1243                               "    <method name=\"Info\">\n"
1244                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
1245                               "    </method>\n"
1246                               "    <method name=\"Problem\">\n"
1247                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
1248                               "    </method>\n"
1249                               "    <method name=\"UsernameChanged\">\n"
1250                               "      <arg name=\"text\" direction=\"in\" type=\"s\"/>\n"
1251                               "    </method>\n"
1252                               "    <method name=\"StartFailed\">\n"
1253                               "      <arg name=\"message\" direction=\"in\" type=\"s\"/>\n"
1254                               "    </method>\n"
1255                               "    <method name=\"SessionStarted\">\n"
1256                               "      <arg name=\"pid\" direction=\"in\" type=\"i\"/>\n"
1257                               "      <arg name=\"environment\" direction=\"in\" type=\"as\"/>\n"
1258                               "    </method>\n"
1259                               "    <method name=\"SessionExited\">\n"
1260                               "      <arg name=\"code\" direction=\"in\" type=\"i\"/>\n"
1261                               "    </method>\n"
1262                               "    <method name=\"SessionDied\">\n"
1263                               "      <arg name=\"signal\" direction=\"in\" type=\"i\"/>\n"
1264                               "    </method>\n"
1265                               "    <signal name=\"Reset\">\n"
1266                               "    </signal>\n"
1267                               "    <signal name=\"Setup\">\n"
1268                               "      <arg name=\"service_name\" type=\"s\"/>\n"
1269                               "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
1270                               "      <arg name=\"display_device\" type=\"s\"/>\n"
1271                               "      <arg name=\"hostname\" type=\"s\"/>\n"
1272                               "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
1273                               "    </signal>\n"
1274                               "    <signal name=\"SetupForUser\">\n"
1275                               "      <arg name=\"service_name\" type=\"s\"/>\n"
1276                               "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
1277                               "      <arg name=\"display_device\" type=\"s\"/>\n"
1278                               "      <arg name=\"hostname\" type=\"s\"/>\n"
1279                               "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
1280                               "      <arg name=\"username\" type=\"s\"/>\n"
1281                               "    </signal>\n"
1282                               "    <signal name=\"Authenticate\">\n"
1283                               "    </signal>\n"
1284                               "    <signal name=\"Authorize\">\n"
1285                               "    </signal>\n"
1286                               "    <signal name=\"EstablishCredentials\">\n"
1287                               "    </signal>\n"
1288                               "    <signal name=\"RefreshCredentials\">\n"
1289                               "    </signal>\n"
1290                               "    <signal name=\"SetEnvironmentVariable\">\n"
1291                               "      <arg name=\"name\" type=\"s\"/>\n"
1292                               "      <arg name=\"value\" type=\"s\"/>\n"
1293                               "    </signal>\n"
1294                               "    <signal name=\"SetLanguageName\">\n"
1295                               "      <arg name=\"language_name\" type=\"s\"/>\n"
1296                               "    </signal>\n"
1297                               "    <signal name=\"SetSessionName\">\n"
1298                               "      <arg name=\"session_name\" type=\"s\"/>\n"
1299                               "    </signal>\n"
1300                               "    <signal name=\"StartProgram\">\n"
1301                               "      <arg name=\"command\" type=\"s\"/>\n"
1302                               "    </signal>\n"
1303                               "  </interface>\n");
1304
1305        reply = dbus_message_new_method_return (message);
1306
1307        xml = g_string_append (xml, "</node>\n");
1308        xml_string = g_string_free (xml, FALSE);
1309
1310        dbus_message_append_args (reply,
1311                                  DBUS_TYPE_STRING, &xml_string,
1312                                  DBUS_TYPE_INVALID);
1313
1314        g_free (xml_string);
1315
1316        if (reply == NULL) {
1317                g_error ("No memory");
1318        }
1319
1320        if (! dbus_connection_send (connection, reply, NULL)) {
1321                g_error ("No memory");
1322        }
1323
1324        dbus_message_unref (reply);
1325
1326        return DBUS_HANDLER_RESULT_HANDLED;
1327}
1328
1329static DBusHandlerResult
1330session_message_handler (DBusConnection  *connection,
1331                         DBusMessage     *message,
1332                         void            *user_data)
1333{
1334        const char *dbus_destination = dbus_message_get_destination (message);
1335        const char *dbus_path        = dbus_message_get_path (message);
1336        const char *dbus_interface   = dbus_message_get_interface (message);
1337        const char *dbus_member      = dbus_message_get_member (message);
1338
1339        g_debug ("session_message_handler: destination=%s obj_path=%s interface=%s method=%s",
1340                 dbus_destination ? dbus_destination : "(null)",
1341                 dbus_path        ? dbus_path        : "(null)",
1342                 dbus_interface   ? dbus_interface   : "(null)",
1343                 dbus_member      ? dbus_member      : "(null)");
1344
1345        if (dbus_message_is_method_call (message, "org.freedesktop.DBus", "AddMatch")) {
1346                DBusMessage *reply;
1347
1348                reply = dbus_message_new_method_return (message);
1349
1350                if (reply == NULL) {
1351                        g_error ("No memory");
1352                }
1353
1354                if (! dbus_connection_send (connection, reply, NULL)) {
1355                        g_error ("No memory");
1356                }
1357
1358                dbus_message_unref (reply);
1359
1360                return DBUS_HANDLER_RESULT_HANDLED;
1361        } else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
1362                   strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
1363
1364                g_debug ("GdmSessionDirect: Disconnected");
1365
1366                /*dbus_connection_unref (connection);*/
1367
1368                return DBUS_HANDLER_RESULT_HANDLED;
1369        } else if (dbus_message_is_method_call (message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
1370                return do_introspect (connection, message);
1371        } else {
1372                return session_worker_message (connection, message, user_data);
1373        }
1374
1375        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1376}
1377
1378/* Note: Use abstract sockets like dbus does by default on Linux. Abstract
1379 * sockets are only available on Linux.
1380 */
1381static char *
1382generate_address (void)
1383{
1384        char *path;
1385#if defined (__linux__)
1386        int   i;
1387        char  tmp[9];
1388
1389        for (i = 0; i < 8; i++) {
1390                if (g_random_int_range (0, 2) == 0) {
1391                        tmp[i] = g_random_int_range ('a', 'z' + 1);
1392                } else {
1393                        tmp[i] = g_random_int_range ('A', 'Z' + 1);
1394                }
1395        }
1396        tmp[8] = '\0';
1397
1398        path = g_strdup_printf ("unix:abstract=/tmp/gdm-session-%s", tmp);
1399#else
1400        path = g_strdup ("unix:tmpdir=/tmp");
1401#endif
1402
1403        return path;
1404}
1405
1406static void
1407session_unregister_handler (DBusConnection  *connection,
1408                            void            *user_data)
1409{
1410        g_debug ("session_unregister_handler");
1411}
1412
1413static dbus_bool_t
1414allow_user_function (DBusConnection *connection,
1415                     unsigned long   uid,
1416                     void           *data)
1417{
1418        if (0 == uid) {
1419                return TRUE;
1420        }
1421
1422        g_debug ("GdmSessionDirect: User not allowed");
1423
1424        return FALSE;
1425}
1426
1427static void
1428handle_connection (DBusServer      *server,
1429                   DBusConnection  *new_connection,
1430                   void            *user_data)
1431{
1432        GdmSessionDirect *session = GDM_SESSION_DIRECT (user_data);
1433
1434        g_debug ("GdmSessionDirect: Handing new connection");
1435
1436        if (session->priv->worker_connection == NULL) {
1437                DBusObjectPathVTable vtable = { &session_unregister_handler,
1438                                                &session_message_handler,
1439                                                NULL, NULL, NULL, NULL
1440                };
1441
1442                session->priv->worker_connection = new_connection;
1443                dbus_connection_ref (new_connection);
1444                dbus_connection_setup_with_g_main (new_connection, NULL);
1445
1446                g_debug ("GdmSessionDirect: worker connection is %p", new_connection);
1447                dbus_connection_set_exit_on_disconnect (new_connection, FALSE);
1448
1449                dbus_connection_set_unix_user_function (new_connection,
1450                                                        allow_user_function,
1451                                                        session,
1452                                                        NULL);
1453
1454                dbus_connection_register_object_path (new_connection,
1455                                                      GDM_SESSION_DBUS_PATH,
1456                                                      &vtable,
1457                                                      session);
1458
1459                g_debug ("GdmSessionDirect: Emitting opened signal");
1460                _gdm_session_opened (GDM_SESSION (session));
1461        }
1462}
1463
1464static gboolean
1465setup_server (GdmSessionDirect *session)
1466{
1467        DBusError   error;
1468        gboolean    ret;
1469        char       *address;
1470        const char *auth_mechanisms[] = {"EXTERNAL", NULL};
1471
1472        ret = FALSE;
1473
1474        g_debug ("GdmSessionDirect: Creating D-Bus server for session");
1475
1476        address = generate_address ();
1477
1478        dbus_error_init (&error);
1479        session->priv->server = dbus_server_listen (address, &error);
1480        g_free (address);
1481
1482        if (session->priv->server == NULL) {
1483                g_warning ("Cannot create D-BUS server for the session: %s", error.message);
1484                /* FIXME: should probably fail if we can't create the socket */
1485                goto out;
1486        }
1487
1488        dbus_server_setup_with_g_main (session->priv->server, NULL);
1489        dbus_server_set_auth_mechanisms (session->priv->server, auth_mechanisms);
1490        dbus_server_set_new_connection_function (session->priv->server,
1491                                                 handle_connection,
1492                                                 session,
1493                                                 NULL);
1494        ret = TRUE;
1495
1496        g_free (session->priv->server_address);
1497        session->priv->server_address = dbus_server_get_address (session->priv->server);
1498
1499        g_debug ("GdmSessionDirect: D-Bus server listening on %s", session->priv->server_address);
1500
1501 out:
1502
1503        return ret;
1504}
1505
1506static void
1507gdm_session_direct_init (GdmSessionDirect *session)
1508{
1509        session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session,
1510                                                     GDM_TYPE_SESSION_DIRECT,
1511                                                     GdmSessionDirectPrivate);
1512
1513        g_signal_connect (session,
1514                          "authentication-failed",
1515                          G_CALLBACK (on_authentication_failed),
1516                          NULL);
1517        g_signal_connect (session,
1518                          "session-started",
1519                          G_CALLBACK (on_session_started),
1520                          NULL);
1521        g_signal_connect (session,
1522                          "session-start-failed",
1523                          G_CALLBACK (on_session_start_failed),
1524                          NULL);
1525        g_signal_connect (session,
1526                          "session-exited",
1527                          G_CALLBACK (on_session_exited),
1528                          NULL);
1529
1530        session->priv->session_pid = -1;
1531
1532        session->priv->environment = g_hash_table_new_full (g_str_hash,
1533                                                            g_str_equal,
1534                                                            (GDestroyNotify) g_free,
1535                                                            (GDestroyNotify) g_free);
1536
1537        setup_server (session);
1538
1539}
1540
1541static void
1542worker_stopped (GdmSessionWorkerJob *job,
1543                GdmSessionDirect    *session)
1544{
1545        g_debug ("GdmSessionDirect: Worker job stopped");
1546}
1547
1548static void
1549worker_started (GdmSessionWorkerJob *job,
1550                GdmSessionDirect    *session)
1551{
1552        g_debug ("GdmSessionDirect: Worker job started");
1553}
1554
1555static void
1556worker_exited (GdmSessionWorkerJob *job,
1557               int                  code,
1558               GdmSessionDirect    *session)
1559{
1560        g_debug ("GdmSessionDirect: Worker job exited: %d", code);
1561
1562        if (!session->priv->is_authenticated) {
1563                _gdm_session_authentication_failed (GDM_SESSION (session), NULL);
1564        } else if (session->priv->is_running) {
1565                _gdm_session_session_exited (GDM_SESSION (session), code);
1566        }
1567}
1568
1569static void
1570worker_died (GdmSessionWorkerJob *job,
1571             int                  signum,
1572             GdmSessionDirect    *session)
1573{
1574        g_debug ("GdmSessionDirect: Worker job died: %d", signum);
1575
1576        if (!session->priv->is_authenticated) {
1577                _gdm_session_authentication_failed (GDM_SESSION (session), NULL);
1578        } else if (session->priv->is_running) {
1579                _gdm_session_session_died (GDM_SESSION (session), signum);
1580        }
1581}
1582
1583static gboolean
1584start_worker (GdmSessionDirect *session)
1585{
1586        gboolean res;
1587
1588        session->priv->job = gdm_session_worker_job_new ();
1589        gdm_session_worker_job_set_server_address (session->priv->job, session->priv->server_address);
1590        g_signal_connect (session->priv->job,
1591                          "stopped",
1592                          G_CALLBACK (worker_stopped),
1593                          session);
1594        g_signal_connect (session->priv->job,
1595                          "started",
1596                          G_CALLBACK (worker_started),
1597                          session);
1598        g_signal_connect (session->priv->job,
1599                          "exited",
1600                          G_CALLBACK (worker_exited),
1601                          session);
1602        g_signal_connect (session->priv->job,
1603                          "died",
1604                          G_CALLBACK (worker_died),
1605                          session);
1606
1607        res = gdm_session_worker_job_start (session->priv->job);
1608
1609        return res;
1610}
1611
1612static void
1613stop_worker (GdmSessionDirect *session)
1614{
1615        g_signal_handlers_disconnect_by_func (session->priv->job,
1616                                              G_CALLBACK (worker_stopped),
1617                                              session);
1618        g_signal_handlers_disconnect_by_func (session->priv->job,
1619                                              G_CALLBACK (worker_started),
1620                                              session);
1621        g_signal_handlers_disconnect_by_func (session->priv->job,
1622                                              G_CALLBACK (worker_exited),
1623                                              session);
1624        g_signal_handlers_disconnect_by_func (session->priv->job,
1625                                              G_CALLBACK (worker_died),
1626                                              session);
1627
1628        cancel_pending_query (session);
1629
1630        if (session->priv->worker_connection != NULL) {
1631                dbus_connection_close (session->priv->worker_connection);
1632                session->priv->worker_connection = NULL;
1633        }
1634
1635        gdm_session_worker_job_stop (session->priv->job);
1636        g_object_unref (session->priv->job);
1637        session->priv->job = NULL;
1638}
1639
1640static void
1641gdm_session_direct_open (GdmSession *session)
1642{
1643        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
1644
1645        g_return_if_fail (session != NULL);
1646
1647        g_debug ("GdmSessionDirect: Opening session");
1648
1649        start_worker (impl);
1650}
1651
1652static void
1653send_setup (GdmSessionDirect *session,
1654            const char       *service_name)
1655{
1656        DBusMessage    *message;
1657        DBusMessageIter iter;
1658        const char     *display_name;
1659        const char     *display_device;
1660        const char     *display_hostname;
1661        const char     *display_x11_authority_file;
1662
1663        g_assert (service_name != NULL);
1664
1665        if (session->priv->display_name != NULL) {
1666                display_name = session->priv->display_name;
1667        } else {
1668                display_name = "";
1669        }
1670        if (session->priv->display_hostname != NULL) {
1671                display_hostname = session->priv->display_hostname;
1672        } else {
1673                display_hostname = "";
1674        }
1675        if (session->priv->display_device != NULL) {
1676                display_device = session->priv->display_device;
1677        } else {
1678                display_device = "";
1679        }
1680        if (session->priv->display_x11_authority_file != NULL) {
1681                display_x11_authority_file = session->priv->display_x11_authority_file;
1682        } else {
1683                display_x11_authority_file = "";
1684        }
1685
1686        g_debug ("GdmSessionDirect: Beginning setup");
1687
1688        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
1689                                           GDM_SESSION_DBUS_INTERFACE,
1690                                           "Setup");
1691
1692        dbus_message_iter_init_append (message, &iter);
1693        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
1694        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
1695        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
1696        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
1697        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
1698
1699        if (! send_dbus_message (session->priv->worker_connection, message)) {
1700                g_debug ("GdmSessionDirect: Could not send %s signal", "Setup");
1701        }
1702
1703        dbus_message_unref (message);
1704}
1705
1706static void
1707send_setup_for_user (GdmSessionDirect *session,
1708                     const char       *service_name)
1709{
1710        DBusMessage    *message;
1711        DBusMessageIter iter;
1712        const char     *display_name;
1713        const char     *display_device;
1714        const char     *display_hostname;
1715        const char     *display_x11_authority_file;
1716        const char     *selected_user;
1717
1718        g_assert (service_name != NULL);
1719
1720        if (session->priv->display_name != NULL) {
1721                display_name = session->priv->display_name;
1722        } else {
1723                display_name = "";
1724        }
1725        if (session->priv->display_hostname != NULL) {
1726                display_hostname = session->priv->display_hostname;
1727        } else {
1728                display_hostname = "";
1729        }
1730        if (session->priv->display_device != NULL) {
1731                display_device = session->priv->display_device;
1732        } else {
1733                display_device = "";
1734        }
1735        if (session->priv->display_x11_authority_file != NULL) {
1736                display_x11_authority_file = session->priv->display_x11_authority_file;
1737        } else {
1738                display_x11_authority_file = "";
1739        }
1740        if (session->priv->selected_user != NULL) {
1741                selected_user = session->priv->selected_user;
1742        } else {
1743                selected_user = "";
1744        }
1745
1746        g_debug ("GdmSessionDirect: Beginning setup for user %s", session->priv->selected_user);
1747
1748        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
1749                                           GDM_SESSION_DBUS_INTERFACE,
1750                                           "SetupForUser");
1751
1752        dbus_message_iter_init_append (message, &iter);
1753        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
1754        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
1755        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
1756        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
1757        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
1758        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &selected_user);
1759
1760        if (! send_dbus_message (session->priv->worker_connection, message)) {
1761                g_debug ("GdmSessionDirect: Could not send %s signal", "SetupForUser");
1762        }
1763
1764        dbus_message_unref (message);
1765}
1766
1767static void
1768gdm_session_direct_setup (GdmSession *session,
1769                          const char *service_name)
1770{
1771        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
1772
1773        g_return_if_fail (session != NULL);
1774        g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection));
1775
1776        send_setup (impl, service_name);
1777        gdm_session_direct_defaults_changed (impl);
1778}
1779
1780static void
1781gdm_session_direct_setup_for_user (GdmSession *session,
1782                                   const char *service_name,
1783                                   const char *username)
1784{
1785        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
1786
1787        g_return_if_fail (session != NULL);
1788        g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection));
1789        g_return_if_fail (username != NULL);
1790
1791        gdm_session_direct_select_user (session, username);
1792
1793        send_setup_for_user (impl, service_name);
1794        gdm_session_direct_defaults_changed (impl);
1795}
1796
1797static void
1798gdm_session_direct_authenticate (GdmSession *session)
1799{
1800        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
1801
1802        g_return_if_fail (session != NULL);
1803        g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection));
1804
1805        send_dbus_void_signal (impl, "Authenticate");
1806}
1807
1808static void
1809gdm_session_direct_authorize (GdmSession *session)
1810{
1811        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
1812
1813        g_return_if_fail (session != NULL);
1814        g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection));
1815
1816        send_dbus_void_signal (impl, "Authorize");
1817}
1818
1819static void
1820gdm_session_direct_accredit (GdmSession *session,
1821                             int         cred_flag)
1822{
1823        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
1824
1825        g_return_if_fail (session != NULL);
1826        g_return_if_fail (dbus_connection_get_is_connected (impl->priv->worker_connection));
1827
1828        switch (cred_flag) {
1829        case GDM_SESSION_CRED_ESTABLISH:
1830                send_dbus_void_signal (impl, "EstablishCredentials");
1831                break;
1832        case GDM_SESSION_CRED_REFRESH:
1833                send_dbus_void_signal (impl, "RefreshCredentials");
1834                break;
1835        default:
1836                g_assert_not_reached ();
1837        }
1838}
1839
1840static void
1841send_environment_variable (const char       *key,
1842                           const char       *value,
1843                           GdmSessionDirect *session)
1844{
1845        DBusMessage    *message;
1846        DBusMessageIter iter;
1847
1848        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
1849                                           GDM_SESSION_DBUS_INTERFACE,
1850                                           "SetEnvironmentVariable");
1851
1852        dbus_message_iter_init_append (message, &iter);
1853        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1854        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
1855
1856        if (! send_dbus_message (session->priv->worker_connection, message)) {
1857                g_debug ("GdmSessionDirect: Could not send %s signal", "SetEnvironmentVariable");
1858        }
1859
1860        dbus_message_unref (message);
1861}
1862
1863static void
1864send_environment (GdmSessionDirect *session)
1865{
1866
1867        g_hash_table_foreach (session->priv->environment,
1868                              (GHFunc) send_environment_variable,
1869                              session);
1870}
1871
1872static const char *
1873get_language_name (GdmSessionDirect *session)
1874{
1875        if (session->priv->selected_language != NULL) {
1876                return session->priv->selected_language;
1877        }
1878
1879        return get_default_language_name (session);
1880}
1881
1882static const char *
1883get_layout_name (GdmSessionDirect *session)
1884{
1885        if (session->priv->selected_layout != NULL) {
1886                return session->priv->selected_layout;
1887        }
1888
1889        return get_default_layout_name (session);
1890}
1891
1892static const char *
1893get_session_name (GdmSessionDirect *session)
1894{
1895        /* FIXME: test the session names before we use them? */
1896
1897        if (session->priv->selected_session != NULL) {
1898                return session->priv->selected_session;
1899        }
1900
1901        return get_default_session_name (session);
1902}
1903
1904static char *
1905get_session_command (GdmSessionDirect *session)
1906{
1907        gboolean res;
1908        char    *command;
1909        char    *filename;
1910
1911        filename = g_strdup_printf ("%s.desktop", get_session_name (session));
1912
1913        command = NULL;
1914        res = get_session_command_for_file (filename, &command);
1915        if (! res) {
1916                g_critical ("Cannot read specified session file: %s", filename);
1917                g_free (filename);
1918                exit (1);
1919        }
1920        g_free (filename);
1921
1922        return command;
1923}
1924
1925static void
1926gdm_session_direct_set_environment_variable (GdmSessionDirect *session,
1927                                             const char       *key,
1928                                             const char       *value)
1929{
1930        g_return_if_fail (session != NULL);
1931        g_return_if_fail (session != NULL);
1932        g_return_if_fail (key != NULL);
1933        g_return_if_fail (value != NULL);
1934
1935        g_hash_table_replace (session->priv->environment,
1936                              g_strdup (key),
1937                              g_strdup (value));
1938}
1939
1940static void
1941setup_session_environment (GdmSessionDirect *session)
1942{
1943        gdm_session_direct_set_environment_variable (session,
1944                                                     "GDMSESSION",
1945                                                     get_session_name (session));
1946        gdm_session_direct_set_environment_variable (session,
1947                                                     "DESKTOP_SESSION",
1948                                                     get_session_name (session));
1949
1950        gdm_session_direct_set_environment_variable (session,
1951                                                     "LANG",
1952                                                     get_language_name (session));
1953        gdm_session_direct_set_environment_variable (session,
1954                                                     "GDM_LANG",
1955                                                     get_language_name (session));
1956
1957        if (strcmp (get_layout_name (session),
1958                    get_default_layout_name (session)) == 0) {
1959                gdm_session_direct_set_environment_variable (session,
1960                                                             "GDM_KEYBOARD_LAYOUT",
1961                                                             get_layout_name (session));
1962        }
1963
1964        gdm_session_direct_set_environment_variable (session,
1965                                                     "DISPLAY",
1966                                                     session->priv->display_name);
1967
1968        if (session->priv->user_x11_authority_file != NULL) {
1969                gdm_session_direct_set_environment_variable (session,
1970                                                             "XAUTHORITY",
1971                                                             session->priv->user_x11_authority_file);
1972        }
1973
1974        /* FIXME: We do this here and in the session worker.  We should consolidate
1975         * somehow.
1976         */
1977        gdm_session_direct_set_environment_variable (session,
1978                                                     "PATH",
1979                                                     strcmp (BINDIR, "/usr/bin") == 0?
1980                                                     GDM_SESSION_DEFAULT_PATH :
1981                                                     BINDIR ":" GDM_SESSION_DEFAULT_PATH);
1982
1983}
1984
1985static void
1986gdm_session_direct_start_session (GdmSession *session)
1987{
1988        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
1989        char             *command;
1990        char             *program;
1991
1992        g_return_if_fail (session != NULL);
1993        g_return_if_fail (impl->priv->is_running == FALSE);
1994
1995        command = get_session_command (impl);
1996        program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
1997        g_free (command);
1998
1999        setup_session_environment (impl);
2000        send_environment (impl);
2001
2002        send_dbus_string_signal (impl, "StartProgram", program);
2003        g_free (program);
2004}
2005
2006static void
2007gdm_session_direct_close (GdmSession *session)
2008{
2009        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
2010
2011        g_return_if_fail (session != NULL);
2012
2013        g_debug ("GdmSessionDirect: Closing session");
2014
2015        if (impl->priv->job != NULL) {
2016                if (impl->priv->is_running) {
2017                        gdm_session_record_logout (impl->priv->session_pid,
2018                                                   impl->priv->selected_user,
2019                                                   impl->priv->display_hostname,
2020                                                   impl->priv->display_name,
2021                                                   impl->priv->display_device);
2022                }
2023
2024                stop_worker (impl);
2025        }
2026
2027        g_free (impl->priv->selected_user);
2028        impl->priv->selected_user = NULL;
2029
2030        g_free (impl->priv->selected_session);
2031        impl->priv->selected_session = NULL;
2032
2033        g_free (impl->priv->saved_session);
2034        impl->priv->saved_session = NULL;
2035
2036        g_free (impl->priv->selected_language);
2037        impl->priv->selected_language = NULL;
2038
2039        g_free (impl->priv->saved_language);
2040        impl->priv->saved_language = NULL;
2041
2042        g_free (impl->priv->selected_layout);
2043        impl->priv->selected_layout = NULL;
2044
2045        g_free (impl->priv->saved_layout);
2046        impl->priv->saved_layout = NULL;
2047
2048        g_free (impl->priv->user_x11_authority_file);
2049        impl->priv->user_x11_authority_file = NULL;
2050
2051        g_hash_table_remove_all (impl->priv->environment);
2052
2053        impl->priv->session_pid = -1;
2054        impl->priv->is_authenticated = FALSE;
2055        impl->priv->is_running = FALSE;
2056}
2057
2058static void
2059gdm_session_direct_answer_query  (GdmSession *session,
2060                                  const char *text)
2061{
2062        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
2063
2064        g_return_if_fail (session != NULL);
2065
2066        answer_pending_query (impl, text);
2067}
2068
2069static void
2070gdm_session_direct_cancel  (GdmSession *session)
2071{
2072        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
2073
2074        g_return_if_fail (session != NULL);
2075
2076        cancel_pending_query (impl);
2077}
2078
2079char *
2080gdm_session_direct_get_username (GdmSessionDirect *session)
2081{
2082        g_return_val_if_fail (session != NULL, NULL);
2083
2084        return g_strdup (session->priv->selected_user);
2085}
2086
2087static void
2088gdm_session_direct_select_session (GdmSession *session,
2089                                   const char *text)
2090{
2091        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
2092
2093        g_free (impl->priv->selected_session);
2094
2095        if (strcmp (text, "__previous") == 0) {
2096                impl->priv->selected_session = NULL;
2097        } else {
2098                impl->priv->selected_session = g_strdup (text);
2099        }
2100
2101        send_dbus_string_signal (impl, "SetSessionName",
2102                                 get_session_name (impl));
2103}
2104
2105static void
2106gdm_session_direct_select_language (GdmSession *session,
2107                                    const char *text)
2108{
2109        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
2110
2111        g_free (impl->priv->selected_language);
2112
2113        if (strcmp (text, "__previous") == 0) {
2114                impl->priv->selected_language = NULL;
2115        } else {
2116                impl->priv->selected_language = g_strdup (text);
2117        }
2118
2119        send_dbus_string_signal (impl, "SetLanguageName",
2120                                 get_language_name (impl));
2121}
2122
2123static void
2124gdm_session_direct_select_layout (GdmSession *session,
2125                                  const char *text)
2126{
2127        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
2128
2129        g_free (impl->priv->selected_layout);
2130
2131        if (strcmp (text, "__previous") == 0) {
2132                impl->priv->selected_layout = NULL;
2133        } else {
2134                impl->priv->selected_layout = g_strdup (text);
2135        }
2136
2137        send_dbus_string_signal (impl, "SetLayoutName",
2138                                 get_layout_name (impl));
2139}
2140
2141static void
2142_gdm_session_direct_set_display_id (GdmSessionDirect *session,
2143                                    const char       *id)
2144{
2145        g_free (session->priv->display_id);
2146        session->priv->display_id = g_strdup (id);
2147}
2148
2149/* At some point we may want to read these right from
2150 * the slave but for now I don't want the dependency */
2151static void
2152_gdm_session_direct_set_display_name (GdmSessionDirect *session,
2153                                      const char       *name)
2154{
2155        g_free (session->priv->display_name);
2156        session->priv->display_name = g_strdup (name);
2157}
2158
2159static void
2160_gdm_session_direct_set_display_hostname (GdmSessionDirect *session,
2161                                          const char       *name)
2162{
2163        g_free (session->priv->display_hostname);
2164        session->priv->display_hostname = g_strdup (name);
2165}
2166
2167static void
2168_gdm_session_direct_set_display_device (GdmSessionDirect *session,
2169                                        const char       *name)
2170{
2171        g_debug ("GdmSessionDirect: Setting display device: %s", name);
2172        g_free (session->priv->display_device);
2173        session->priv->display_device = g_strdup (name);
2174}
2175
2176static void
2177_gdm_session_direct_set_user_x11_authority_file (GdmSessionDirect *session,
2178                                                 const char       *name)
2179{
2180        g_free (session->priv->user_x11_authority_file);
2181        session->priv->user_x11_authority_file = g_strdup (name);
2182}
2183
2184static void
2185_gdm_session_direct_set_display_x11_authority_file (GdmSessionDirect *session,
2186                                                    const char       *name)
2187{
2188        g_free (session->priv->display_x11_authority_file);
2189        session->priv->display_x11_authority_file = g_strdup (name);
2190}
2191
2192static void
2193_gdm_session_direct_set_display_is_local (GdmSessionDirect *session,
2194                                          gboolean          is)
2195{
2196        session->priv->display_is_local = is;
2197}
2198
2199static void
2200gdm_session_direct_set_property (GObject      *object,
2201                                 guint         prop_id,
2202                                 const GValue *value,
2203                                 GParamSpec   *pspec)
2204{
2205        GdmSessionDirect *self;
2206
2207        self = GDM_SESSION_DIRECT (object);
2208
2209        switch (prop_id) {
2210        case PROP_DISPLAY_ID:
2211                _gdm_session_direct_set_display_id (self, g_value_get_string (value));
2212                break;
2213        case PROP_DISPLAY_NAME:
2214                _gdm_session_direct_set_display_name (self, g_value_get_string (value));
2215                break;
2216        case PROP_DISPLAY_HOSTNAME:
2217                _gdm_session_direct_set_display_hostname (self, g_value_get_string (value));
2218                break;
2219        case PROP_DISPLAY_DEVICE:
2220                _gdm_session_direct_set_display_device (self, g_value_get_string (value));
2221                break;
2222        case PROP_USER_X11_AUTHORITY_FILE:
2223                _gdm_session_direct_set_user_x11_authority_file (self, g_value_get_string (value));
2224                break;
2225        case PROP_DISPLAY_X11_AUTHORITY_FILE:
2226                _gdm_session_direct_set_display_x11_authority_file (self, g_value_get_string (value));
2227                break;
2228        case PROP_DISPLAY_IS_LOCAL:
2229                _gdm_session_direct_set_display_is_local (self, g_value_get_boolean (value));
2230                break;
2231        default:
2232                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2233                break;
2234        }
2235}
2236
2237static void
2238gdm_session_direct_get_property (GObject    *object,
2239                                 guint       prop_id,
2240                                 GValue     *value,
2241                                 GParamSpec *pspec)
2242{
2243        GdmSessionDirect *self;
2244
2245        self = GDM_SESSION_DIRECT (object);
2246
2247        switch (prop_id) {
2248        case PROP_DISPLAY_ID:
2249                g_value_set_string (value, self->priv->display_id);
2250                break;
2251        case PROP_DISPLAY_NAME:
2252                g_value_set_string (value, self->priv->display_name);
2253                break;
2254        case PROP_DISPLAY_HOSTNAME:
2255                g_value_set_string (value, self->priv->display_hostname);
2256                break;
2257        case PROP_DISPLAY_DEVICE:
2258                g_value_set_string (value, self->priv->display_device);
2259                break;
2260        case PROP_USER_X11_AUTHORITY_FILE:
2261                g_value_set_string (value, self->priv->user_x11_authority_file);
2262                break;
2263        case PROP_DISPLAY_X11_AUTHORITY_FILE:
2264                g_value_set_string (value, self->priv->display_x11_authority_file);
2265                break;
2266        case PROP_DISPLAY_IS_LOCAL:
2267                g_value_set_boolean (value, self->priv->display_is_local);
2268                break;
2269        default:
2270                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2271                break;
2272        }
2273}
2274
2275static void
2276gdm_session_direct_dispose (GObject *object)
2277{
2278        GdmSessionDirect *session;
2279
2280        session = GDM_SESSION_DIRECT (object);
2281
2282        g_debug ("GdmSessionDirect: Disposing session");
2283
2284        gdm_session_direct_close (GDM_SESSION (session));
2285
2286        g_free (session->priv->display_id);
2287        session->priv->display_id = NULL;
2288
2289        g_free (session->priv->display_name);
2290        session->priv->display_name = NULL;
2291
2292        g_free (session->priv->display_hostname);
2293        session->priv->display_hostname = NULL;
2294
2295        g_free (session->priv->display_device);
2296        session->priv->display_device = NULL;
2297
2298        g_free (session->priv->display_x11_authority_file);
2299        session->priv->display_x11_authority_file = NULL;
2300
2301        g_free (session->priv->server_address);
2302        session->priv->server_address = NULL;
2303
2304        if (session->priv->server != NULL) {
2305                dbus_server_disconnect (session->priv->server);
2306                dbus_server_unref (session->priv->server);
2307                session->priv->server = NULL;
2308        }
2309
2310        if (session->priv->environment != NULL) {
2311                g_hash_table_destroy (session->priv->environment);
2312                session->priv->environment = NULL;
2313        }
2314
2315        G_OBJECT_CLASS (gdm_session_direct_parent_class)->dispose (object);
2316}
2317
2318static void
2319gdm_session_direct_finalize (GObject *object)
2320{
2321        GdmSessionDirect *session;
2322        GObjectClass     *parent_class;
2323
2324        session = GDM_SESSION_DIRECT (object);
2325
2326        g_free (session->priv->id);
2327
2328        g_free (session->priv->selected_user);
2329        g_free (session->priv->selected_session);
2330        g_free (session->priv->saved_session);
2331        g_free (session->priv->selected_language);
2332        g_free (session->priv->saved_language);
2333        g_free (session->priv->selected_layout);
2334        g_free (session->priv->saved_layout);
2335
2336        parent_class = G_OBJECT_CLASS (gdm_session_direct_parent_class);
2337
2338        if (parent_class->finalize != NULL)
2339                parent_class->finalize (object);
2340}
2341
2342static gboolean
2343register_session (GdmSessionDirect *session)
2344{
2345        GError *error;
2346
2347        error = NULL;
2348        session->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
2349        if (session->priv->connection == NULL) {
2350                if (error != NULL) {
2351                        g_critical ("error getting system bus: %s", error->message);
2352                        g_error_free (error);
2353                }
2354                exit (1);
2355        }
2356
2357        dbus_g_connection_register_g_object (session->priv->connection, session->priv->id, G_OBJECT (session));
2358
2359        return TRUE;
2360}
2361
2362static GObject *
2363gdm_session_direct_constructor (GType                  type,
2364                                guint                  n_construct_properties,
2365                                GObjectConstructParam *construct_properties)
2366{
2367        GdmSessionDirect *session;
2368        gboolean          res;
2369        const char       *id;
2370
2371        session = GDM_SESSION_DIRECT (G_OBJECT_CLASS (gdm_session_direct_parent_class)->constructor (type,
2372                                                                                          n_construct_properties,
2373                                                                                          construct_properties));
2374
2375        /* Always match the session id with the master */
2376        id = NULL;
2377        if (g_str_has_prefix (session->priv->display_id, "/org/gnome/DisplayManager/Display")) {
2378                id = session->priv->display_id + strlen ("/org/gnome/DisplayManager/Display");
2379        }
2380
2381        g_assert (id != NULL);
2382
2383        session->priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Session%s", id);
2384        g_debug ("GdmSessionDirect: Registering %s", session->priv->id);
2385
2386        res = register_session (session);
2387        if (! res) {
2388                g_warning ("Unable to register session with system bus");
2389        }
2390
2391        return G_OBJECT (session);
2392}
2393
2394static void
2395gdm_session_iface_init (GdmSessionIface *iface)
2396{
2397        iface->open = gdm_session_direct_open;
2398        iface->setup = gdm_session_direct_setup;
2399        iface->setup_for_user = gdm_session_direct_setup_for_user;
2400        iface->authenticate = gdm_session_direct_authenticate;
2401        iface->authorize = gdm_session_direct_authorize;
2402        iface->accredit = gdm_session_direct_accredit;
2403        iface->close = gdm_session_direct_close;
2404
2405        iface->cancel = gdm_session_direct_cancel;
2406        iface->start_session = gdm_session_direct_start_session;
2407        iface->answer_query = gdm_session_direct_answer_query;
2408        iface->select_session = gdm_session_direct_select_session;
2409        iface->select_language = gdm_session_direct_select_language;
2410        iface->select_layout = gdm_session_direct_select_layout;
2411        iface->select_user = gdm_session_direct_select_user;
2412}
2413
2414static void
2415gdm_session_direct_class_init (GdmSessionDirectClass *session_class)
2416{
2417        GObjectClass *object_class;
2418
2419        object_class = G_OBJECT_CLASS (session_class);
2420
2421        object_class->get_property = gdm_session_direct_get_property;
2422        object_class->set_property = gdm_session_direct_set_property;
2423        object_class->constructor = gdm_session_direct_constructor;
2424        object_class->dispose = gdm_session_direct_dispose;
2425        object_class->finalize = gdm_session_direct_finalize;
2426
2427        g_type_class_add_private (session_class, sizeof (GdmSessionDirectPrivate));
2428
2429        g_object_class_install_property (object_class,
2430                                         PROP_DISPLAY_ID,
2431                                         g_param_spec_string ("display-id",
2432                                                              "display id",
2433                                                              "display id",
2434                                                              NULL,
2435                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
2436        g_object_class_install_property (object_class,
2437                                         PROP_DISPLAY_NAME,
2438                                         g_param_spec_string ("display-name",
2439                                                              "display name",
2440                                                              "display name",
2441                                                              NULL,
2442                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
2443        g_object_class_install_property (object_class,
2444                                         PROP_DISPLAY_HOSTNAME,
2445                                         g_param_spec_string ("display-hostname",
2446                                                              "display hostname",
2447                                                              "display hostname",
2448                                                              NULL,
2449                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
2450        g_object_class_install_property (object_class,
2451                                         PROP_DISPLAY_IS_LOCAL,
2452                                         g_param_spec_boolean ("display-is-local",
2453                                                               "display is local",
2454                                                               "display is local",
2455                                                               TRUE,
2456                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
2457        g_object_class_install_property (object_class,
2458                                         PROP_DISPLAY_X11_AUTHORITY_FILE,
2459                                         g_param_spec_string ("display-x11-authority-file",
2460                                                              "display x11 authority file",
2461                                                              "display x11 authority file",
2462                                                              NULL,
2463                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
2464        /* not construct only */
2465        g_object_class_install_property (object_class,
2466                                         PROP_USER_X11_AUTHORITY_FILE,
2467                                         g_param_spec_string ("user-x11-authority-file",
2468                                                              "",
2469                                                              "",
2470                                                              NULL,
2471                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
2472        g_object_class_install_property (object_class,
2473                                         PROP_DISPLAY_DEVICE,
2474                                         g_param_spec_string ("display-device",
2475                                                              "display device",
2476                                                              "display device",
2477                                                              NULL,
2478                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
2479
2480
2481        dbus_g_object_type_install_info (GDM_TYPE_SESSION_DIRECT, &dbus_glib_gdm_session_direct_object_info);
2482}
2483
2484GdmSessionDirect *
2485gdm_session_direct_new (const char *display_id,
2486                        const char *display_name,
2487                        const char *display_hostname,
2488                        const char *display_device,
2489                        const char *display_x11_authority_file,
2490                        gboolean    display_is_local)
2491{
2492        GdmSessionDirect *session;
2493
2494        session = g_object_new (GDM_TYPE_SESSION_DIRECT,
2495                                "display-id", display_id,
2496                                "display-name", display_name,
2497                                "display-hostname", display_hostname,
2498                                "display-device", display_device,
2499                                "display-x11-authority-file", display_x11_authority_file,
2500                                "display-is-local", display_is_local,
2501                                NULL);
2502
2503        return session;
2504}
2505
2506gboolean
2507gdm_session_direct_restart (GdmSessionDirect *session,
2508                            GError          **error)
2509{
2510        gboolean ret;
2511
2512        ret = TRUE;
2513        g_debug ("GdmSessionDirect: Request to restart session");
2514
2515        return ret;
2516}
2517
2518gboolean
2519gdm_session_direct_stop (GdmSessionDirect *session,
2520                         GError          **error)
2521{
2522        gboolean ret;
2523
2524        ret = TRUE;
2525
2526        g_debug ("GdmSessionDirect: Request to stop session");
2527
2528        return ret;
2529}
2530
2531gboolean
2532gdm_session_direct_detach (GdmSessionDirect *session,
2533                           GError          **error)
2534{
2535        gboolean ret;
2536
2537        ret = TRUE;
2538
2539        g_debug ("GdmSessionDirect: Request to detach session");
2540
2541        return ret;
2542}
Note: See TracBrowser for help on using the repository browser.