source: proiecte/PPPP/gdm/daemon/gdm-welcome-session.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: 46.7 KB
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
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
36#include <glib.h>
37#include <glib/gi18n.h>
38#include <glib/gstdio.h>
39#include <glib-object.h>
40#define DBUS_API_SUBJECT_TO_CHANGE
41#include <dbus/dbus-glib.h>
42#include <dbus/dbus-glib-lowlevel.h>
43
44#include "gdm-common.h"
45#include "ck-connector.h"
46
47#include "gdm-welcome-session.h"
48
49#define DBUS_LAUNCH_COMMAND BINDIR "/dbus-launch --exit-with-session"
50
51#define MAX_LOGS 5
52
53extern char **environ;
54
55#define GDM_WELCOME_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_WELCOME_SESSION, GdmWelcomeSessionPrivate))
56
57struct GdmWelcomeSessionPrivate
58{
59        char           *command;
60        GPid            pid;
61
62        CkConnector    *ckc;
63
64        char           *user_name;
65        char           *group_name;
66
67        char           *x11_display_name;
68        char           *x11_display_device;
69        char           *x11_display_hostname;
70        char           *x11_authority_file;
71        gboolean        x11_display_is_local;
72
73        guint           child_watch_id;
74
75        GPid            dbus_pid;
76        char           *dbus_bus_address;
77        char           *server_dbus_path;
78        char           *server_dbus_interface;
79        char           *server_env_var_name;
80        gboolean        register_ck_session;
81
82        char           *server_address;
83};
84
85enum {
86        PROP_0,
87        PROP_X11_DISPLAY_NAME,
88        PROP_X11_DISPLAY_DEVICE,
89        PROP_X11_DISPLAY_HOSTNAME,
90        PROP_X11_AUTHORITY_FILE,
91        PROP_X11_DISPLAY_IS_LOCAL,
92        PROP_USER_NAME,
93        PROP_GROUP_NAME,
94        PROP_SERVER_ADDRESS,
95        PROP_COMMAND,
96        PROP_SERVER_DBUS_PATH,
97        PROP_SERVER_DBUS_INTERFACE,
98        PROP_SERVER_ENV_VAR_NAME,
99        PROP_REGISTER_CK_SESSION,
100};
101
102enum {
103        STARTED,
104        STOPPED,
105        EXITED,
106        DIED,
107        LAST_SIGNAL
108};
109
110static guint signals [LAST_SIGNAL] = { 0, };
111
112static void     gdm_welcome_session_class_init    (GdmWelcomeSessionClass *klass);
113static void     gdm_welcome_session_init          (GdmWelcomeSession      *welcome_session);
114static void     gdm_welcome_session_finalize      (GObject                *object);
115
116G_DEFINE_ABSTRACT_TYPE (GdmWelcomeSession, gdm_welcome_session, G_TYPE_OBJECT)
117
118static void
119listify_hash (const char *key,
120              const char *value,
121              GPtrArray  *env)
122{
123        char *str;
124        str = g_strdup_printf ("%s=%s", key, value);
125        g_debug ("GdmWelcomeSession: welcome environment: %s", str);
126        g_ptr_array_add (env, str);
127}
128
129static gboolean
130open_welcome_session (GdmWelcomeSession *welcome_session)
131{
132        struct passwd *pwent;
133        const char    *session_type;
134        const char    *hostname;
135        const char    *x11_display_device;
136        int            res;
137        gboolean       ret;
138        DBusError      error;
139
140        ret = FALSE;
141
142        g_debug ("GdmWelcomeSession: Registering session with ConsoleKit");
143
144        session_type = "LoginWindow";
145
146        pwent = getpwnam (welcome_session->priv->user_name);
147        if (pwent == NULL) {
148                /* FIXME: */
149                g_warning ("Couldn't look up uid");
150                goto out;
151        }
152
153        welcome_session->priv->ckc = ck_connector_new ();
154        if (welcome_session->priv->ckc == NULL) {
155                g_warning ("Couldn't create new ConsoleKit connector");
156                goto out;
157        }
158
159        if (welcome_session->priv->x11_display_hostname != NULL) {
160                hostname = welcome_session->priv->x11_display_hostname;
161        } else {
162                hostname = "";
163        }
164
165        if (welcome_session->priv->x11_display_device != NULL) {
166                x11_display_device = welcome_session->priv->x11_display_device;
167        } else {
168                x11_display_device = "";
169        }
170
171        g_debug ("GdmWelcomeSession: Opening ConsoleKit session for user:%d x11-display:'%s' x11-display-device:'%s' remote-host-name:'%s' is-local:%d",
172                 pwent->pw_uid,
173                 welcome_session->priv->x11_display_name,
174                 x11_display_device,
175                 hostname,
176                 welcome_session->priv->x11_display_is_local);
177
178        dbus_error_init (&error);
179        res = ck_connector_open_session_with_parameters (welcome_session->priv->ckc,
180                                                         &error,
181                                                         "unix-user", &pwent->pw_uid,
182                                                         "session-type", &session_type,
183                                                         "x11-display", &welcome_session->priv->x11_display_name,
184                                                         "x11-display-device", &x11_display_device,
185                                                         "remote-host-name", &hostname,
186                                                         "is-local", &welcome_session->priv->x11_display_is_local,
187                                                         NULL);
188        if (! res) {
189                if (dbus_error_is_set (&error)) {
190                        g_warning ("%s\n", error.message);
191                        dbus_error_free (&error);
192                } else {
193                        g_warning ("cannot open CK session: OOM, D-Bus system bus not available,\n"
194                                   "ConsoleKit not available or insufficient privileges.\n");
195                }
196                goto out;
197        }
198
199        ret = TRUE;
200
201 out:
202        return ret;
203}
204
205static gboolean
206close_welcome_session (GdmWelcomeSession *welcome_session)
207{
208        int       res;
209        gboolean  ret;
210        DBusError error;
211
212        ret = FALSE;
213
214        if (welcome_session->priv->ckc == NULL) {
215                return FALSE;
216        }
217
218        g_debug ("GdmWelcomeSession: De-registering session from ConsoleKit");
219
220        dbus_error_init (&error);
221        res = ck_connector_close_session (welcome_session->priv->ckc, &error);
222        if (! res) {
223                if (dbus_error_is_set (&error)) {
224                        g_warning ("%s\n", error.message);
225                        dbus_error_free (&error);
226                } else {
227                        g_warning ("cannot open CK session: OOM, D-Bus system bus not available,\n"
228                                   "ConsoleKit not available or insufficient privileges.\n");
229                }
230                goto out;
231        }
232
233        ret = TRUE;
234 out:
235
236        return ret;
237}
238
239static GPtrArray *
240get_welcome_environment (GdmWelcomeSession *welcome_session)
241{
242        GPtrArray     *env;
243        GHashTable    *hash;
244        struct passwd *pwent;
245        static const char * const optional_environment[] = {
246                "LANG", "LANGUAGE", "LC_CTYPE", "LC_NUMERIC", "LC_TIME",
247                "LC_COLLATE", "LC_MONETARY", "LC_MESSAGES", "LC_PAPER",
248                "LC_NAME", "LC_ADDRESS", "LC_TELEPHONE", "LC_MEASUREMENT",
249                "LC_IDENTIFICATION", "LC_ALL",
250                NULL
251        };
252        int i;
253
254        env = g_ptr_array_new ();
255
256        /* create a hash table of current environment, then update keys has necessary */
257        hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
258
259        for (i = 0; optional_environment[i] != NULL; i++) {
260                if (g_getenv (optional_environment[i]) == NULL) {
261                        continue;
262                }
263
264                g_hash_table_insert (hash,
265                                     g_strdup (optional_environment[i]),
266                                     g_strdup (g_getenv (optional_environment[i])));
267        }
268
269        if (welcome_session->priv->dbus_bus_address != NULL) {
270                g_hash_table_insert (hash,
271                                     g_strdup ("DBUS_SESSION_BUS_ADDRESS"),
272                                     g_strdup (welcome_session->priv->dbus_bus_address));
273        }
274        if (welcome_session->priv->server_address != NULL) {
275                g_assert (welcome_session->priv->server_env_var_name != NULL);
276                g_hash_table_insert (hash,
277                                     g_strdup (welcome_session->priv->server_env_var_name),
278                                     g_strdup (welcome_session->priv->server_address));
279        }
280
281        g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (welcome_session->priv->x11_authority_file));
282        g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (welcome_session->priv->x11_display_name));
283
284#if 0
285        /* hackish ain't it */
286        set_xnest_parent_stuff ();
287#endif
288
289        if (welcome_session->priv->ckc != NULL) {
290                const char *cookie;
291                cookie = ck_connector_get_cookie (welcome_session->priv->ckc);
292                if (cookie != NULL) {
293                        g_hash_table_insert (hash, g_strdup ("XDG_SESSION_COOKIE"), g_strdup (cookie));
294                }
295        }
296
297        g_hash_table_insert (hash, g_strdup ("LOGNAME"), g_strdup (welcome_session->priv->user_name));
298        g_hash_table_insert (hash, g_strdup ("USER"), g_strdup (welcome_session->priv->user_name));
299        g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (welcome_session->priv->user_name));
300
301        g_hash_table_insert (hash, g_strdup ("GDM_VERSION"), g_strdup (VERSION));
302        g_hash_table_remove (hash, "MAIL");
303
304        g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup ("/"));
305        g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup ("/"));
306        g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup ("/bin/sh"));
307
308        pwent = getpwnam (welcome_session->priv->user_name);
309        if (pwent != NULL) {
310                if (pwent->pw_dir != NULL && pwent->pw_dir[0] != '\0') {
311                        g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup (pwent->pw_dir));
312                        g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup (pwent->pw_dir));
313                }
314
315                g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup (pwent->pw_shell));
316        }
317
318
319        g_hash_table_insert (hash, g_strdup ("PATH"), g_strdup (g_getenv ("PATH")));
320
321        g_hash_table_insert (hash, g_strdup ("RUNNING_UNDER_GDM"), g_strdup ("true"));
322        g_hash_table_insert (hash, g_strdup ("GVFS_DISABLE_FUSE"), g_strdup ("1"));
323
324        g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
325        g_hash_table_destroy (hash);
326
327        g_ptr_array_add (env, NULL);
328
329        return env;
330}
331
332
333static gboolean
334stop_dbus_daemon (GdmWelcomeSession *welcome_session)
335{
336        int res;
337
338        if (welcome_session->priv->dbus_pid > 0) {
339                g_debug ("GdmWelcomeSession: Stopping D-Bus daemon");
340                res = gdm_signal_pid (-1 * welcome_session->priv->dbus_pid, SIGTERM);
341                if (res < 0) {
342                        g_warning ("Unable to kill D-Bus daemon");
343                } else {
344                        welcome_session->priv->dbus_pid = 0;
345                }
346        }
347        return TRUE;
348}
349
350static void
351welcome_session_child_watch (GPid               pid,
352                             int                status,
353                             GdmWelcomeSession *session)
354{
355        g_debug ("GdmWelcomeSession: child (pid:%d) done (%s:%d)",
356                 (int) pid,
357                 WIFEXITED (status) ? "status"
358                 : WIFSIGNALED (status) ? "signal"
359                 : "unknown",
360                 WIFEXITED (status) ? WEXITSTATUS (status)
361                 : WIFSIGNALED (status) ? WTERMSIG (status)
362                 : -1);
363
364        if (WIFEXITED (status)) {
365                int code = WEXITSTATUS (status);
366                g_signal_emit (session, signals [EXITED], 0, code);
367        } else if (WIFSIGNALED (status)) {
368                int num = WTERMSIG (status);
369                g_signal_emit (session, signals [DIED], 0, num);
370        }
371
372        g_spawn_close_pid (session->priv->pid);
373        session->priv->pid = -1;
374
375        if (session->priv->ckc != NULL) {
376                close_welcome_session (session);
377        }
378        stop_dbus_daemon (session);
379}
380
381static void
382rotate_logs (const char *path,
383             guint       n_copies)
384{
385        int i;
386
387        for (i = n_copies - 1; i > 0; i--) {
388                char *name_n;
389                char *name_n1;
390
391                name_n = g_strdup_printf ("%s.%d", path, i);
392                if (i > 1) {
393                        name_n1 = g_strdup_printf ("%s.%d", path, i - 1);
394                } else {
395                        name_n1 = g_strdup (path);
396                }
397
398                VE_IGNORE_EINTR (g_unlink (name_n));
399                VE_IGNORE_EINTR (g_rename (name_n1, name_n));
400
401                g_free (name_n1);
402                g_free (name_n);
403        }
404
405        VE_IGNORE_EINTR (g_unlink (path));
406}
407
408typedef struct {
409        const char *user_name;
410        const char *group_name;
411        const char *log_file;
412} SpawnChildData;
413
414static void
415spawn_child_setup (SpawnChildData *data)
416{
417        struct passwd *pwent;
418        struct group  *grent;
419
420        if (data->user_name == NULL) {
421                return;
422        }
423
424        pwent = getpwnam (data->user_name);
425        if (pwent == NULL) {
426                g_warning (_("User %s doesn't exist"),
427                           data->user_name);
428                _exit (1);
429        }
430
431        grent = getgrnam (data->group_name);
432        if (grent == NULL) {
433                g_warning (_("Group %s doesn't exist"),
434                           data->group_name);
435                _exit (1);
436        }
437
438        g_debug ("GdmWelcomeSession: Changing (uid:gid) for child process to (%d:%d)",
439                 pwent->pw_uid,
440                 grent->gr_gid);
441
442        if (pwent->pw_uid != 0) {
443                if (setgid (grent->gr_gid) < 0)  {
444                        g_warning (_("Couldn't set groupid to %d"),
445                                   grent->gr_gid);
446                        _exit (1);
447                }
448
449                if (initgroups (pwent->pw_name, pwent->pw_gid) < 0) {
450                        g_warning (_("initgroups () failed for %s"),
451                                   pwent->pw_name);
452                        _exit (1);
453                }
454
455                if (setuid (pwent->pw_uid) < 0)  {
456                        g_warning (_("Couldn't set userid to %d"),
457                                   (int)pwent->pw_uid);
458                        _exit (1);
459                }
460        } else {
461                gid_t groups[1] = { 0 };
462
463                if (setgid (0) < 0)  {
464                        g_warning (_("Couldn't set groupid to 0"));
465                        /* Don't error out, it's not fatal, if it fails we'll
466                         * just still be */
467                }
468
469                /* this will get rid of any suplementary groups etc... */
470                setgroups (1, groups);
471        }
472
473        if (setsid () < 0) {
474                g_debug ("GdmWelcomeSession: could not set pid '%u' as leader of new session and process group - %s",
475                         (guint) getpid (), g_strerror (errno));
476                _exit (2);
477        }
478
479        if (data->log_file != NULL) {
480                int logfd;
481
482                rotate_logs (data->log_file, MAX_LOGS);
483
484                VE_IGNORE_EINTR (g_unlink (data->log_file));
485                VE_IGNORE_EINTR (logfd = open (data->log_file, O_CREAT|O_APPEND|O_TRUNC|O_WRONLY|O_EXCL, 0644));
486
487                if (logfd != -1) {
488                        VE_IGNORE_EINTR (dup2 (logfd, 1));
489                        VE_IGNORE_EINTR (dup2 (logfd, 2));
490                        close (logfd);
491                }
492        }
493}
494
495static gboolean
496spawn_command_line_sync_as_user (const char *command_line,
497                                 const char *user_name,
498                                 const char *group_name,
499                                 const char *log_file,
500                                 char       **env,
501                                 char       **std_output,
502                                 char       **std_error,
503                                 int         *exit_status,
504                                 GError     **error)
505{
506        char           **argv;
507        GError          *local_error;
508        gboolean         ret;
509        gboolean         res;
510        SpawnChildData   data;
511
512        ret = FALSE;
513
514        argv = NULL;
515        local_error = NULL;
516        if (! g_shell_parse_argv (command_line, NULL, &argv, &local_error)) {
517                g_warning ("Could not parse command: %s", local_error->message);
518                g_propagate_error (error, local_error);
519                goto out;
520        }
521
522        data.user_name = user_name;
523        data.group_name = group_name;
524        data.log_file = log_file;
525
526        local_error = NULL;
527        res = g_spawn_sync (NULL,
528                            argv,
529                            env,
530                            G_SPAWN_SEARCH_PATH,
531                            (GSpawnChildSetupFunc)spawn_child_setup,
532                            &data,
533                            std_output,
534                            std_error,
535                            exit_status,
536                            &local_error);
537
538        if (! res) {
539                g_warning ("Could not spawn command: %s", local_error->message);
540                g_propagate_error (error, local_error);
541                goto out;
542        }
543
544        ret = TRUE;
545 out:
546        g_strfreev (argv);
547
548        return ret;
549}
550
551static gboolean
552spawn_command_line_async_as_user (const char *command_line,
553                                  const char *user_name,
554                                  const char *group_name,
555                                  const char *log_file,
556                                  char      **env,
557                                  GPid       *child_pid,
558                                  GError    **error)
559{
560        char           **argv;
561        GError          *local_error;
562        gboolean         ret;
563        gboolean         res;
564        SpawnChildData   data;
565
566        ret = FALSE;
567
568        argv = NULL;
569        local_error = NULL;
570        if (! g_shell_parse_argv (command_line, NULL, &argv, &local_error)) {
571                g_warning ("Could not parse command: %s", local_error->message);
572                g_propagate_error (error, local_error);
573                goto out;
574        }
575
576        data.user_name = user_name;
577        data.group_name = group_name;
578        data.log_file = log_file;
579
580        local_error = NULL;
581        res = g_spawn_async (NULL,
582                             argv,
583                             env,
584                             G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
585                             (GSpawnChildSetupFunc)spawn_child_setup,
586                             &data,
587                             child_pid,
588                             &local_error);
589
590        if (! res) {
591                g_warning ("Could not spawn command: %s", local_error->message);
592                g_propagate_error (error, local_error);
593                goto out;
594        }
595
596        ret = TRUE;
597 out:
598        g_strfreev (argv);
599
600        return ret;
601}
602
603static gboolean
604parse_value_as_integer (const char *value,
605                        int        *intval)
606{
607        char *end_of_valid_int;
608        glong long_value;
609        gint  int_value;
610
611        errno = 0;
612        long_value = strtol (value, &end_of_valid_int, 10);
613
614        if (*value == '\0' || *end_of_valid_int != '\0') {
615                return FALSE;
616        }
617
618        int_value = long_value;
619        if (int_value != long_value || errno == ERANGE) {
620                return FALSE;
621        }
622
623        *intval = int_value;
624
625        return TRUE;
626}
627
628static gboolean
629parse_dbus_launch_output (const char *output,
630                          char      **addressp,
631                          GPid       *pidp)
632{
633        GRegex     *re;
634        GMatchInfo *match_info;
635        gboolean    ret;
636        gboolean    res;
637        GError     *error;
638
639        ret = FALSE;
640
641        error = NULL;
642        re = g_regex_new ("DBUS_SESSION_BUS_ADDRESS=(.+)\nDBUS_SESSION_BUS_PID=([0-9]+)", 0, 0, &error);
643        if (re == NULL) {
644                g_critical ("%s", error->message);
645        }
646
647        g_regex_match (re, output, 0, &match_info);
648
649        res = g_match_info_matches (match_info);
650        if (! res) {
651                g_warning ("Unable to parse output: %s", output);
652                goto out;
653        }
654
655        if (addressp != NULL) {
656                *addressp = g_strdup (g_match_info_fetch (match_info, 1));
657        }
658
659        if (pidp != NULL) {
660                int      pid;
661                gboolean result;
662                result = parse_value_as_integer (g_match_info_fetch (match_info, 2), &pid);
663                if (result) {
664                        *pidp = pid;
665                } else {
666                        *pidp = 0;
667                }
668        }
669
670        ret = TRUE;
671
672 out:
673        g_match_info_free (match_info);
674        g_regex_unref (re);
675
676        return ret;
677}
678
679static gboolean
680start_dbus_daemon (GdmWelcomeSession *welcome_session)
681{
682        gboolean   res;
683        char      *std_out;
684        char      *std_err;
685        int        exit_status;
686        GError    *error;
687        GPtrArray *env;
688
689        g_debug ("GdmWelcomeSession: Starting D-Bus daemon");
690
691        env = get_welcome_environment (welcome_session);
692
693        error = NULL;
694        res = spawn_command_line_sync_as_user (DBUS_LAUNCH_COMMAND,
695                                               welcome_session->priv->user_name,
696                                               welcome_session->priv->group_name,
697                                               NULL, /* log file */
698                                               (char **)env->pdata,
699                                               &std_out,
700                                               &std_err,
701                                               &exit_status,
702                                               &error);
703        g_ptr_array_foreach (env, (GFunc)g_free, NULL);
704        g_ptr_array_free (env, TRUE);
705
706        if (! res) {
707                g_warning ("Unable to launch D-Bus daemon: %s", error->message);
708                g_error_free (error);
709                goto out;
710        }
711
712        /* pull the address and pid from the output */
713        res = parse_dbus_launch_output (std_out,
714                                        &welcome_session->priv->dbus_bus_address,
715                                        &welcome_session->priv->dbus_pid);
716        if (! res) {
717                g_warning ("Unable to parse D-Bus launch output");
718        } else {
719                g_debug ("GdmWelcomeSession: Started D-Bus daemon on pid %d", welcome_session->priv->dbus_pid);
720        }
721 out:
722        return res;
723}
724
725static gboolean
726gdm_welcome_session_spawn (GdmWelcomeSession *welcome_session)
727{
728        GError          *error;
729        GPtrArray       *env;
730        gboolean         ret;
731        gboolean         res;
732        char            *log_path;
733        char            *log_file;
734
735        ret = FALSE;
736
737        g_debug ("GdmWelcomeSession: Running welcome_session process: %s", welcome_session->priv->command);
738
739        if (welcome_session->priv->register_ck_session) {
740                open_welcome_session (welcome_session);
741        }
742
743        res = start_dbus_daemon (welcome_session);
744        if (! res) {
745                /* FIXME: */
746        }
747
748        env = get_welcome_environment (welcome_session);
749
750        error = NULL;
751
752        log_file = g_strdup_printf ("%s-greeter.log", welcome_session->priv->x11_display_name);
753        log_path = g_build_filename (LOGDIR, log_file, NULL);
754        g_free (log_file);
755
756        ret = spawn_command_line_async_as_user (welcome_session->priv->command,
757                                                welcome_session->priv->user_name,
758                                                welcome_session->priv->group_name,
759                                                log_path,
760                                                (char **)env->pdata,
761                                                &welcome_session->priv->pid,
762                                                &error);
763
764        g_ptr_array_foreach (env, (GFunc)g_free, NULL);
765        g_ptr_array_free (env, TRUE);
766
767        g_free (log_path);
768
769        if (! ret) {
770                g_warning ("Could not start command '%s': %s",
771                           welcome_session->priv->command,
772                           error->message);
773                g_error_free (error);
774                goto out;
775        } else {
776                g_debug ("GdmWelcomeSession: WelcomeSession on pid %d", (int)welcome_session->priv->pid);
777        }
778
779        welcome_session->priv->child_watch_id = g_child_watch_add (welcome_session->priv->pid,
780                                                                   (GChildWatchFunc)welcome_session_child_watch,
781                                                                   welcome_session);
782
783 out:
784
785        return ret;
786}
787
788/**
789 * gdm_welcome_session_start:
790 * @disp: Pointer to a GdmDisplay structure
791 *
792 * Starts a local X welcome_session. Handles retries and fatal errors properly.
793 */
794gboolean
795gdm_welcome_session_start (GdmWelcomeSession *welcome_session)
796{
797        gboolean    res;
798
799        g_debug ("GdmWelcomeSession: Starting welcome...");
800
801        res = gdm_welcome_session_spawn (welcome_session);
802
803        if (res) {
804
805        }
806
807
808        return res;
809}
810
811static void
812welcome_session_died (GdmWelcomeSession *welcome_session)
813{
814        int exit_status;
815
816        g_debug ("GdmWelcomeSession: Waiting on process %d", welcome_session->priv->pid);
817        exit_status = gdm_wait_on_pid (welcome_session->priv->pid);
818
819        if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
820                g_debug ("GdmWelcomeSession: Wait on child process failed");
821        } else {
822                /* exited normally */
823        }
824
825        g_spawn_close_pid (welcome_session->priv->pid);
826        welcome_session->priv->pid = -1;
827
828        g_debug ("GdmWelcomeSession: WelcomeSession died");
829}
830
831gboolean
832gdm_welcome_session_stop (GdmWelcomeSession *welcome_session)
833{
834        int res;
835
836        if (welcome_session->priv->pid <= 1) {
837                return TRUE;
838        }
839
840        /* remove watch source before we can wait on child */
841        if (welcome_session->priv->child_watch_id > 0) {
842                g_source_remove (welcome_session->priv->child_watch_id);
843                welcome_session->priv->child_watch_id = 0;
844        }
845
846        g_debug ("GdmWelcomeSession: Stopping welcome_session");
847
848        res = gdm_signal_pid (-1 * welcome_session->priv->pid, SIGTERM);
849        if (res < 0) {
850                g_warning ("Unable to kill welcome session process");
851        } else {
852                welcome_session_died (welcome_session);
853        }
854
855        if (welcome_session->priv->ckc != NULL) {
856                close_welcome_session (welcome_session);
857        }
858
859        stop_dbus_daemon (welcome_session);
860
861        return TRUE;
862}
863
864void
865gdm_welcome_session_set_server_address (GdmWelcomeSession *welcome_session,
866                                        const char        *address)
867{
868        g_return_if_fail (GDM_IS_WELCOME_SESSION (welcome_session));
869
870        g_free (welcome_session->priv->server_address);
871        welcome_session->priv->server_address = g_strdup (address);
872}
873
874static void
875_gdm_welcome_session_set_x11_display_name (GdmWelcomeSession *welcome_session,
876                                           const char        *name)
877{
878        g_free (welcome_session->priv->x11_display_name);
879        welcome_session->priv->x11_display_name = g_strdup (name);
880}
881
882static void
883_gdm_welcome_session_set_x11_display_hostname (GdmWelcomeSession *welcome_session,
884                                               const char        *name)
885{
886        g_free (welcome_session->priv->x11_display_hostname);
887        welcome_session->priv->x11_display_hostname = g_strdup (name);
888}
889
890static void
891_gdm_welcome_session_set_x11_display_device (GdmWelcomeSession *welcome_session,
892                                             const char        *name)
893{
894        g_free (welcome_session->priv->x11_display_device);
895        welcome_session->priv->x11_display_device = g_strdup (name);
896}
897
898static void
899_gdm_welcome_session_set_x11_display_is_local (GdmWelcomeSession *welcome_session,
900                                               gboolean           is_local)
901{
902        welcome_session->priv->x11_display_is_local = is_local;
903}
904
905
906static void
907_gdm_welcome_session_set_x11_authority_file (GdmWelcomeSession *welcome_session,
908                                             const char        *file)
909{
910        g_free (welcome_session->priv->x11_authority_file);
911        welcome_session->priv->x11_authority_file = g_strdup (file);
912}
913
914static void
915_gdm_welcome_session_set_user_name (GdmWelcomeSession *welcome_session,
916                                    const char        *name)
917{
918        g_free (welcome_session->priv->user_name);
919        welcome_session->priv->user_name = g_strdup (name);
920}
921
922static void
923_gdm_welcome_session_set_group_name (GdmWelcomeSession *welcome_session,
924                                     const char        *name)
925{
926        g_free (welcome_session->priv->group_name);
927        welcome_session->priv->group_name = g_strdup (name);
928}
929
930static void
931_gdm_welcome_session_set_server_dbus_path (GdmWelcomeSession *welcome_session,
932                                           const char        *name)
933{
934        g_free (welcome_session->priv->server_dbus_path);
935        welcome_session->priv->server_dbus_path = g_strdup (name);
936}
937
938static void
939_gdm_welcome_session_set_server_dbus_interface (GdmWelcomeSession *welcome_session,
940                                                const char        *name)
941{
942        g_free (welcome_session->priv->server_dbus_interface);
943        welcome_session->priv->server_dbus_interface = g_strdup (name);
944}
945
946static void
947_gdm_welcome_session_set_command (GdmWelcomeSession *welcome_session,
948                                  const char        *name)
949{
950        g_free (welcome_session->priv->command);
951        welcome_session->priv->command = g_strdup (name);
952}
953
954static void
955_gdm_welcome_session_set_server_env_var_name (GdmWelcomeSession *welcome_session,
956                                              const char        *name)
957{
958        g_free (welcome_session->priv->server_env_var_name);
959        welcome_session->priv->server_env_var_name = g_strdup (name);
960}
961
962static void
963_gdm_welcome_session_set_register_ck_session (GdmWelcomeSession *welcome_session,
964                                              gboolean           val)
965{
966        welcome_session->priv->register_ck_session = val;
967}
968
969static void
970gdm_welcome_session_set_property (GObject      *object,
971                                  guint         prop_id,
972                                  const GValue *value,
973                                  GParamSpec   *pspec)
974{
975        GdmWelcomeSession *self;
976
977        self = GDM_WELCOME_SESSION (object);
978
979        switch (prop_id) {
980        case PROP_X11_DISPLAY_NAME:
981                _gdm_welcome_session_set_x11_display_name (self, g_value_get_string (value));
982                break;
983        case PROP_X11_DISPLAY_HOSTNAME:
984                _gdm_welcome_session_set_x11_display_hostname (self, g_value_get_string (value));
985                break;
986        case PROP_X11_DISPLAY_DEVICE:
987                _gdm_welcome_session_set_x11_display_device (self, g_value_get_string (value));
988                break;
989        case PROP_X11_DISPLAY_IS_LOCAL:
990                _gdm_welcome_session_set_x11_display_is_local (self, g_value_get_boolean (value));
991                break;
992        case PROP_X11_AUTHORITY_FILE:
993                _gdm_welcome_session_set_x11_authority_file (self, g_value_get_string (value));
994                break;
995        case PROP_USER_NAME:
996                _gdm_welcome_session_set_user_name (self, g_value_get_string (value));
997                break;
998        case PROP_GROUP_NAME:
999                _gdm_welcome_session_set_group_name (self, g_value_get_string (value));
1000                break;
1001        case PROP_SERVER_ADDRESS:
1002                gdm_welcome_session_set_server_address (self, g_value_get_string (value));
1003                break;
1004        case PROP_SERVER_DBUS_PATH:
1005                _gdm_welcome_session_set_server_dbus_path (self, g_value_get_string (value));
1006                break;
1007        case PROP_SERVER_DBUS_INTERFACE:
1008                _gdm_welcome_session_set_server_dbus_interface (self, g_value_get_string (value));
1009                break;
1010        case PROP_REGISTER_CK_SESSION:
1011                _gdm_welcome_session_set_register_ck_session (self, g_value_get_boolean (value));
1012                break;
1013        case PROP_SERVER_ENV_VAR_NAME:
1014                _gdm_welcome_session_set_server_env_var_name (self, g_value_get_string (value));
1015                break;
1016        case PROP_COMMAND:
1017                _gdm_welcome_session_set_command (self, g_value_get_string (value));
1018                break;
1019        default:
1020                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1021                break;
1022        }
1023}
1024
1025static void
1026gdm_welcome_session_get_property (GObject    *object,
1027                                  guint       prop_id,
1028                                  GValue     *value,
1029                                  GParamSpec *pspec)
1030{
1031        GdmWelcomeSession *self;
1032
1033        self = GDM_WELCOME_SESSION (object);
1034
1035        switch (prop_id) {
1036        case PROP_X11_DISPLAY_NAME:
1037                g_value_set_string (value, self->priv->x11_display_name);
1038                break;
1039        case PROP_X11_DISPLAY_HOSTNAME:
1040                g_value_set_string (value, self->priv->x11_display_hostname);
1041                break;
1042        case PROP_X11_DISPLAY_DEVICE:
1043                g_value_set_string (value, self->priv->x11_display_device);
1044                break;
1045        case PROP_X11_DISPLAY_IS_LOCAL:
1046                g_value_set_boolean (value, self->priv->x11_display_is_local);
1047                break;
1048        case PROP_X11_AUTHORITY_FILE:
1049                g_value_set_string (value, self->priv->x11_authority_file);
1050                break;
1051        case PROP_USER_NAME:
1052                g_value_set_string (value, self->priv->user_name);
1053                break;
1054        case PROP_GROUP_NAME:
1055                g_value_set_string (value, self->priv->group_name);
1056                break;
1057        case PROP_SERVER_ADDRESS:
1058                g_value_set_string (value, self->priv->server_address);
1059                break;
1060        case PROP_SERVER_DBUS_PATH:
1061                g_value_set_string (value, self->priv->server_dbus_path);
1062                break;
1063        case PROP_SERVER_DBUS_INTERFACE:
1064                g_value_set_string (value, self->priv->server_dbus_interface);
1065                break;
1066        case PROP_REGISTER_CK_SESSION:
1067                g_value_set_boolean (value, self->priv->register_ck_session);
1068                break;
1069        case PROP_SERVER_ENV_VAR_NAME:
1070                g_value_set_string (value, self->priv->server_env_var_name);
1071                break;
1072        case PROP_COMMAND:
1073                g_value_set_string (value, self->priv->command);
1074                break;
1075        default:
1076                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1077                break;
1078        }
1079}
1080
1081static GObject *
1082gdm_welcome_session_constructor (GType                  type,
1083                                 guint                  n_construct_properties,
1084                                 GObjectConstructParam *construct_properties)
1085{
1086        GdmWelcomeSession      *welcome_session;
1087
1088        welcome_session = GDM_WELCOME_SESSION (G_OBJECT_CLASS (gdm_welcome_session_parent_class)->constructor (type,
1089                                                                                                               n_construct_properties,
1090                                                                                                               construct_properties));
1091
1092        return G_OBJECT (welcome_session);
1093}
1094
1095static void
1096gdm_welcome_session_class_init (GdmWelcomeSessionClass *klass)
1097{
1098        GObjectClass    *object_class = G_OBJECT_CLASS (klass);
1099
1100        object_class->get_property = gdm_welcome_session_get_property;
1101        object_class->set_property = gdm_welcome_session_set_property;
1102        object_class->constructor = gdm_welcome_session_constructor;
1103        object_class->finalize = gdm_welcome_session_finalize;
1104
1105        g_type_class_add_private (klass, sizeof (GdmWelcomeSessionPrivate));
1106
1107        g_object_class_install_property (object_class,
1108                                         PROP_X11_DISPLAY_NAME,
1109                                         g_param_spec_string ("x11-display-name",
1110                                                              "name",
1111                                                              "name",
1112                                                              NULL,
1113                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1114        g_object_class_install_property (object_class,
1115                                         PROP_X11_DISPLAY_HOSTNAME,
1116                                         g_param_spec_string ("x11-display-hostname",
1117                                                              "hostname",
1118                                                              "hostname",
1119                                                              NULL,
1120                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1121        g_object_class_install_property (object_class,
1122                                         PROP_X11_DISPLAY_DEVICE,
1123                                         g_param_spec_string ("x11-display-device",
1124                                                              "device",
1125                                                              "device",
1126                                                              NULL,
1127                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1128        g_object_class_install_property (object_class,
1129                                         PROP_X11_DISPLAY_IS_LOCAL,
1130                                         g_param_spec_boolean ("x11-display-is-local",
1131                                                               "is local",
1132                                                               "is local",
1133                                                               FALSE,
1134                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1135        g_object_class_install_property (object_class,
1136                                         PROP_X11_AUTHORITY_FILE,
1137                                         g_param_spec_string ("x11-authority-file",
1138                                                              "authority file",
1139                                                              "authority file",
1140                                                              NULL,
1141                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1142        g_object_class_install_property (object_class,
1143                                         PROP_USER_NAME,
1144                                         g_param_spec_string ("user-name",
1145                                                              "user name",
1146                                                              "user name",
1147                                                              GDM_USERNAME,
1148                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1149        g_object_class_install_property (object_class,
1150                                         PROP_GROUP_NAME,
1151                                         g_param_spec_string ("group-name",
1152                                                              "group name",
1153                                                              "group name",
1154                                                              GDM_GROUPNAME,
1155                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1156        g_object_class_install_property (object_class,
1157                                         PROP_SERVER_ADDRESS,
1158                                         g_param_spec_string ("server-address",
1159                                                              "server address",
1160                                                              "server address",
1161                                                              NULL,
1162                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
1163        g_object_class_install_property (object_class,
1164                                         PROP_SERVER_DBUS_PATH,
1165                                         g_param_spec_string ("server-dbus-path",
1166                                                              "server dbus path",
1167                                                              "server dbus path",
1168                                                              NULL,
1169                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1170        g_object_class_install_property (object_class,
1171                                         PROP_SERVER_DBUS_INTERFACE,
1172                                         g_param_spec_string ("server-dbus-interface",
1173                                                              "server dbus interface",
1174                                                              "server dbus interface",
1175                                                              NULL,
1176                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1177        g_object_class_install_property (object_class,
1178                                         PROP_SERVER_ENV_VAR_NAME,
1179                                         g_param_spec_string ("server-env-var-name",
1180                                                              "server env var name",
1181                                                              "server env var name",
1182                                                              NULL,
1183                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1184        g_object_class_install_property (object_class,
1185                                         PROP_COMMAND,
1186                                         g_param_spec_string ("command",
1187                                                              "command",
1188                                                              "command",
1189                                                              NULL,
1190                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1191        g_object_class_install_property (object_class,
1192                                         PROP_REGISTER_CK_SESSION,
1193                                         g_param_spec_boolean ("register-ck-session",
1194                                                               NULL,
1195                                                               NULL,
1196                                                               FALSE,
1197                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
1198        signals [STARTED] =
1199                g_signal_new ("started",
1200                              G_OBJECT_CLASS_TYPE (object_class),
1201                              G_SIGNAL_RUN_FIRST,
1202                              G_STRUCT_OFFSET (GdmWelcomeSessionClass, started),
1203                              NULL,
1204                              NULL,
1205                              g_cclosure_marshal_VOID__VOID,
1206                              G_TYPE_NONE,
1207                              0);
1208        signals [STOPPED] =
1209                g_signal_new ("stopped",
1210                              G_OBJECT_CLASS_TYPE (object_class),
1211                              G_SIGNAL_RUN_FIRST,
1212                              G_STRUCT_OFFSET (GdmWelcomeSessionClass, stopped),
1213                              NULL,
1214                              NULL,
1215                              g_cclosure_marshal_VOID__VOID,
1216                              G_TYPE_NONE,
1217                              0);
1218        signals [EXITED] =
1219                g_signal_new ("exited",
1220                              G_OBJECT_CLASS_TYPE (object_class),
1221                              G_SIGNAL_RUN_FIRST,
1222                              G_STRUCT_OFFSET (GdmWelcomeSessionClass, exited),
1223                              NULL,
1224                              NULL,
1225                              g_cclosure_marshal_VOID__INT,
1226                              G_TYPE_NONE,
1227                              1,
1228                              G_TYPE_INT);
1229        signals [DIED] =
1230                g_signal_new ("died",
1231                              G_OBJECT_CLASS_TYPE (object_class),
1232                              G_SIGNAL_RUN_FIRST,
1233                              G_STRUCT_OFFSET (GdmWelcomeSessionClass, died),
1234                              NULL,
1235                              NULL,
1236                              g_cclosure_marshal_VOID__INT,
1237                              G_TYPE_NONE,
1238                              1,
1239                              G_TYPE_INT);
1240}
1241
1242static void
1243gdm_welcome_session_init (GdmWelcomeSession *welcome_session)
1244{
1245
1246        welcome_session->priv = GDM_WELCOME_SESSION_GET_PRIVATE (welcome_session);
1247
1248        welcome_session->priv->pid = -1;
1249
1250        welcome_session->priv->command = NULL;
1251}
1252
1253static void
1254gdm_welcome_session_finalize (GObject *object)
1255{
1256        GdmWelcomeSession *welcome_session;
1257
1258        g_return_if_fail (object != NULL);
1259        g_return_if_fail (GDM_IS_WELCOME_SESSION (object));
1260
1261        welcome_session = GDM_WELCOME_SESSION (object);
1262
1263        g_return_if_fail (welcome_session->priv != NULL);
1264
1265        gdm_welcome_session_stop (welcome_session);
1266
1267        g_free (welcome_session->priv->command);
1268        g_free (welcome_session->priv->user_name);
1269        g_free (welcome_session->priv->group_name);
1270        g_free (welcome_session->priv->x11_display_name);
1271        g_free (welcome_session->priv->x11_display_device);
1272        g_free (welcome_session->priv->x11_display_hostname);
1273        g_free (welcome_session->priv->x11_authority_file);
1274        g_free (welcome_session->priv->server_address);
1275        g_free (welcome_session->priv->server_dbus_path);
1276        g_free (welcome_session->priv->server_dbus_interface);
1277
1278        G_OBJECT_CLASS (gdm_welcome_session_parent_class)->finalize (object);
1279}
Note: See TracBrowser for help on using the repository browser.