source: proiecte/PPPP/gdm/daemon/gdm-server.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: 30.8 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 <ctype.h>
32#include <pwd.h>
33#include <grp.h>
34#include <signal.h>
35#include <sys/resource.h>
36
37#include <glib.h>
38#include <glib/gi18n.h>
39#include <glib/gstdio.h>
40#include <glib-object.h>
41
42#include <X11/Xlib.h> /* for Display */
43
44#include "gdm-common.h"
45#include "gdm-signal-handler.h"
46
47#include "gdm-server.h"
48
49extern char **environ;
50
51#define GDM_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SERVER, GdmServerPrivate))
52
53/* These are the servstat values, also used as server
54 * process exit codes */
55#define SERVER_TIMEOUT 2        /* Server didn't start */
56#define SERVER_DEAD 250         /* Server stopped */
57#define SERVER_PENDING 251      /* Server started but not ready for connections yet */
58#define SERVER_RUNNING 252      /* Server running and ready for connections */
59#define SERVER_ABORT 253        /* Server failed badly. Suspending display. */
60
61#define MAX_LOGS 5
62
63struct GdmServerPrivate
64{
65        char    *command;
66        GPid     pid;
67
68        gboolean disable_tcp;
69        int      priority;
70        char    *user_name;
71        char    *session_args;
72
73        char    *log_dir;
74        char    *display_name;
75        char    *display_device;
76        char    *auth_file;
77
78        gboolean is_parented;
79        char    *parent_display_name;
80        char    *parent_auth_file;
81        char    *chosen_hostname;
82
83        guint    child_watch_id;
84};
85
86enum {
87        PROP_0,
88        PROP_DISPLAY_NAME,
89        PROP_DISPLAY_DEVICE,
90        PROP_AUTH_FILE,
91        PROP_IS_PARENTED,
92        PROP_PARENT_DISPLAY_NAME,
93        PROP_PARENT_AUTH_FILE,
94        PROP_CHOSEN_HOSTNAME,
95        PROP_COMMAND,
96        PROP_PRIORITY,
97        PROP_USER_NAME,
98        PROP_SESSION_ARGS,
99        PROP_LOG_DIR,
100        PROP_DISABLE_TCP,
101};
102
103enum {
104        READY,
105        EXITED,
106        DIED,
107        LAST_SIGNAL
108};
109
110static guint signals [LAST_SIGNAL] = { 0, };
111
112static void     gdm_server_class_init   (GdmServerClass *klass);
113static void     gdm_server_init         (GdmServer      *server);
114static void     gdm_server_finalize     (GObject        *object);
115
116G_DEFINE_TYPE (GdmServer, gdm_server, G_TYPE_OBJECT)
117
118static char *
119_gdm_server_query_ck_for_display_device (GdmServer *server)
120{
121        char    *out;
122        char    *command;
123        int      status;
124        gboolean res;
125        GError  *error;
126
127        g_return_val_if_fail (GDM_IS_SERVER (server), NULL);
128
129        error = NULL;
130        command = g_strdup_printf (LIBEXECDIR "/ck-get-x11-display-device --display %s",
131                                   server->priv->display_name);
132
133        g_debug ("GdmServer: Running helper %s", command);
134        out = NULL;
135        res = g_spawn_command_line_sync (command,
136                                         &out,
137                                         NULL,
138                                         &status,
139                                         &error);
140        if (! res) {
141                g_warning ("Could not run helper: %s", error->message);
142                g_error_free (error);
143        } else {
144                out = g_strstrip (out);
145                g_debug ("GdmServer: Got tty: '%s'", out);
146        }
147
148        g_free (command);
149
150        return out;
151}
152
153char *
154gdm_server_get_display_device (GdmServer *server)
155{
156        if (server->priv->display_device == NULL) {
157                server->priv->display_device =
158                    _gdm_server_query_ck_for_display_device (server);
159
160                g_object_notify (G_OBJECT (server), "display-device");
161        }
162
163        return g_strdup (server->priv->display_device);
164}
165
166static gboolean
167emit_ready_idle (GdmServer *server)
168{
169        g_debug ("GdmServer: Got USR1 from X server - emitting READY");
170
171        g_signal_emit (server, signals[READY], 0);
172        return FALSE;
173}
174
175
176static gboolean
177signal_cb (int        signo,
178           GdmServer *server)
179
180{
181        g_idle_add ((GSourceFunc)emit_ready_idle, server);
182
183        return TRUE;
184}
185
186static void
187add_ready_handler (GdmServer *server)
188{
189        GdmSignalHandler *signal_handler;
190
191        signal_handler = gdm_signal_handler_new ();
192        gdm_signal_handler_add (signal_handler,
193                                SIGUSR1,
194                                (GdmSignalHandlerFunc)signal_cb,
195                                server);
196        g_object_unref (signal_handler);
197}
198
199static void
200remove_ready_handler (GdmServer *server)
201{
202        GdmSignalHandler *signal_handler;
203
204        signal_handler = gdm_signal_handler_new ();
205        gdm_signal_handler_remove_func (signal_handler,
206                                        SIGUSR1,
207                                        (GdmSignalHandlerFunc)signal_cb,
208                                        server);
209        g_object_unref (signal_handler);
210}
211
212/* We keep a connection (parent_dsp) open with the parent X server
213 * before running a proxy on it to prevent the X server resetting
214 * as we open and close other connections.
215 * Note that XDMCP servers, by default, reset when the seed X
216 * connection closes whereas usually the X server only quits when
217 * all X connections have closed.
218 */
219#if 0
220static gboolean
221connect_to_parent (GdmServer *server)
222{
223        int maxtries;
224        int openretries;
225
226        g_debug ("GdmServer: Connecting to parent display \'%s\'",
227                   d->parent_disp);
228
229        d->parent_dsp = NULL;
230
231        maxtries = SERVER_IS_XDMCP (d) ? 10 : 2;
232
233        openretries = 0;
234        while (openretries < maxtries &&
235               d->parent_dsp == NULL) {
236                d->parent_dsp = XOpenDisplay (d->parent_disp);
237
238                if G_UNLIKELY (d->parent_dsp == NULL) {
239                        g_debug ("GdmServer: Sleeping %d on a retry", 1+openretries*2);
240                        gdm_sleep_no_signal (1+openretries*2);
241                        openretries++;
242                }
243        }
244
245        if (d->parent_dsp == NULL)
246                gdm_error (_("%s: failed to connect to parent display \'%s\'"),
247                           "gdm_server_start", d->parent_disp);
248
249        return d->parent_dsp != NULL;
250}
251#endif
252
253static gboolean
254gdm_server_resolve_command_line (GdmServer  *server,
255                                 const char *vtarg,
256                                 int        *argcp,
257                                 char     ***argvp)
258{
259        int      argc;
260        char   **argv;
261        int      len;
262        int      i;
263        gboolean gotvtarg = FALSE;
264        gboolean query_in_arglist = FALSE;
265
266        g_shell_parse_argv (server->priv->command, &argc, &argv, NULL);
267
268        for (len = 0; argv != NULL && argv[len] != NULL; len++) {
269                char *arg = argv[len];
270
271                /* HACK! Not to add vt argument to servers that already force
272                 * allocation.  Mostly for backwards compat only */
273                if (strncmp (arg, "vt", 2) == 0 &&
274                    isdigit (arg[2]) &&
275                    (arg[3] == '\0' ||
276                     (isdigit (arg[3]) && arg[4] == '\0')))
277                        gotvtarg = TRUE;
278                if (strcmp (arg, "-query") == 0 ||
279                    strcmp (arg, "-indirect") == 0)
280                        query_in_arglist = TRUE;
281        }
282
283        argv = g_renew (char *, argv, len + 10);
284        /* shift args down one */
285        for (i = len - 1; i >= 1; i--) {
286                argv[i+1] = argv[i];
287        }
288
289        /* server number is the FIRST argument, before any others */
290        argv[1] = g_strdup (server->priv->display_name);
291        len++;
292
293        if (server->priv->auth_file != NULL) {
294                argv[len++] = g_strdup ("-auth");
295                argv[len++] = g_strdup (server->priv->auth_file);
296        }
297
298        if (server->priv->chosen_hostname) {
299                /* run just one session */
300                argv[len++] = g_strdup ("-terminate");
301                argv[len++] = g_strdup ("-query");
302                argv[len++] = g_strdup (server->priv->chosen_hostname);
303                query_in_arglist = TRUE;
304        }
305
306        if (server->priv->disable_tcp && ! query_in_arglist) {
307                argv[len++] = g_strdup ("-nolisten");
308                argv[len++] = g_strdup ("tcp");
309        }
310
311        if (vtarg != NULL && ! gotvtarg) {
312                argv[len++] = g_strdup (vtarg);
313        }
314
315        argv[len++] = NULL;
316
317        *argvp = argv;
318        *argcp = len;
319
320        return TRUE;
321}
322
323static void
324rotate_logs (const char *path,
325             guint       n_copies)
326{
327        int i;
328
329        for (i = n_copies - 1; i > 0; i--) {
330                char *name_n;
331                char *name_n1;
332
333                name_n = g_strdup_printf ("%s.%d", path, i);
334                if (i > 1) {
335                        name_n1 = g_strdup_printf ("%s.%d", path, i - 1);
336                } else {
337                        name_n1 = g_strdup (path);
338                }
339
340                VE_IGNORE_EINTR (g_unlink (name_n));
341                VE_IGNORE_EINTR (g_rename (name_n1, name_n));
342
343                g_free (name_n1);
344                g_free (name_n);
345        }
346
347        VE_IGNORE_EINTR (g_unlink (path));
348}
349
350static void
351change_user (GdmServer *server)
352{
353        struct passwd *pwent;
354
355        if (server->priv->user_name == NULL) {
356                return;
357        }
358
359        pwent = getpwnam (server->priv->user_name);
360        if (pwent == NULL) {
361                g_warning (_("Server was to be spawned by user %s but that user doesn't exist"),
362                           server->priv->user_name);
363                _exit (1);
364        }
365
366        g_debug ("GdmServer: Changing (uid:gid) for child process to (%d:%d)",
367                 pwent->pw_uid,
368                 pwent->pw_gid);
369
370        if (pwent->pw_uid != 0) {
371                if (setgid (pwent->pw_gid) < 0)  {
372                        g_warning (_("Couldn't set groupid to %d"),
373                                   pwent->pw_gid);
374                        _exit (1);
375                }
376
377                if (initgroups (pwent->pw_name, pwent->pw_gid) < 0) {
378                        g_warning (_("initgroups () failed for %s"),
379                                   pwent->pw_name);
380                        _exit (1);
381                }
382
383                if (setuid (pwent->pw_uid) < 0)  {
384                        g_warning (_("Couldn't set userid to %d"),
385                                   (int)pwent->pw_uid);
386                        _exit (1);
387                }
388        } else {
389                gid_t groups[1] = { 0 };
390
391                if (setgid (0) < 0)  {
392                        g_warning (_("Couldn't set groupid to 0"));
393                        /* Don't error out, it's not fatal, if it fails we'll
394                         * just still be */
395                }
396
397                /* this will get rid of any suplementary groups etc... */
398                setgroups (1, groups);
399        }
400}
401
402static void
403server_child_setup (GdmServer *server)
404{
405        int              logfd;
406        struct sigaction ign_signal;
407        sigset_t         mask;
408        char            *log_file;
409        char            *log_path;
410
411        log_file = g_strdup_printf ("%s.log", server->priv->display_name);
412        log_path = g_build_filename (server->priv->log_dir, log_file, NULL);
413        g_free (log_file);
414
415        /* Rotate the X server logs */
416        rotate_logs (log_path, MAX_LOGS);
417
418        /* Log all output from spawned programs to a file */
419        g_debug ("GdmServer: Opening logfile for server %s", log_path);
420
421        VE_IGNORE_EINTR (g_unlink (log_path));
422        VE_IGNORE_EINTR (logfd = open (log_path, O_CREAT|O_APPEND|O_TRUNC|O_WRONLY|O_EXCL, 0644));
423
424        g_free (log_path);
425
426        if (logfd != -1) {
427                VE_IGNORE_EINTR (dup2 (logfd, 1));
428                VE_IGNORE_EINTR (dup2 (logfd, 2));
429                close (logfd);
430        } else {
431                g_warning (_("%s: Could not open logfile for display %s!"),
432                           "gdm_server_spawn",
433                           server->priv->display_name);
434        }
435
436        /* The X server expects USR1/TTIN/TTOU to be SIG_IGN */
437        ign_signal.sa_handler = SIG_IGN;
438        ign_signal.sa_flags = SA_RESTART;
439        sigemptyset (&ign_signal.sa_mask);
440
441        if (sigaction (SIGUSR1, &ign_signal, NULL) < 0) {
442                g_warning (_("%s: Error setting %s to %s"),
443                           "gdm_server_spawn", "USR1", "SIG_IGN");
444                _exit (SERVER_ABORT);
445        }
446
447        if (sigaction (SIGTTIN, &ign_signal, NULL) < 0) {
448                g_warning (_("%s: Error setting %s to %s"),
449                           "gdm_server_spawn", "TTIN", "SIG_IGN");
450                _exit (SERVER_ABORT);
451        }
452
453        if (sigaction (SIGTTOU, &ign_signal, NULL) < 0) {
454                g_warning (_("%s: Error setting %s to %s"),
455                           "gdm_server_spawn", "TTOU", "SIG_IGN");
456                _exit (SERVER_ABORT);
457        }
458
459        /* And HUP and TERM are at SIG_DFL from gdm_unset_signals,
460           we also have an empty mask and all that fun stuff */
461
462        /* unblock signals (especially HUP/TERM/USR1) so that we
463         * can control the X server */
464        sigemptyset (&mask);
465        sigprocmask (SIG_SETMASK, &mask, NULL);
466
467        if (server->priv->priority != 0) {
468                if (setpriority (PRIO_PROCESS, 0, server->priv->priority)) {
469                        g_warning (_("%s: Server priority couldn't be set to %d: %s"),
470                                   "gdm_server_spawn",
471                                   server->priv->priority,
472                                   g_strerror (errno));
473                }
474        }
475
476        setpgid (0, 0);
477
478        change_user (server);
479}
480
481static void
482listify_hash (const char *key,
483              const char *value,
484              GPtrArray  *env)
485{
486        char *str;
487        str = g_strdup_printf ("%s=%s", key, value);
488        g_ptr_array_add (env, str);
489}
490
491static GPtrArray *
492get_server_environment (GdmServer *server)
493{
494        GPtrArray  *env;
495        char      **l;
496        GHashTable *hash;
497
498        env = g_ptr_array_new ();
499
500        /* create a hash table of current environment, then update keys has necessary */
501        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
502        for (l = environ; *l != NULL; l++) {
503                char **str;
504                str = g_strsplit (*l, "=", 2);
505                g_hash_table_insert (hash, str[0], str[1]);
506        }
507
508        /* modify environment here */
509        if (server->priv->is_parented) {
510                if (server->priv->parent_auth_file != NULL) {
511                        g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (server->priv->parent_auth_file));
512                }
513
514                if (server->priv->parent_display_name != NULL) {
515                        g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (server->priv->parent_display_name));
516                }
517        } else {
518                g_hash_table_insert (hash, g_strdup ("DISPLAY="), g_strdup (server->priv->display_name));
519        }
520
521        if (server->priv->user_name != NULL) {
522                struct passwd *pwent;
523
524                pwent = getpwnam (server->priv->user_name);
525
526                if (pwent->pw_dir != NULL
527                    && g_file_test (pwent->pw_dir, G_FILE_TEST_EXISTS)) {
528                        g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup (pwent->pw_dir));
529                } else {
530                        /* Hack */
531                        g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup ("/"));
532                }
533                g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup (pwent->pw_shell));
534                g_hash_table_remove (hash, "MAIL");
535        }
536
537        g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
538        g_hash_table_destroy (hash);
539
540        g_ptr_array_add (env, NULL);
541
542        return env;
543}
544
545static void
546server_add_xserver_args (GdmServer *server,
547                         int       *argc,
548                         char    ***argv)
549{
550        int    count;
551        char **args;
552        int    len;
553        int    i;
554
555        len = *argc;
556        g_shell_parse_argv (server->priv->session_args, &count, &args, NULL);
557        *argv = g_renew (char *, *argv, len + count + 1);
558
559        for (i=0; i < count;i++) {
560                *argv[len++] = g_strdup (args[i]);
561        }
562
563        *argc += count;
564
565        argv[len] = NULL;
566        g_strfreev (args);
567}
568
569static void
570server_child_watch (GPid       pid,
571                    int        status,
572                    GdmServer *server)
573{
574        g_debug ("GdmServer: child (pid:%d) done (%s:%d)",
575                 (int) pid,
576                 WIFEXITED (status) ? "status"
577                 : WIFSIGNALED (status) ? "signal"
578                 : "unknown",
579                 WIFEXITED (status) ? WEXITSTATUS (status)
580                 : WIFSIGNALED (status) ? WTERMSIG (status)
581                 : -1);
582
583        if (WIFEXITED (status)) {
584                int code = WEXITSTATUS (status);
585                g_signal_emit (server, signals [EXITED], 0, code);
586        } else if (WIFSIGNALED (status)) {
587                int num = WTERMSIG (status);
588                g_signal_emit (server, signals [DIED], 0, num);
589        }
590
591        g_spawn_close_pid (server->priv->pid);
592        server->priv->pid = -1;
593}
594
595static gboolean
596gdm_server_spawn (GdmServer  *server,
597                  const char *vtarg)
598{
599        int              argc;
600        gchar          **argv = NULL;
601        GError          *error;
602        GPtrArray       *env;
603        gboolean         ret;
604        char            *freeme;
605
606        ret = FALSE;
607
608        /* Figure out the server command */
609        argv = NULL;
610        argc = 0;
611        gdm_server_resolve_command_line (server,
612                                         vtarg,
613                                         &argc,
614                                         &argv);
615
616        if (server->priv->session_args) {
617                server_add_xserver_args (server, &argc, &argv);
618        }
619
620        if (argv[0] == NULL) {
621                g_warning (_("%s: Empty server command for display %s"),
622                           "gdm_server_spawn",
623                           server->priv->display_name);
624                _exit (SERVER_ABORT);
625        }
626
627        env = get_server_environment (server);
628
629        freeme = g_strjoinv (" ", argv);
630        g_debug ("GdmServer: Starting X server process: %s", freeme);
631        g_free (freeme);
632
633        error = NULL;
634        ret = g_spawn_async_with_pipes (NULL,
635                                        argv,
636                                        (char **)env->pdata,
637                                        G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
638                                        (GSpawnChildSetupFunc)server_child_setup,
639                                        server,
640                                        &server->priv->pid,
641                                        NULL,
642                                        NULL,
643                                        NULL,
644                                        &error);
645
646        if (! ret) {
647                g_warning ("Could not start command '%s': %s",
648                           server->priv->command,
649                           error->message);
650                g_error_free (error);
651        }
652
653        g_strfreev (argv);
654        g_ptr_array_foreach (env, (GFunc)g_free, NULL);
655        g_ptr_array_free (env, TRUE);
656
657        g_debug ("GdmServer: Started X server process %d - waiting for READY", (int)server->priv->pid);
658
659        server->priv->child_watch_id = g_child_watch_add (server->priv->pid,
660                                                          (GChildWatchFunc)server_child_watch,
661                                                          server);
662
663        return ret;
664}
665
666/**
667 * gdm_server_start:
668 * @disp: Pointer to a GdmDisplay structure
669 *
670 * Starts a local X server. Handles retries and fatal errors properly.
671 */
672
673gboolean
674gdm_server_start (GdmServer *server)
675{
676        gboolean res;
677
678        /* fork X server process */
679        res = gdm_server_spawn (server, NULL);
680
681        return res;
682}
683
684static void
685server_died (GdmServer *server)
686{
687        int exit_status;
688
689        g_debug ("GdmServer: Waiting on process %d", server->priv->pid);
690        exit_status = gdm_wait_on_pid (server->priv->pid);
691
692        if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
693                g_debug ("GdmServer: Wait on child process failed");
694        } else {
695                /* exited normally */
696        }
697
698        g_spawn_close_pid (server->priv->pid);
699        server->priv->pid = -1;
700
701        if (server->priv->display_device != NULL) {
702                g_free (server->priv->display_device);
703                server->priv->display_device = NULL;
704                g_object_notify (G_OBJECT (server), "display-device");
705        }
706
707        g_debug ("GdmServer: Server died");
708}
709
710gboolean
711gdm_server_stop (GdmServer *server)
712{
713        int res;
714
715        if (server->priv->pid <= 1) {
716                return TRUE;
717        }
718
719        /* remove watch source before we can wait on child */
720        if (server->priv->child_watch_id > 0) {
721                g_source_remove (server->priv->child_watch_id);
722                server->priv->child_watch_id = 0;
723        }
724
725        g_debug ("GdmServer: Stopping server");
726
727        res = gdm_signal_pid (server->priv->pid, SIGTERM);
728        if (res < 0) {
729        } else {
730                server_died (server);
731        }
732
733        return TRUE;
734}
735
736
737static void
738_gdm_server_set_display_name (GdmServer  *server,
739                              const char *name)
740{
741        g_free (server->priv->display_name);
742        server->priv->display_name = g_strdup (name);
743}
744
745static void
746_gdm_server_set_auth_file (GdmServer  *server,
747                           const char *auth_file)
748{
749        g_free (server->priv->auth_file);
750        server->priv->auth_file = g_strdup (auth_file);
751}
752
753static void
754_gdm_server_set_user_name (GdmServer  *server,
755                           const char *name)
756{
757        g_free (server->priv->user_name);
758        server->priv->user_name = g_strdup (name);
759}
760
761static void
762_gdm_server_set_disable_tcp (GdmServer  *server,
763                             gboolean    disabled)
764{
765        server->priv->disable_tcp = disabled;
766}
767
768static void
769gdm_server_set_property (GObject      *object,
770                         guint         prop_id,
771                         const GValue *value,
772                         GParamSpec   *pspec)
773{
774        GdmServer *self;
775
776        self = GDM_SERVER (object);
777
778        switch (prop_id) {
779        case PROP_DISPLAY_NAME:
780                _gdm_server_set_display_name (self, g_value_get_string (value));
781                break;
782        case PROP_AUTH_FILE:
783                _gdm_server_set_auth_file (self, g_value_get_string (value));
784                break;
785        case PROP_USER_NAME:
786                _gdm_server_set_user_name (self, g_value_get_string (value));
787                break;
788        case PROP_DISABLE_TCP:
789                _gdm_server_set_disable_tcp (self, g_value_get_boolean (value));
790                break;
791        default:
792                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
793                break;
794        }
795}
796
797static void
798gdm_server_get_property (GObject    *object,
799                         guint       prop_id,
800                         GValue     *value,
801                         GParamSpec *pspec)
802{
803        GdmServer *self;
804
805        self = GDM_SERVER (object);
806
807        switch (prop_id) {
808        case PROP_DISPLAY_NAME:
809                g_value_set_string (value, self->priv->display_name);
810                break;
811        case PROP_DISPLAY_DEVICE:
812                g_value_take_string (value,
813                                     gdm_server_get_display_device (self));
814                break;
815        case PROP_AUTH_FILE:
816                g_value_set_string (value, self->priv->auth_file);
817                break;
818        case PROP_USER_NAME:
819                g_value_set_string (value, self->priv->user_name);
820                break;
821        case PROP_DISABLE_TCP:
822                g_value_set_boolean (value, self->priv->disable_tcp);
823                break;
824        default:
825                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
826                break;
827        }
828}
829
830static GObject *
831gdm_server_constructor (GType                  type,
832                        guint                  n_construct_properties,
833                        GObjectConstructParam *construct_properties)
834{
835        GdmServer      *server;
836
837        server = GDM_SERVER (G_OBJECT_CLASS (gdm_server_parent_class)->constructor (type,
838                                                                                    n_construct_properties,
839                                                                                    construct_properties));
840        return G_OBJECT (server);
841}
842
843static void
844gdm_server_class_init (GdmServerClass *klass)
845{
846        GObjectClass    *object_class = G_OBJECT_CLASS (klass);
847
848        object_class->get_property = gdm_server_get_property;
849        object_class->set_property = gdm_server_set_property;
850        object_class->constructor = gdm_server_constructor;
851        object_class->finalize = gdm_server_finalize;
852
853        g_type_class_add_private (klass, sizeof (GdmServerPrivate));
854
855        signals [READY] =
856                g_signal_new ("ready",
857                              G_TYPE_FROM_CLASS (object_class),
858                              G_SIGNAL_RUN_LAST,
859                              G_STRUCT_OFFSET (GdmServerClass, ready),
860                              NULL,
861                              NULL,
862                              g_cclosure_marshal_VOID__VOID,
863                              G_TYPE_NONE,
864                              0);
865        signals [EXITED] =
866                g_signal_new ("exited",
867                              G_OBJECT_CLASS_TYPE (object_class),
868                              G_SIGNAL_RUN_FIRST,
869                              G_STRUCT_OFFSET (GdmServerClass, exited),
870                              NULL,
871                              NULL,
872                              g_cclosure_marshal_VOID__INT,
873                              G_TYPE_NONE,
874                              1,
875                              G_TYPE_INT);
876        signals [DIED] =
877                g_signal_new ("died",
878                              G_OBJECT_CLASS_TYPE (object_class),
879                              G_SIGNAL_RUN_FIRST,
880                              G_STRUCT_OFFSET (GdmServerClass, died),
881                              NULL,
882                              NULL,
883                              g_cclosure_marshal_VOID__INT,
884                              G_TYPE_NONE,
885                              1,
886                              G_TYPE_INT);
887
888        g_object_class_install_property (object_class,
889                                         PROP_DISPLAY_NAME,
890                                         g_param_spec_string ("display-name",
891                                                              "name",
892                                                              "name",
893                                                              NULL,
894                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
895        g_object_class_install_property (object_class,
896                                         PROP_DISPLAY_DEVICE,
897                                         g_param_spec_string ("display-device",
898                                                              "Display Device",
899                                                              "Path to terminal display is running on",
900                                                              NULL,
901                                                              G_PARAM_READABLE));
902        g_object_class_install_property (object_class,
903                                         PROP_AUTH_FILE,
904                                         g_param_spec_string ("auth-file",
905                                                              "Authorization File",
906                                                              "Path to X authorization file",
907                                                              NULL,
908                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
909
910        g_object_class_install_property (object_class,
911                                         PROP_USER_NAME,
912                                         g_param_spec_string ("user-name",
913                                                              "user name",
914                                                              "user name",
915                                                              NULL,
916                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
917        g_object_class_install_property (object_class,
918                                         PROP_DISABLE_TCP,
919                                         g_param_spec_boolean ("disable-tcp",
920                                                               NULL,
921                                                               NULL,
922                                                               TRUE,
923                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
924
925}
926
927static void
928gdm_server_init (GdmServer *server)
929{
930
931        server->priv = GDM_SERVER_GET_PRIVATE (server);
932
933        server->priv->pid = -1;
934        server->priv->command = g_strdup (X_SERVER " -br -verbose");
935        server->priv->log_dir = g_strdup (LOGDIR);
936
937        add_ready_handler (server);
938}
939
940static void
941gdm_server_finalize (GObject *object)
942{
943        GdmServer *server;
944
945        g_return_if_fail (object != NULL);
946        g_return_if_fail (GDM_IS_SERVER (object));
947
948        server = GDM_SERVER (object);
949
950        g_return_if_fail (server->priv != NULL);
951
952        remove_ready_handler (server);
953
954        gdm_server_stop (server);
955
956        G_OBJECT_CLASS (gdm_server_parent_class)->finalize (object);
957}
958
959GdmServer *
960gdm_server_new (const char *display_name,
961                const char *auth_file)
962{
963        GObject *object;
964
965        object = g_object_new (GDM_TYPE_SERVER,
966                               "display-name", display_name,
967                               "auth-file", auth_file,
968                               NULL);
969
970        return GDM_SERVER (object);
971}
Note: See TracBrowser for help on using the repository browser.