source: proiecte/PPPP/gdm/daemon/gdm-slave.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: 53.5 KB
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21#include "config.h"
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <fcntl.h>
26#include <unistd.h>
27#include <string.h>
28#include <sys/types.h>
29#include <sys/wait.h>
30#include <errno.h>
31#include <pwd.h>
32#include <grp.h>
33#include <signal.h>
34
35#include <glib.h>
36#include <glib/gstdio.h>
37#include <glib/gi18n.h>
38#include <glib-object.h>
39
40#define DBUS_API_SUBJECT_TO_CHANGE
41#include <dbus/dbus-glib.h>
42#include <dbus/dbus-glib-lowlevel.h>
43
44#include <X11/Xlib.h> /* for Display */
45#include <X11/cursorfont.h> /* for watch cursor */
46
47#include "gdm-common.h"
48
49#include "gdm-slave.h"
50#include "gdm-slave-glue.h"
51
52#include "gdm-server.h"
53
54#define GDM_SLAVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SLAVE, GdmSlavePrivate))
55
56#define CK_NAME      "org.freedesktop.ConsoleKit"
57#define CK_PATH      "/org/freedesktop/ConsoleKit"
58#define CK_INTERFACE "org.freedesktop.ConsoleKit"
59
60#define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
61#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
62#define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
63#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
64
65#define GDM_DBUS_NAME              "org.gnome.DisplayManager"
66#define GDM_DBUS_DISPLAY_INTERFACE "org.gnome.DisplayManager.Display"
67
68#define MAX_CONNECT_ATTEMPTS 10
69
70struct GdmSlavePrivate
71{
72        char            *id;
73        GPid             pid;
74        guint            output_watch_id;
75        guint            error_watch_id;
76
77        Display         *server_display;
78
79        /* cached display values */
80        char            *display_id;
81        char            *display_name;
82        int              display_number;
83        char            *display_hostname;
84        gboolean         display_is_local;
85        gboolean         display_is_parented;
86        char            *display_seat_id;
87        char            *display_x11_authority_file;
88        char            *parent_display_name;
89        char            *parent_display_x11_authority_file;
90
91        GArray          *display_x11_cookie;
92
93        DBusGProxy      *display_proxy;
94        DBusGConnection *connection;
95};
96
97enum {
98        PROP_0,
99        PROP_DISPLAY_ID,
100        PROP_DISPLAY_NAME,
101        PROP_DISPLAY_NUMBER,
102        PROP_DISPLAY_HOSTNAME,
103        PROP_DISPLAY_IS_LOCAL,
104        PROP_DISPLAY_SEAT_ID,
105        PROP_DISPLAY_X11_AUTHORITY_FILE
106};
107
108enum {
109        STOPPED,
110        LAST_SIGNAL
111};
112
113static guint signals [LAST_SIGNAL] = { 0, };
114
115static void     gdm_slave_class_init    (GdmSlaveClass *klass);
116static void     gdm_slave_init          (GdmSlave      *slave);
117static void     gdm_slave_finalize      (GObject       *object);
118
119G_DEFINE_ABSTRACT_TYPE (GdmSlave, gdm_slave, G_TYPE_OBJECT)
120
121#define CURSOR_WATCH XC_watch
122
123static void
124gdm_slave_whack_temp_auth_file (GdmSlave *slave)
125{
126#if 0
127        uid_t old;
128
129        old = geteuid ();
130        if (old != 0)
131                seteuid (0);
132        if (d->parent_temp_auth_file != NULL) {
133                VE_IGNORE_EINTR (g_unlink (d->parent_temp_auth_file));
134        }
135        g_free (d->parent_temp_auth_file);
136        d->parent_temp_auth_file = NULL;
137        if (old != 0)
138                seteuid (old);
139#endif
140}
141
142
143static void
144create_temp_auth_file (GdmSlave *slave)
145{
146#if 0
147        if (d->type == TYPE_FLEXI_XNEST &&
148            d->parent_auth_file != NULL) {
149                if (d->parent_temp_auth_file != NULL) {
150                        VE_IGNORE_EINTR (g_unlink (d->parent_temp_auth_file));
151                }
152                g_free (d->parent_temp_auth_file);
153                d->parent_temp_auth_file =
154                        copy_auth_file (d->server_uid,
155                                        gdm_daemon_config_get_gdmuid (),
156                                        d->parent_auth_file);
157        }
158#endif
159}
160
161static void
162listify_hash (const char *key,
163              const char *value,
164              GPtrArray  *env)
165{
166        char *str;
167        str = g_strdup_printf ("%s=%s", key, value);
168        g_debug ("GdmSlave: script environment: %s", str);
169        g_ptr_array_add (env, str);
170}
171
172static GPtrArray *
173get_script_environment (GdmSlave   *slave,
174                        const char *username)
175{
176        GPtrArray     *env;
177        GHashTable    *hash;
178        struct passwd *pwent;
179        char          *x_servers_file;
180        char          *temp;
181
182        env = g_ptr_array_new ();
183
184        /* create a hash table of current environment, then update keys has necessary */
185        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
186
187        /* modify environment here */
188        g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup ("/"));
189        g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup ("/"));
190        g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup ("/bin/sh"));
191
192        if (username != NULL) {
193                g_hash_table_insert (hash, g_strdup ("LOGNAME"),
194                                     g_strdup (username));
195                g_hash_table_insert (hash, g_strdup ("USER"),
196                                     g_strdup (username));
197                g_hash_table_insert (hash, g_strdup ("USERNAME"),
198                                     g_strdup (username));
199
200                pwent = getpwnam (username);
201                if (pwent != NULL) {
202                        if (pwent->pw_dir != NULL && pwent->pw_dir[0] != '\0') {
203                                g_hash_table_insert (hash, g_strdup ("HOME"),
204                                                     g_strdup (pwent->pw_dir));
205                                g_hash_table_insert (hash, g_strdup ("PWD"),
206                                                     g_strdup (pwent->pw_dir));
207                        }
208
209                        g_hash_table_insert (hash, g_strdup ("SHELL"),
210                                             g_strdup (pwent->pw_shell));
211                }
212        }
213
214#if 0
215        if (display_is_parented) {
216                g_hash_table_insert (hash, g_strdup ("GDM_PARENT_DISPLAY"), g_strdup (parent_display_name));
217
218                /*g_hash_table_insert (hash, "GDM_PARENT_XAUTHORITY"), slave->priv->parent_temp_auth_file));*/
219        }
220#endif
221
222        /* some env for use with the Pre and Post scripts */
223        temp = g_strconcat (slave->priv->display_name, ".Xservers", NULL);
224        x_servers_file = g_build_filename (AUTHDIR, temp, NULL);
225        g_free (temp);
226
227        g_hash_table_insert (hash, g_strdup ("X_SERVERS"), x_servers_file);
228
229        if (! slave->priv->display_is_local) {
230                g_hash_table_insert (hash, g_strdup ("REMOTE_HOST"), g_strdup (slave->priv->display_hostname));
231        }
232
233        /* Runs as root */
234        g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (slave->priv->display_x11_authority_file));
235        g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (slave->priv->display_name));
236
237        /*g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE);*/
238
239        g_hash_table_insert (hash, g_strdup ("RUNNING_UNDER_GDM"), g_strdup ("true"));
240
241        g_hash_table_remove (hash, "MAIL");
242
243
244        g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
245        g_hash_table_destroy (hash);
246
247        g_ptr_array_add (env, NULL);
248
249        return env;
250}
251
252gboolean
253gdm_slave_run_script (GdmSlave   *slave,
254                      const char *dir,
255                      const char *login)
256{
257        char      *script;
258        char     **argv;
259        gint       status;
260        GError    *error;
261        GPtrArray *env;
262        gboolean   res;
263        gboolean   ret;
264
265        ret = FALSE;
266
267        g_assert (dir != NULL);
268        g_assert (login != NULL);
269
270        script = g_build_filename (dir, slave->priv->display_name, NULL);
271        g_debug ("GdmSlave: Trying script %s", script);
272        if (! (g_file_test (script, G_FILE_TEST_IS_REGULAR)
273               && g_file_test (script, G_FILE_TEST_IS_EXECUTABLE))) {
274                g_debug ("GdmSlave: script %s not found; skipping", script);
275                g_free (script);
276                script = NULL;
277        }
278
279        if (script == NULL
280            && slave->priv->display_hostname != NULL
281            && slave->priv->display_hostname[0] != '\0') {
282                script = g_build_filename (dir, slave->priv->display_hostname, NULL);
283                g_debug ("GdmSlave: Trying script %s", script);
284                if (! (g_file_test (script, G_FILE_TEST_IS_REGULAR)
285                       && g_file_test (script, G_FILE_TEST_IS_EXECUTABLE))) {
286                        g_debug ("GdmSlave: script %s not found; skipping", script);
287                        g_free (script);
288                        script = NULL;
289                }
290        }
291
292        if (script == NULL) {
293                script = g_build_filename (dir, "Default", NULL);
294                g_debug ("GdmSlave: Trying script %s", script);
295                if (! (g_file_test (script, G_FILE_TEST_IS_REGULAR)
296                       && g_file_test (script, G_FILE_TEST_IS_EXECUTABLE))) {
297                        g_debug ("GdmSlave: script %s not found; skipping", script);
298                        g_free (script);
299                        script = NULL;
300                }
301        }
302
303        if (script == NULL) {
304                g_debug ("GdmSlave: no script found");
305                return TRUE;
306        }
307
308        create_temp_auth_file (slave);
309
310        g_debug ("GdmSlave: Running process: %s", script);
311        error = NULL;
312        if (! g_shell_parse_argv (script, NULL, &argv, &error)) {
313                g_warning ("Could not parse command: %s", error->message);
314                g_error_free (error);
315                goto out;
316        }
317
318        env = get_script_environment (slave, login);
319
320        res = g_spawn_sync (NULL,
321                            argv,
322                            (char **)env->pdata,
323                            G_SPAWN_SEARCH_PATH,
324                            NULL,
325                            NULL,
326                            NULL,
327                            NULL,
328                            &status,
329                            &error);
330
331        g_ptr_array_foreach (env, (GFunc)g_free, NULL);
332        g_ptr_array_free (env, TRUE);
333
334        if (! res) {
335                g_warning ("GdmSlave: Unable to run script: %s", error->message);
336                g_error_free (error);
337        }
338
339        gdm_slave_whack_temp_auth_file (slave);
340
341        if (WIFEXITED (status)) {
342                g_debug ("GdmSlave: Process exit status: %d", WEXITSTATUS (status));
343                ret = WEXITSTATUS (status) != 0;
344        } else {
345                ret = TRUE;
346        }
347
348 out:
349        g_free (script);
350
351        return ret;
352}
353
354void
355gdm_slave_set_busy_cursor (GdmSlave *slave)
356{
357        if (slave->priv->server_display != NULL) {
358                Cursor xcursor;
359
360                xcursor = XCreateFontCursor (slave->priv->server_display, CURSOR_WATCH);
361                XDefineCursor (slave->priv->server_display,
362                               DefaultRootWindow (slave->priv->server_display),
363                               xcursor);
364                XFreeCursor (slave->priv->server_display, xcursor);
365                XSync (slave->priv->server_display, False);
366        }
367}
368
369gboolean
370gdm_slave_connect_to_x11_display (GdmSlave *slave)
371{
372        gboolean ret;
373        sigset_t mask;
374        sigset_t omask;
375
376        ret = FALSE;
377
378        /* We keep our own (windowless) connection (dsp) open to avoid the
379         * X server resetting due to lack of active connections. */
380
381        g_debug ("GdmSlave: Server is ready - opening display %s", slave->priv->display_name);
382
383        g_setenv ("DISPLAY", slave->priv->display_name, TRUE);
384        g_setenv ("XAUTHORITY", slave->priv->display_x11_authority_file, TRUE);
385
386        sigemptyset (&mask);
387        sigaddset (&mask, SIGCHLD);
388        sigprocmask (SIG_BLOCK, &mask, &omask);
389
390        /* Give slave access to the display independent of current hostname */
391        XSetAuthorization ("MIT-MAGIC-COOKIE-1",
392                           strlen ("MIT-MAGIC-COOKIE-1"),
393                           slave->priv->display_x11_cookie->data,
394                           slave->priv->display_x11_cookie->len);
395
396        slave->priv->server_display = XOpenDisplay (slave->priv->display_name);
397
398        sigprocmask (SIG_SETMASK, &omask, NULL);
399
400
401        if (slave->priv->server_display == NULL) {
402                g_warning ("Unable to connect to display %s", slave->priv->display_name);
403                ret = FALSE;
404        } else if (slave->priv->display_is_local) {
405                XHostAddress host_entries[2] = {
406                        { FamilyServerInterpreted },
407                        { FamilyServerInterpreted }
408                };
409                XServerInterpretedAddress si_entries[2];
410
411                g_debug ("GdmSlave: Connected to display %s", slave->priv->display_name);
412                ret = TRUE;
413
414                /* Give programs run by the slave and greeter access to the display
415                 * independent of current hostname
416                 */
417                si_entries[0].type = "localuser";
418                si_entries[0].typelength = strlen ("localuser");
419                si_entries[1].type = "localuser";
420                si_entries[1].typelength = strlen ("localuser");
421
422                si_entries[0].value = "root";
423                si_entries[0].valuelength = strlen ("root");
424                si_entries[1].value = GDM_USERNAME;
425                si_entries[1].valuelength = strlen (GDM_USERNAME);
426
427                host_entries[0].address = (char *) &si_entries[0];
428                host_entries[0].length = sizeof (XServerInterpretedAddress);
429                host_entries[1].address = (char *) &si_entries[1];
430                host_entries[1].length = sizeof (XServerInterpretedAddress);
431
432                XAddHosts (slave->priv->server_display, host_entries,
433                           G_N_ELEMENTS (host_entries));
434        } else {
435                g_debug ("GdmSlave: Connected to display %s", slave->priv->display_name);
436                ret = TRUE;
437        }
438
439        return ret;
440}
441
442static void
443display_proxy_destroyed_cb (DBusGProxy *display_proxy,
444                            GdmSlave   *slave)
445{
446        g_debug ("GdmSlave: Disconnected from display");
447
448        slave->priv->display_proxy = NULL;
449}
450
451static gboolean
452gdm_slave_set_slave_bus_name (GdmSlave *slave)
453{
454        gboolean    res;
455        GError     *error;
456        const char *name;
457
458        name = dbus_bus_get_unique_name (dbus_g_connection_get_connection (slave->priv->connection));
459
460        error = NULL;
461        res = dbus_g_proxy_call (slave->priv->display_proxy,
462                                 "SetSlaveBusName",
463                                 &error,
464                                 G_TYPE_STRING, name,
465                                 G_TYPE_INVALID,
466                                 G_TYPE_INVALID);
467
468        if (! res) {
469                if (error != NULL) {
470                        g_warning ("Failed to set slave bus name on parent: %s", error->message);
471                        g_error_free (error);
472                } else {
473                        g_warning ("Failed to set slave bus name on parent");
474                }
475        }
476
477        return res;
478}
479
480static gboolean
481gdm_slave_real_start (GdmSlave *slave)
482{
483        gboolean res;
484        char    *id;
485        GError  *error;
486
487        g_debug ("GdmSlave: Starting slave");
488
489        g_assert (slave->priv->display_proxy == NULL);
490
491        g_debug ("GdmSlave: Creating proxy for %s", slave->priv->display_id);
492        error = NULL;
493        slave->priv->display_proxy = dbus_g_proxy_new_for_name_owner (slave->priv->connection,
494                                                                      GDM_DBUS_NAME,
495                                                                      slave->priv->display_id,
496                                                                      GDM_DBUS_DISPLAY_INTERFACE,
497                                                                      &error);
498        g_signal_connect (slave->priv->display_proxy,
499                          "destroy",
500                          G_CALLBACK (display_proxy_destroyed_cb),
501                          slave);
502
503        if (slave->priv->display_proxy == NULL) {
504                if (error != NULL) {
505                        g_warning ("Failed to create display proxy %s: %s", slave->priv->display_id, error->message);
506                        g_error_free (error);
507                } else {
508                        g_warning ("Unable to create display proxy");
509                }
510                return FALSE;
511        }
512
513        /* Make sure display ID works */
514        error = NULL;
515        res = dbus_g_proxy_call (slave->priv->display_proxy,
516                                 "GetId",
517                                 &error,
518                                 G_TYPE_INVALID,
519                                 DBUS_TYPE_G_OBJECT_PATH, &id,
520                                 G_TYPE_INVALID);
521        if (! res) {
522                if (error != NULL) {
523                        g_warning ("Failed to get display id %s: %s", slave->priv->display_id, error->message);
524                        g_error_free (error);
525                } else {
526                        g_warning ("Failed to get display id %s", slave->priv->display_id);
527                }
528
529                return FALSE;
530        }
531
532        g_debug ("GdmSlave: Got display id: %s", id);
533
534        if (strcmp (id, slave->priv->display_id) != 0) {
535                g_critical ("Display ID doesn't match");
536                exit (1);
537        }
538
539        gdm_slave_set_slave_bus_name (slave);
540
541        /* cache some values up front */
542        error = NULL;
543        res = dbus_g_proxy_call (slave->priv->display_proxy,
544                                 "IsLocal",
545                                 &error,
546                                 G_TYPE_INVALID,
547                                 G_TYPE_BOOLEAN, &slave->priv->display_is_local,
548                                 G_TYPE_INVALID);
549        if (! res) {
550                if (error != NULL) {
551                        g_warning ("Failed to get value: %s", error->message);
552                        g_error_free (error);
553                } else {
554                        g_warning ("Failed to get value");
555                }
556
557                return FALSE;
558        }
559
560        error = NULL;
561        res = dbus_g_proxy_call (slave->priv->display_proxy,
562                                 "GetX11DisplayName",
563                                 &error,
564                                 G_TYPE_INVALID,
565                                 G_TYPE_STRING, &slave->priv->display_name,
566                                 G_TYPE_INVALID);
567        if (! res) {
568                if (error != NULL) {
569                        g_warning ("Failed to get value: %s", error->message);
570                        g_error_free (error);
571                } else {
572                        g_warning ("Failed to get value");
573                }
574
575                return FALSE;
576        }
577
578        error = NULL;
579        res = dbus_g_proxy_call (slave->priv->display_proxy,
580                                 "GetX11DisplayNumber",
581                                 &error,
582                                 G_TYPE_INVALID,
583                                 G_TYPE_INT, &slave->priv->display_number,
584                                 G_TYPE_INVALID);
585        if (! res) {
586                if (error != NULL) {
587                        g_warning ("Failed to get value: %s", error->message);
588                        g_error_free (error);
589                } else {
590                        g_warning ("Failed to get value");
591                }
592
593                return FALSE;
594        }
595
596        error = NULL;
597        res = dbus_g_proxy_call (slave->priv->display_proxy,
598                                 "GetRemoteHostname",
599                                 &error,
600                                 G_TYPE_INVALID,
601                                 G_TYPE_STRING, &slave->priv->display_hostname,
602                                 G_TYPE_INVALID);
603        if (! res) {
604                if (error != NULL) {
605                        g_warning ("Failed to get value: %s", error->message);
606                        g_error_free (error);
607                } else {
608                        g_warning ("Failed to get value");
609                }
610
611                return FALSE;
612        }
613
614        error = NULL;
615        res = dbus_g_proxy_call (slave->priv->display_proxy,
616                                 "GetX11Cookie",
617                                 &error,
618                                 G_TYPE_INVALID,
619                                 dbus_g_type_get_collection ("GArray", G_TYPE_CHAR),
620                                 &slave->priv->display_x11_cookie,
621                                 G_TYPE_INVALID);
622        if (! res) {
623                if (error != NULL) {
624                        g_warning ("Failed to get value: %s", error->message);
625                        g_error_free (error);
626                } else {
627                        g_warning ("Failed to get value");
628                }
629
630                return FALSE;
631        }
632
633        error = NULL;
634        res = dbus_g_proxy_call (slave->priv->display_proxy,
635                                 "GetX11AuthorityFile",
636                                 &error,
637                                 G_TYPE_INVALID,
638                                 G_TYPE_STRING, &slave->priv->display_x11_authority_file,
639                                 G_TYPE_INVALID);
640        if (! res) {
641                if (error != NULL) {
642                        g_warning ("Failed to get value: %s", error->message);
643                        g_error_free (error);
644                } else {
645                        g_warning ("Failed to get value");
646                }
647
648                return FALSE;
649        }
650
651        error = NULL;
652        res = dbus_g_proxy_call (slave->priv->display_proxy,
653                                 "GetSeatId",
654                                 &error,
655                                 G_TYPE_INVALID,
656                                 G_TYPE_STRING, &slave->priv->display_seat_id,
657                                 G_TYPE_INVALID);
658        if (! res) {
659                if (error != NULL) {
660                        g_warning ("Failed to get value: %s", error->message);
661                        g_error_free (error);
662                } else {
663                        g_warning ("Failed to get value");
664                }
665
666                return FALSE;
667        }
668
669        return TRUE;
670}
671
672static gboolean
673gdm_slave_real_stop (GdmSlave *slave)
674{
675        g_debug ("GdmSlave: Stopping slave");
676
677        if (slave->priv->display_proxy != NULL) {
678                g_object_unref (slave->priv->display_proxy);
679        }
680
681        return TRUE;
682}
683
684gboolean
685gdm_slave_start (GdmSlave *slave)
686{
687        gboolean ret;
688
689        g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
690
691        g_debug ("GdmSlave: starting slave");
692
693        g_object_ref (slave);
694        ret = GDM_SLAVE_GET_CLASS (slave)->start (slave);
695        g_object_unref (slave);
696
697        return ret;
698}
699
700gboolean
701gdm_slave_stop (GdmSlave *slave)
702{
703        gboolean ret;
704
705        g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE);
706
707        g_debug ("GdmSlave: stopping slave");
708
709        g_object_ref (slave);
710        ret = GDM_SLAVE_GET_CLASS (slave)->stop (slave);
711        g_object_unref (slave);
712
713        return ret;
714}
715
716void
717gdm_slave_stopped (GdmSlave *slave)
718{
719        g_return_if_fail (GDM_IS_SLAVE (slave));
720
721        g_signal_emit (slave, signals [STOPPED], 0);
722}
723
724gboolean
725gdm_slave_add_user_authorization (GdmSlave   *slave,
726                                  const char *username,
727                                  char      **filenamep)
728{
729        gboolean res;
730        GError  *error;
731        char    *filename;
732
733        filename = NULL;
734
735        if (filenamep != NULL) {
736                *filenamep = NULL;
737        }
738
739        g_debug ("GdmSlave: Requesting user authorization");
740
741        error = NULL;
742        res = dbus_g_proxy_call (slave->priv->display_proxy,
743                                 "AddUserAuthorization",
744                                 &error,
745                                 G_TYPE_STRING, username,
746                                 G_TYPE_INVALID,
747                                 G_TYPE_STRING, &filename,
748                                 G_TYPE_INVALID);
749
750        if (! res) {
751                if (error != NULL) {
752                        g_warning ("Failed to add user authorization: %s", error->message);
753                        g_error_free (error);
754                } else {
755                        g_warning ("Failed to add user authorization");
756                }
757        } else {
758                g_debug ("GdmSlave: Got user authorization: %s", filename);
759        }
760
761        if (filenamep != NULL) {
762                *filenamep = g_strdup (filename);
763        }
764        g_free (filename);
765
766        return res;
767}
768
769static gchar *
770gdm_slave_parse_enriched_login (GdmSlave *slave,
771                                char *username,
772                                char *display_name)
773{
774        char in_buffer[20];
775        char **argv = NULL;
776        gint pipe1[2], in_buffer_len;
777        int  username_length;
778        pid_t pid;
779
780        if (username == NULL)
781                return (NULL);
782
783        /* A script may be used to generate the automatic/timed login name
784           based on the display/host by ending the name with the pipe symbol
785           '|'. */
786
787        username_length = strlen (username);
788        if (username_length > 0 && username[username_length-1] == '|') {
789                GPtrArray *env;
790                GError    *error;
791                gboolean   res;
792                char     **argv;
793                char      *std_output;
794                char      *std_error;
795
796                /* Remove the pipe symbol */
797                username[username_length-1] = '\0';
798
799                argv = NULL;
800                error = NULL;
801                if (! g_shell_parse_argv (username, NULL, &argv, &error)) {
802                      g_warning ("Could not parse command: %s", error->message);
803                      return (NULL);
804                }
805
806                g_debug ("Calling script %s to acquire auto/timed username",
807                         username);
808
809                env = get_script_environment (slave, NULL);
810                error = NULL;
811                res = g_spawn_sync (NULL,
812                                    argv,
813                                    (char **)env->pdata,
814                                    G_SPAWN_SEARCH_PATH,
815                                    NULL,
816                                    NULL,
817                                    &std_output,
818                                    &std_error,
819                                    NULL,
820                                    &error);
821
822                g_ptr_array_foreach (env, (GFunc)g_free, NULL);
823                g_ptr_array_free (env, TRUE);
824                g_strfreev (argv);
825
826                if (! res) {
827                        g_warning ("Unable to launch auto/timed login script: %s", error->message);
828                        g_error_free (error);
829                } else {
830                        if (std_output != NULL) {
831                                g_strchomp (std_output);
832                                if (std_output[0] != '\0') {
833                                        return (g_strdup (std_output));
834                                }
835                        }
836                        return NULL;
837                }
838        } else {
839                return (g_strdup (username));
840        }
841
842        return NULL;
843}
844
845gboolean
846gdm_slave_get_timed_login_details (GdmSlave   *slave,
847                                   gboolean   *enabledp,
848                                   char      **usernamep,
849                                   int        *delayp)
850{
851        struct passwd *pwent;
852        GError        *error;
853        gboolean       res;
854        gboolean       enabled;
855        char          *username;
856        int            delay;
857
858        username = NULL;
859        enabled = FALSE;
860        delay = 0;
861
862        g_debug ("GdmSlave: Requesting timed login details");
863
864        error = NULL;
865        res = dbus_g_proxy_call (slave->priv->display_proxy,
866                                 "GetTimedLoginDetails",
867                                 &error,
868                                 G_TYPE_INVALID,
869                                 G_TYPE_BOOLEAN, &enabled,
870                                 G_TYPE_STRING, &username,
871                                 G_TYPE_INT, &delay,
872                                 G_TYPE_INVALID);
873
874        if (! res) {
875                if (error != NULL) {
876                        g_warning ("Failed to get timed login details: %s", error->message);
877                        g_error_free (error);
878                } else {
879                        g_warning ("Failed to get timed login details");
880                }
881        } else {
882                g_debug ("GdmSlave: Got timed login details: %d %s %d", enabled, username, delay);
883        }
884
885        if (usernamep != NULL) {
886                *usernamep = gdm_slave_parse_enriched_login (slave,
887                        username, slave->priv->display_name);
888        } else {
889                g_free (username);
890
891                if (enabledp != NULL) {
892                        *enabledp = enabled;
893                }
894                if (delayp != NULL) {
895                        *delayp = delay;
896                }
897                return TRUE;
898        }
899        g_free (username);
900
901        if (usernamep != NULL && *usernamep != NULL) {
902                pwent = getpwnam (*usernamep);
903                if (pwent == NULL) {
904                        g_debug ("Invalid username %s for auto/timed login",
905                                 *usernamep);
906                        g_free (*usernamep);
907                        *usernamep = NULL;
908                } else {
909                        g_debug ("Using username %s for auto/timed login",
910                                 *usernamep);
911
912                        if (enabledp != NULL) {
913                                *enabledp = enabled;
914                        }
915                        if (delayp != NULL) {
916                                *delayp = delay;
917                        }
918               }
919        } else {
920                g_debug ("Invalid NULL username for auto/timed login");
921        }
922
923        return res;
924}
925
926static gboolean
927_get_uid_and_gid_for_user (const char *username,
928                           uid_t      *uid,
929                           gid_t      *gid)
930{
931        struct passwd *passwd_entry;
932
933        g_assert (username != NULL);
934
935        errno = 0;
936        passwd_entry = getpwnam (username);
937
938        if (passwd_entry == NULL) {
939                return FALSE;
940        }
941
942        if (uid != NULL) {
943                *uid = passwd_entry->pw_uid;
944        }
945
946        if (gid != NULL) {
947                *gid = passwd_entry->pw_gid;
948        }
949
950        return TRUE;
951}
952
953static gboolean
954x11_session_is_on_seat (GdmSlave        *slave,
955                        const char      *session_id,
956                        const char      *seat_id)
957{
958        DBusGProxy      *proxy;
959        GError          *error;
960        char            *sid;
961        gboolean         res;
962        gboolean         ret;
963        char            *x11_display_device;
964        char            *x11_display;
965
966        ret = FALSE;
967
968        if (seat_id == NULL || seat_id[0] == '\0' || session_id == NULL || session_id[0] == '\0') {
969                return FALSE;
970        }
971
972        proxy = dbus_g_proxy_new_for_name (slave->priv->connection,
973                                           CK_NAME,
974                                           session_id,
975                                           CK_SESSION_INTERFACE);
976        if (proxy == NULL) {
977                g_warning ("Failed to connect to the ConsoleKit seat object");
978                goto out;
979        }
980
981        sid = NULL;
982        error = NULL;
983        res = dbus_g_proxy_call (proxy,
984                                 "GetSeatId",
985                                 &error,
986                                 G_TYPE_INVALID,
987                                 DBUS_TYPE_G_OBJECT_PATH, &sid,
988                                 G_TYPE_INVALID);
989        if (! res) {
990                g_debug ("Failed to identify the current seat: %s", error->message);
991                g_error_free (error);
992                goto out;
993        }
994
995        if (sid == NULL || sid[0] == '\0' || strcmp (sid, seat_id) != 0) {
996                g_debug ("GdmSlave: session not on current seat: %s", seat_id);
997                goto out;
998        }
999
1000        x11_display = NULL;
1001        error = NULL;
1002        res = dbus_g_proxy_call (proxy,
1003                                 "GetX11Display",
1004                                 &error,
1005                                 G_TYPE_INVALID,
1006                                 G_TYPE_STRING, &x11_display,
1007                                 G_TYPE_INVALID);
1008        if (! res) {
1009                g_error_free (error);
1010                goto out;
1011        }
1012
1013        /* don't try to switch to our own session */
1014        if (x11_display == NULL || x11_display[0] == '\0'
1015            || strcmp (slave->priv->display_name, x11_display) == 0) {
1016                g_free (x11_display);
1017                goto out;
1018        }
1019        g_free (x11_display);
1020
1021        x11_display_device = NULL;
1022        error = NULL;
1023        res = dbus_g_proxy_call (proxy,
1024                                 "GetX11DisplayDevice",
1025                                 &error,
1026                                 G_TYPE_INVALID,
1027                                 G_TYPE_STRING, &x11_display_device,
1028                                 G_TYPE_INVALID);
1029        if (! res) {
1030                g_error_free (error);
1031                goto out;
1032        }
1033
1034        if (x11_display_device == NULL || x11_display_device[0] == '\0') {
1035                g_free (x11_display_device);
1036                goto out;
1037        }
1038        g_free (x11_display_device);
1039
1040        ret = TRUE;
1041
1042 out:
1043        if (proxy != NULL) {
1044                g_object_unref (proxy);
1045        }
1046
1047        return ret;
1048}
1049
1050char *
1051gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
1052                                           const char *username)
1053{
1054        gboolean    res;
1055        gboolean    can_activate_sessions;
1056        GError     *error;
1057        DBusGProxy *manager_proxy;
1058        DBusGProxy *seat_proxy;
1059        GPtrArray  *sessions;
1060        char       *primary_ssid;
1061        int         i;
1062        uid_t       uid;
1063
1064        if (slave->priv->display_seat_id == NULL || slave->priv->display_seat_id[0] == '\0') {
1065                g_debug ("GdmSlave: display seat id is not set; can't switch sessions");
1066                return NULL;
1067        }
1068
1069        manager_proxy = NULL;
1070        primary_ssid = NULL;
1071        sessions = NULL;
1072
1073        g_debug ("GdmSlave: getting proxy for seat: %s", slave->priv->display_seat_id);
1074
1075        seat_proxy = dbus_g_proxy_new_for_name (slave->priv->connection,
1076                                                CK_NAME,
1077                                                slave->priv->display_seat_id,
1078                                                CK_SEAT_INTERFACE);
1079
1080        g_debug ("GdmSlave: checking if seat can activate sessions");
1081
1082        error = NULL;
1083        res = dbus_g_proxy_call (seat_proxy,
1084                                 "CanActivateSessions",
1085                                 &error,
1086                                 G_TYPE_INVALID,
1087                                 G_TYPE_BOOLEAN, &can_activate_sessions,
1088                                 G_TYPE_INVALID);
1089        if (! res) {
1090                g_warning ("unable to determine if seat can activate sessions: %s",
1091                           error->message);
1092                g_error_free (error);
1093                goto out;
1094        }
1095
1096        if (! can_activate_sessions) {
1097                g_debug ("GdmSlave: seat is unable to activate sessions");
1098                goto out;
1099        }
1100
1101        manager_proxy = dbus_g_proxy_new_for_name (slave->priv->connection,
1102                                                   CK_NAME,
1103                                                   CK_MANAGER_PATH,
1104                                                   CK_MANAGER_INTERFACE);
1105
1106        if (! _get_uid_and_gid_for_user (username, &uid, NULL)) {
1107                g_debug ("GdmSlave: unable to determine uid for user: %s", username);
1108                goto out;
1109        }
1110
1111        error = NULL;
1112        res = dbus_g_proxy_call (manager_proxy,
1113                                 "GetSessionsForUnixUser",
1114                                 &error,
1115                                 G_TYPE_UINT, uid,
1116                                 G_TYPE_INVALID,
1117                                 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &sessions,
1118                                 G_TYPE_INVALID);
1119        if (! res) {
1120                g_warning ("unable to determine sessions for user: %s",
1121                           error->message);
1122                g_error_free (error);
1123                goto out;
1124        }
1125
1126        for (i = 0; i < sessions->len; i++) {
1127                char *ssid;
1128
1129                ssid = g_ptr_array_index (sessions, i);
1130
1131                if (x11_session_is_on_seat (slave, ssid, slave->priv->display_seat_id)) {
1132                        primary_ssid = g_strdup (ssid);
1133                        break;
1134                }
1135        }
1136
1137        g_ptr_array_foreach (sessions, (GFunc)g_free, NULL);
1138        g_ptr_array_free (sessions, TRUE);
1139
1140 out:
1141
1142        if (seat_proxy != NULL) {
1143                g_object_unref (seat_proxy);
1144        }
1145        if (manager_proxy != NULL) {
1146                g_object_unref (manager_proxy);
1147        }
1148
1149        return primary_ssid;
1150}
1151
1152static gboolean
1153activate_session_id (GdmSlave   *slave,
1154                     const char *seat_id,
1155                     const char *session_id)
1156{
1157        DBusError    local_error;
1158        DBusMessage *message;
1159        DBusMessage *reply;
1160        gboolean     ret;
1161
1162        ret = FALSE;
1163        reply = NULL;
1164
1165        dbus_error_init (&local_error);
1166        message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit",
1167                                                seat_id,
1168                                                "org.freedesktop.ConsoleKit.Seat",
1169                                                "ActivateSession");
1170        if (message == NULL) {
1171                goto out;
1172        }
1173
1174        if (! dbus_message_append_args (message,
1175                                        DBUS_TYPE_OBJECT_PATH, &session_id,
1176                                        DBUS_TYPE_INVALID)) {
1177                goto out;
1178        }
1179
1180
1181        dbus_error_init (&local_error);
1182        reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (slave->priv->connection),
1183                                                           message,
1184                                                           -1,
1185                                                           &local_error);
1186        if (reply == NULL) {
1187                if (dbus_error_is_set (&local_error)) {
1188                        g_warning ("Unable to activate session: %s", local_error.message);
1189                        dbus_error_free (&local_error);
1190                        goto out;
1191                }
1192        }
1193
1194        ret = TRUE;
1195 out:
1196        if (message != NULL) {
1197                dbus_message_unref (message);
1198        }
1199        if (reply != NULL) {
1200                dbus_message_unref (reply);
1201        }
1202
1203        return ret;
1204}
1205
1206static gboolean
1207session_unlock (GdmSlave   *slave,
1208                const char *ssid)
1209{
1210        DBusError       error;
1211        DBusMessage    *message;
1212        DBusMessage    *reply;
1213
1214        g_debug ("ConsoleKit: Unlocking session %s", ssid);
1215        message = dbus_message_new_method_call (CK_NAME,
1216                                                ssid,
1217                                                CK_SESSION_INTERFACE,
1218                                                "Unlock");
1219        if (message == NULL) {
1220                g_debug ("GdmSlave: ConsoleKit couldn't allocate the D-Bus message");
1221                return FALSE;
1222        }
1223
1224        dbus_error_init (&error);
1225        reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (slave->priv->connection),
1226                                                           message,
1227                                                           -1, &error);
1228        dbus_message_unref (message);
1229        if (reply != NULL) {
1230                dbus_message_unref (reply);
1231        }
1232        dbus_connection_flush (dbus_g_connection_get_connection (slave->priv->connection));
1233
1234        if (dbus_error_is_set (&error)) {
1235                g_debug ("GdmSlave: ConsoleKit %s raised:\n %s\n\n", error.name, error.message);
1236                return FALSE;
1237        }
1238
1239        return TRUE;
1240}
1241
1242gboolean
1243gdm_slave_switch_to_user_session (GdmSlave   *slave,
1244                                  const char *username)
1245{
1246        gboolean    res;
1247        gboolean    ret;
1248        char       *ssid_to_activate;
1249
1250        ret = FALSE;
1251
1252        ssid_to_activate = gdm_slave_get_primary_session_id_for_user (slave, username);
1253        if (ssid_to_activate == NULL) {
1254                g_debug ("GdmSlave: unable to determine session to activate");
1255                goto out;
1256        }
1257
1258        g_debug ("GdmSlave: Activating session: '%s'", ssid_to_activate);
1259
1260        res = activate_session_id (slave, slave->priv->display_seat_id, ssid_to_activate);
1261        if (! res) {
1262                g_debug ("GdmSlave: unable to activate session: %s", ssid_to_activate);
1263                goto out;
1264        }
1265
1266        res = session_unlock (slave, ssid_to_activate);
1267        if (!res) {
1268                /* this isn't fatal */
1269                g_debug ("GdmSlave: unable to unlock session: %s", ssid_to_activate);
1270        }
1271
1272        ret = TRUE;
1273
1274 out:
1275        g_free (ssid_to_activate);
1276
1277        return ret;
1278}
1279
1280static void
1281_gdm_slave_set_display_id (GdmSlave   *slave,
1282                           const char *id)
1283{
1284        g_free (slave->priv->display_id);
1285        slave->priv->display_id = g_strdup (id);
1286}
1287
1288static void
1289_gdm_slave_set_display_name (GdmSlave   *slave,
1290                             const char *name)
1291{
1292        g_free (slave->priv->display_name);
1293        slave->priv->display_name = g_strdup (name);
1294}
1295
1296static void
1297_gdm_slave_set_display_number (GdmSlave   *slave,
1298                               int         number)
1299{
1300        slave->priv->display_number = number;
1301}
1302
1303static void
1304_gdm_slave_set_display_hostname (GdmSlave   *slave,
1305                                 const char *name)
1306{
1307        g_free (slave->priv->display_hostname);
1308        slave->priv->display_hostname = g_strdup (name);
1309}
1310
1311static void
1312_gdm_slave_set_display_x11_authority_file (GdmSlave   *slave,
1313                                           const char *name)
1314{
1315        g_free (slave->priv->display_x11_authority_file);
1316        slave->priv->display_x11_authority_file = g_strdup (name);
1317}
1318
1319static void
1320_gdm_slave_set_display_seat_id (GdmSlave   *slave,
1321                                const char *id)
1322{
1323        g_free (slave->priv->display_seat_id);
1324        slave->priv->display_seat_id = g_strdup (id);
1325}
1326
1327static void
1328_gdm_slave_set_display_is_local (GdmSlave   *slave,
1329                                 gboolean    is)
1330{
1331        slave->priv->display_is_local = is;
1332}
1333
1334static void
1335gdm_slave_set_property (GObject      *object,
1336                        guint         prop_id,
1337                        const GValue *value,
1338                        GParamSpec   *pspec)
1339{
1340        GdmSlave *self;
1341
1342        self = GDM_SLAVE (object);
1343
1344        switch (prop_id) {
1345        case PROP_DISPLAY_ID:
1346                _gdm_slave_set_display_id (self, g_value_get_string (value));
1347                break;
1348        case PROP_DISPLAY_NAME:
1349                _gdm_slave_set_display_name (self, g_value_get_string (value));
1350                break;
1351        case PROP_DISPLAY_NUMBER:
1352                _gdm_slave_set_display_number (self, g_value_get_int (value));
1353                break;
1354        case PROP_DISPLAY_HOSTNAME:
1355                _gdm_slave_set_display_hostname (self, g_value_get_string (value));
1356                break;
1357        case PROP_DISPLAY_SEAT_ID:
1358                _gdm_slave_set_display_seat_id (self, g_value_get_string (value));
1359                break;
1360        case PROP_DISPLAY_X11_AUTHORITY_FILE:
1361                _gdm_slave_set_display_x11_authority_file (self, g_value_get_string (value));
1362                break;
1363        case PROP_DISPLAY_IS_LOCAL:
1364                _gdm_slave_set_display_is_local (self, g_value_get_boolean (value));
1365                break;
1366        default:
1367                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1368                break;
1369        }
1370}
1371
1372static void
1373gdm_slave_get_property (GObject    *object,
1374                        guint       prop_id,
1375                        GValue     *value,
1376                        GParamSpec *pspec)
1377{
1378        GdmSlave *self;
1379
1380        self = GDM_SLAVE (object);
1381
1382        switch (prop_id) {
1383        case PROP_DISPLAY_ID:
1384                g_value_set_string (value, self->priv->display_id);
1385                break;
1386        case PROP_DISPLAY_NAME:
1387                g_value_set_string (value, self->priv->display_name);
1388                break;
1389        case PROP_DISPLAY_NUMBER:
1390                g_value_set_int (value, self->priv->display_number);
1391                break;
1392        case PROP_DISPLAY_HOSTNAME:
1393                g_value_set_string (value, self->priv->display_hostname);
1394                break;
1395        case PROP_DISPLAY_SEAT_ID:
1396                g_value_set_string (value, self->priv->display_seat_id);
1397                break;
1398        case PROP_DISPLAY_X11_AUTHORITY_FILE:
1399                g_value_set_string (value, self->priv->display_x11_authority_file);
1400                break;
1401        case PROP_DISPLAY_IS_LOCAL:
1402                g_value_set_boolean (value, self->priv->display_is_local);
1403                break;
1404        default:
1405                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1406                break;
1407        }
1408}
1409
1410static gboolean
1411register_slave (GdmSlave *slave)
1412{
1413        GError *error;
1414
1415        error = NULL;
1416        slave->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
1417        if (slave->priv->connection == NULL) {
1418                if (error != NULL) {
1419                        g_critical ("error getting system bus: %s", error->message);
1420                        g_error_free (error);
1421                }
1422                exit (1);
1423        }
1424
1425        dbus_g_connection_register_g_object (slave->priv->connection, slave->priv->id, G_OBJECT (slave));
1426
1427        return TRUE;
1428}
1429
1430static GObject *
1431gdm_slave_constructor (GType                  type,
1432                       guint                  n_construct_properties,
1433                       GObjectConstructParam *construct_properties)
1434{
1435        GdmSlave      *slave;
1436        gboolean       res;
1437        const char    *id;
1438
1439        slave = GDM_SLAVE (G_OBJECT_CLASS (gdm_slave_parent_class)->constructor (type,
1440                                                                                 n_construct_properties,
1441                                                                                 construct_properties));
1442        /* Always match the slave id with the master */
1443
1444        id = NULL;
1445        if (g_str_has_prefix (slave->priv->display_id, "/org/gnome/DisplayManager/Display")) {
1446                id = slave->priv->display_id + strlen ("/org/gnome/DisplayManager/Display");
1447        }
1448
1449        g_assert (id != NULL);
1450
1451        slave->priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Slave%s", id);
1452        g_debug ("GdmSlave: Registering %s", slave->priv->id);
1453
1454        res = register_slave (slave);
1455        if (! res) {
1456                g_warning ("Unable to register slave with system bus");
1457        }
1458
1459        return G_OBJECT (slave);
1460}
1461
1462static void
1463gdm_slave_class_init (GdmSlaveClass *klass)
1464{
1465        GObjectClass    *object_class = G_OBJECT_CLASS (klass);
1466
1467        object_class->get_property = gdm_slave_get_property;
1468        object_class->set_property = gdm_slave_set_property;
1469        object_class->constructor = gdm_slave_constructor;
1470        object_class->finalize = gdm_slave_finalize;
1471
1472        klass->start = gdm_slave_real_start;
1473        klass->stop = gdm_slave_real_stop;
1474
1475        g_type_class_add_private (klass, sizeof (GdmSlavePrivate));
1476
1477        g_object_class_install_property (object_class,
1478                                         PROP_DISPLAY_ID,
1479                                         g_param_spec_string ("display-id",
1480                                                              "id",
1481                                                              "id",
1482                                                              NULL,
1483                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1484        g_object_class_install_property (object_class,
1485                                         PROP_DISPLAY_NAME,
1486                                         g_param_spec_string ("display-name",
1487                                                              "display name",
1488                                                              "display name",
1489                                                              NULL,
1490                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1491        g_object_class_install_property (object_class,
1492                                         PROP_DISPLAY_NUMBER,
1493                                         g_param_spec_int ("display-number",
1494                                                           "display number",
1495                                                           "display number",
1496                                                           -1,
1497                                                           G_MAXINT,
1498                                                           -1,
1499                                                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1500        g_object_class_install_property (object_class,
1501                                         PROP_DISPLAY_HOSTNAME,
1502                                         g_param_spec_string ("display-hostname",
1503                                                              "display hostname",
1504                                                              "display hostname",
1505                                                              NULL,
1506                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1507        g_object_class_install_property (object_class,
1508                                         PROP_DISPLAY_SEAT_ID,
1509                                         g_param_spec_string ("display-seat-id",
1510                                                              "",
1511                                                              "",
1512                                                              NULL,
1513                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1514        g_object_class_install_property (object_class,
1515                                         PROP_DISPLAY_X11_AUTHORITY_FILE,
1516                                         g_param_spec_string ("display-x11-authority-file",
1517                                                              "",
1518                                                              "",
1519                                                              NULL,
1520                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1521        g_object_class_install_property (object_class,
1522                                         PROP_DISPLAY_IS_LOCAL,
1523                                         g_param_spec_boolean ("display-is-local",
1524                                                               "display is local",
1525                                                               "display is local",
1526                                                               TRUE,
1527                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1528
1529        signals [STOPPED] =
1530                g_signal_new ("stopped",
1531                              G_TYPE_FROM_CLASS (object_class),
1532                              G_SIGNAL_RUN_LAST,
1533                              G_STRUCT_OFFSET (GdmSlaveClass, stopped),
1534                              NULL,
1535                              NULL,
1536                              g_cclosure_marshal_VOID__VOID,
1537                              G_TYPE_NONE,
1538                              0);
1539
1540        dbus_g_object_type_install_info (GDM_TYPE_SLAVE, &dbus_glib_gdm_slave_object_info);
1541}
1542
1543static void
1544gdm_slave_init (GdmSlave *slave)
1545{
1546
1547        slave->priv = GDM_SLAVE_GET_PRIVATE (slave);
1548
1549        slave->priv->pid = -1;
1550}
1551
1552static void
1553gdm_slave_finalize (GObject *object)
1554{
1555        GdmSlave *slave;
1556
1557        g_return_if_fail (object != NULL);
1558        g_return_if_fail (GDM_IS_SLAVE (object));
1559
1560        slave = GDM_SLAVE (object);
1561
1562        g_return_if_fail (slave->priv != NULL);
1563
1564        gdm_slave_real_stop (slave);
1565
1566        g_free (slave->priv->id);
1567        g_free (slave->priv->display_id);
1568        g_free (slave->priv->display_name);
1569        g_free (slave->priv->display_hostname);
1570        g_free (slave->priv->display_seat_id);
1571        g_free (slave->priv->display_x11_authority_file);
1572        g_free (slave->priv->parent_display_name);
1573        g_free (slave->priv->parent_display_x11_authority_file);
1574        g_array_free (slave->priv->display_x11_cookie, TRUE);
1575
1576        G_OBJECT_CLASS (gdm_slave_parent_class)->finalize (object);
1577}
Note: See TracBrowser for help on using the repository browser.