[gdm] daemon: run greeter in its own distinct session



commit 647cad5bf59a4ff3776ba1ae5cda6b1aaaa1cfb2
Author: Ray Strode <rstrode redhat com>
Date:   Tue Aug 30 11:05:53 2011 -0400

    daemon: run greeter in its own distinct session
    
    Right now before launching the greeter, we create this
    little ad hoc session that only runs through some of the
    OS machinery for session registration.
    
    This means not only is there duplicate code with GDMs
    real session handling functions, but the greeter is
    potentially running in an incomplete session.
    
    This commit, inspired by the work of Lennart and Kay,
    changes GDM to run its greeter session through a session
    worker just like any other session.

 daemon/Makefile.am           |   15 ++
 daemon/gdm-session-direct.c  |  167 ++++++++++++---
 daemon/gdm-session-worker.c  |  218 ++++++++++++++++++--
 daemon/gdm-session.c         |   37 ++++
 daemon/gdm-session.h         |   20 ++
 daemon/gdm-welcome-session.c |  483 ++++++++++++++---------------------------
 data/Makefile.am             |    7 +-
 data/gdm-welcome             |    4 +
 8 files changed, 587 insertions(+), 364 deletions(-)
---
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 5b4796a..98b95ce 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -166,9 +166,15 @@ gdm_factory_slave_SOURCES = 		\
 	gdm-server.h			\
 	gdm-session.c			\
 	gdm-session.h			\
+	gdm-session-direct.c		\
+	gdm-session-direct.h		\
 	gdm-session-private.h		\
+	gdm-session-record.c		\
+	gdm-session-record.h		\
 	gdm-session-relay.c		\
 	gdm-session-relay.h		\
+	gdm-session-worker-job.c	\
+	gdm-session-worker-job.h	\
 	gdm-xerrors.h			\
 	gdm-xerrors.c			\
 	gdm-slave.c			\
@@ -226,6 +232,15 @@ gdm_xdmcp_chooser_slave_SOURCES = 		\
 	gdm-chooser-server.h			\
 	ck-connector.h				\
 	ck-connector.c				\
+	gdm-session.c				\
+	gdm-session.h				\
+	gdm-session-direct.c			\
+	gdm-session-direct.h			\
+	gdm-session-private.h			\
+	gdm-session-record.c			\
+	gdm-session-record.h			\
+	gdm-session-worker-job.c		\
+	gdm-session-worker-job.h		\
 	gdm-welcome-session.c			\
 	gdm-welcome-session.h			\
 	gdm-chooser-session.c			\
diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c
index e977486..1d5c16a 100644
--- a/daemon/gdm-session-direct.c
+++ b/daemon/gdm-session-direct.c
@@ -80,6 +80,7 @@ typedef struct
 struct _GdmSessionDirectPrivate
 {
         /* per open scope */
+        char                *selected_program;
         char                *selected_session;
         char                *saved_session;
         char                *selected_language;
@@ -1397,6 +1398,12 @@ do_introspect (DBusConnection *connection,
                                "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
                                "      <arg name=\"username\" type=\"s\"/>\n"
                                "    </signal>\n"
+                               "    <signal name=\"SetupForProgram\">\n"
+                               "      <arg name=\"service_name\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
+                               "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
+                               "      <arg name=\"log_file\" type=\"s\"/>\n"
+                               "    </signal>\n"
                                "    <signal name=\"Authenticate\">\n"
                                "    </signal>\n"
                                "    <signal name=\"Authorize\">\n"
@@ -1415,6 +1422,9 @@ do_introspect (DBusConnection *connection,
                                "    <signal name=\"SetSessionName\">\n"
                                "      <arg name=\"session_name\" type=\"s\"/>\n"
                                "    </signal>\n"
+                               "    <signal name=\"SetSessionType\">\n"
+                               "      <arg name=\"session_type\" type=\"s\"/>\n"
+                               "    </signal>\n"
                                "    <signal name=\"StartProgram\">\n"
                                "      <arg name=\"command\" type=\"s\"/>\n"
                                "    </signal>\n"
@@ -2035,6 +2045,50 @@ send_setup_for_user (GdmSessionDirect *session,
 }
 
 static void
+send_setup_for_program (GdmSessionDirect *session,
+                        const char       *service_name,
+                        const char       *log_file)
+{
+        DBusMessage    *message;
+        DBusMessageIter iter;
+        const char     *display_name;
+        const char     *display_x11_authority_file;
+        GdmSessionConversation *conversation;
+
+        g_assert (service_name != NULL);
+
+        if (session->priv->display_name != NULL) {
+                display_name = session->priv->display_name;
+        } else {
+                display_name = "";
+        }
+        if (session->priv->display_x11_authority_file != NULL) {
+                display_x11_authority_file = session->priv->display_x11_authority_file;
+        } else {
+                display_x11_authority_file = "";
+        }
+
+        g_debug ("GdmSessionDirect: Beginning setup for session for program with log '%s'", log_file);
+
+        message = dbus_message_new_signal (GDM_SESSION_DBUS_PATH,
+                                           GDM_SESSION_DBUS_INTERFACE,
+                                           "SetupForProgram");
+
+        dbus_message_iter_init_append (message, &iter);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
+        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &log_file);
+
+        conversation = find_conversation_by_name (session, service_name);
+        if (conversation != NULL && ! send_dbus_message (conversation, message)) {
+                g_debug ("GdmSessionDirect: Could not send %s signal", "SetupForProgram");
+        }
+
+        dbus_message_unref (message);
+}
+
+static void
 gdm_session_direct_setup (GdmSession *session,
                           const char *service_name)
 {
@@ -2063,6 +2117,18 @@ gdm_session_direct_setup_for_user (GdmSession *session,
 }
 
 static void
+gdm_session_direct_setup_for_program (GdmSession *session,
+                                      const char *service_name,
+                                      const char *log_file)
+{
+        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
+
+        g_return_if_fail (session != NULL);
+
+        send_setup_for_program (impl, service_name, log_file);
+}
+
+static void
 gdm_session_direct_authenticate (GdmSession *session,
                                  const char *service_name)
 {
@@ -2194,33 +2260,34 @@ get_session_command (GdmSessionDirect *session)
 }
 
 static void
-gdm_session_direct_set_environment_variable (GdmSessionDirect *session,
-                                             const char       *key,
-                                             const char       *value)
+gdm_session_direct_set_environment_variable (GdmSession *session,
+                                             const char *key,
+                                             const char *value)
 {
-        g_return_if_fail (session != NULL);
-        g_return_if_fail (session != NULL);
+        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
+
         g_return_if_fail (key != NULL);
         g_return_if_fail (value != NULL);
 
-        g_hash_table_replace (session->priv->environment,
+        g_hash_table_replace (impl->priv->environment,
                               g_strdup (key),
                               g_strdup (value));
 }
 
 static void
-setup_session_environment (GdmSessionDirect *session)
+setup_session_environment (GdmSessionDirect *session_direct)
 {
+        GdmSession *session = GDM_SESSION (session_direct);
         const char *locale;
 
         gdm_session_direct_set_environment_variable (session,
                                                      "GDMSESSION",
-                                                     get_session_name (session));
+                                                     get_session_name (session_direct));
         gdm_session_direct_set_environment_variable (session,
                                                      "DESKTOP_SESSION",
-                                                     get_session_name (session));
+                                                     get_session_name (session_direct));
 
-        locale = get_language_name (session);
+        locale = get_language_name (session_direct);
 
         if (locale != NULL && locale[0] != '\0') {
                 gdm_session_direct_set_environment_variable (session,
@@ -2233,12 +2300,12 @@ setup_session_environment (GdmSessionDirect *session)
 
         gdm_session_direct_set_environment_variable (session,
                                                      "DISPLAY",
-                                                     session->priv->display_name);
+                                                     session_direct->priv->display_name);
 
-        if (session->priv->user_x11_authority_file != NULL) {
+        if (session_direct->priv->user_x11_authority_file != NULL) {
                 gdm_session_direct_set_environment_variable (session,
                                                              "XAUTHORITY",
-                                                             session->priv->user_x11_authority_file);
+                                                             session_direct->priv->user_x11_authority_file);
         }
 
         if (g_getenv ("WINDOWPATH") != NULL) {
@@ -2336,16 +2403,20 @@ gdm_session_direct_start_session (GdmSession *session,
 
         stop_all_other_conversations (impl, conversation);
 
-        command = get_session_command (impl);
+        if (impl->priv->selected_program == NULL) {
+                command = get_session_command (impl);
 
-        if (gdm_session_direct_bypasses_xsession (impl)) {
-                program = g_strdup (command);
+                if (gdm_session_direct_bypasses_xsession (impl)) {
+                        program = g_strdup (command);
+                } else {
+                        program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
+                }
+
+                g_free (command);
         } else {
-                program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
+                program = g_strdup (impl->priv->selected_program);
         }
 
-        g_free (command);
-
         setup_session_environment (impl);
         send_environment (impl, conversation);
 
@@ -2495,6 +2566,35 @@ out:
 }
 
 static void
+gdm_session_direct_select_program (GdmSession *session,
+                                   const char *text)
+{
+        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
+
+        g_free (impl->priv->selected_program);
+
+        impl->priv->selected_program = g_strdup (text);
+}
+
+static void
+gdm_session_direct_select_session_type (GdmSession *session,
+                                        const char *text)
+{
+        GdmSessionDirect *impl = GDM_SESSION_DIRECT (session);
+        GHashTableIter iter;
+        gpointer key, value;
+
+        g_hash_table_iter_init (&iter, impl->priv->conversations);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                GdmSessionConversation *conversation;
+
+                conversation = (GdmSessionConversation *) value;
+
+                send_dbus_string_signal (conversation, "SetSessionType",
+                                         text);
+        }
+}
+static void
 gdm_session_direct_select_session (GdmSession *session,
                                    const char *text)
 {
@@ -2781,21 +2881,22 @@ gdm_session_direct_constructor (GType                  type,
         session = GDM_SESSION_DIRECT (G_OBJECT_CLASS (gdm_session_direct_parent_class)->constructor (type,
                                                                                           n_construct_properties,
                                                                                           construct_properties));
+        if (session->priv->display_id != NULL) {
+                /* Always match the session id with the master */
+                id = NULL;
+                if (g_str_has_prefix (session->priv->display_id, "/org/gnome/DisplayManager/Display")) {
+                        id = session->priv->display_id + strlen ("/org/gnome/DisplayManager/Display");
+                }
 
-        /* Always match the session id with the master */
-        id = NULL;
-        if (g_str_has_prefix (session->priv->display_id, "/org/gnome/DisplayManager/Display")) {
-                id = session->priv->display_id + strlen ("/org/gnome/DisplayManager/Display");
-        }
-
-        g_assert (id != NULL);
+                g_assert (id != NULL);
 
-        session->priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Session%s", id);
-        g_debug ("GdmSessionDirect: Registering %s", session->priv->id);
+                session->priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Session%s", id);
+                g_debug ("GdmSessionDirect: Registering %s", session->priv->id);
 
-        res = register_session (session);
-        if (! res) {
-                g_warning ("Unable to register session with system bus");
+                res = register_session (session);
+                if (! res) {
+                        g_warning ("Unable to register session with system bus");
+                }
         }
 
         return G_OBJECT (session);
@@ -2808,6 +2909,8 @@ gdm_session_iface_init (GdmSessionIface *iface)
         iface->stop_conversation = gdm_session_direct_stop_conversation;
         iface->setup = gdm_session_direct_setup;
         iface->setup_for_user = gdm_session_direct_setup_for_user;
+        iface->setup_for_program = gdm_session_direct_setup_for_program;
+        iface->set_environment_variable = gdm_session_direct_set_environment_variable;
         iface->authenticate = gdm_session_direct_authenticate;
         iface->authorize = gdm_session_direct_authorize;
         iface->accredit = gdm_session_direct_accredit;
@@ -2817,6 +2920,8 @@ gdm_session_iface_init (GdmSessionIface *iface)
         iface->cancel = gdm_session_direct_cancel;
         iface->start_session = gdm_session_direct_start_session;
         iface->answer_query = gdm_session_direct_answer_query;
+        iface->select_program = gdm_session_direct_select_program;
+        iface->select_session_type = gdm_session_direct_select_session_type;
         iface->select_session = gdm_session_direct_select_session;
         iface->select_language = gdm_session_direct_select_language;
         iface->select_user = gdm_session_direct_select_user;
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 1c44b17..2b46ca8 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -85,6 +85,7 @@
 #endif
 
 #define MAX_FILE_SIZE     65536
+#define MAX_LOGS          5
 
 enum {
         GDM_SESSION_WORKER_STATE_NONE = 0,
@@ -119,6 +120,8 @@ struct GdmSessionWorkerPrivate
         char             *display_device;
         char             *hostname;
         char             *username;
+        char             *log_file;
+        char             *session_type;
         uid_t             uid;
         gid_t             gid;
         gboolean          password_is_required;
@@ -128,6 +131,7 @@ struct GdmSessionWorkerPrivate
         char            **arguments;
         guint32           cancelled : 1;
         guint32           timed_out : 1;
+        guint32           is_program_session : 1;
         guint             state_change_idle_id;
 
         char             *server_address;
@@ -176,6 +180,7 @@ open_ck_session (GdmSessionWorker  *worker)
         const char     *display_name;
         const char     *display_device;
         const char     *display_hostname;
+        const char     *session_type;
         gboolean        is_local;
 
         ret = FALSE;
@@ -196,6 +201,12 @@ open_ck_session (GdmSessionWorker  *worker)
                 display_device = "";
         }
 
+        if (worker->priv->session_type != NULL) {
+                session_type = worker->priv->session_type;
+        } else {
+                session_type = "";
+        }
+
         g_assert (worker->priv->username != NULL);
 
         /* FIXME: this isn't very good */
@@ -226,6 +237,7 @@ open_ck_session (GdmSessionWorker  *worker)
                                                          "x11-display-device", &display_device,
                                                          "remote-host-name", &display_hostname,
                                                          "is-local", &is_local,
+                                                         "session-type", &session_type,
                                                          NULL);
 
         if (! res) {
@@ -931,6 +943,13 @@ gdm_session_worker_pam_new_messages_handler (int                        number_o
 static void
 gdm_session_worker_start_auditor (GdmSessionWorker *worker)
 {
+    /* Use dummy auditor so program session doesn't pollute user audit logs
+     */
+    if (worker->priv->is_program_session) {
+            worker->priv->auditor = gdm_session_auditor_new (worker->priv->hostname,
+                                                             worker->priv->display_device);
+            return;
+    }
 
 /* FIXME: it may make sense at some point to keep a list of
  * auditors, instead of assuming they are mutually exclusive
@@ -1238,7 +1257,7 @@ gdm_session_worker_authorize_user (GdmSessionWorker *worker,
 
         /* it's possible that the user needs to change their password or pin code
          */
-        if (error_code == PAM_NEW_AUTHTOK_REQD) {
+        if (error_code == PAM_NEW_AUTHTOK_REQD && !worker->priv->is_program_session) {
                 error_code = pam_chauthtok (worker->priv->pam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
 
                 gdm_session_worker_get_username (worker, NULL);
@@ -1624,8 +1643,85 @@ _is_loggable_file (const char* filename)
         return S_ISREG (file_info.st_mode) && g_access (filename, R_OK | W_OK) == 0;
 }
 
+static void
+rotate_logs (const char *path,
+             guint       n_copies)
+{
+        int i;
+
+        for (i = n_copies - 1; i > 0; i--) {
+                char *name_n;
+                char *name_n1;
+
+                name_n = g_strdup_printf ("%s.%d", path, i);
+                if (i > 1) {
+                        name_n1 = g_strdup_printf ("%s.%d", path, i - 1);
+                } else {
+                        name_n1 = g_strdup (path);
+                }
+
+                g_unlink (name_n);
+                g_rename (name_n1, name_n);
+
+                g_free (name_n1);
+                g_free (name_n);
+        }
+
+        g_unlink (path);
+}
+
+static int
+_open_program_session_log (const char *filename)
+{
+        int   fd;
+
+        rotate_logs (filename, MAX_LOGS);
+
+        fd = g_open (filename, O_RDWR | O_APPEND | O_CREAT, 0600);
+
+        if (fd < 0) {
+                char *temp_name;
+
+                close (fd);
+
+                temp_name = g_strdup_printf ("%s.XXXXXXXX", filename);
+
+                fd = g_mkstemp (temp_name);
+
+                if (fd < 0) {
+                        g_free (temp_name);
+                        goto out;
+                }
+
+                g_warning ("session log '%s' is not appendable, logging session to '%s' instead.\n", filename,
+                           temp_name);
+                g_free (temp_name);
+        } else {
+                if (ftruncate (fd, 0) < 0) {
+                        close (fd);
+                        fd = -1;
+                        goto out;
+                }
+        }
+
+        if (fchmod (fd, 0644) < 0) {
+                close (fd);
+                fd = -1;
+                goto out;
+        }
+
+
+out:
+        if (fd < 0) {
+                g_warning ("unable to log program session");
+                fd = g_open ("/dev/null", O_RDWR);
+        }
+
+        return fd;
+}
+
 static int
-_open_session_log (const char *dir)
+_open_user_session_log (const char *dir)
 {
         int   fd;
         char *filename;
@@ -1687,8 +1783,8 @@ out:
 }
 
 static gboolean
-gdm_session_worker_start_user_session (GdmSessionWorker  *worker,
-                                       GError           **error)
+gdm_session_worker_start_session (GdmSessionWorker  *worker,
+                                  GError           **error)
 {
         struct passwd *passwd_entry;
         pid_t session_pid;
@@ -1697,8 +1793,13 @@ gdm_session_worker_start_user_session (GdmSessionWorker  *worker,
         register_ck_session (worker);
 
         gdm_get_pwent_for_name (worker->priv->username, &passwd_entry);
-        g_debug ("GdmSessionWorker: opening user session with program '%s'",
-                 worker->priv->arguments[0]);
+        if (worker->priv->is_program_session) {
+                g_debug ("GdmSessionWorker: opening session for program '%s'",
+                         worker->priv->arguments[0]);
+        } else {
+                g_debug ("GdmSessionWorker: opening user session with program '%s'",
+                         worker->priv->arguments[0]);
+        }
 
         error_code = PAM_SUCCESS;
 
@@ -1743,7 +1844,11 @@ gdm_session_worker_start_user_session (GdmSessionWorker  *worker,
                 dup2 (fd, STDIN_FILENO);
                 close (fd);
 
-                fd = _open_session_log (home_dir);
+                if (worker->priv->is_program_session) {
+                        fd = _open_program_session_log (worker->priv->log_file);
+                } else {
+                        fd = _open_user_session_log (home_dir);
+                }
                 dup2 (fd, STDOUT_FILENO);
                 dup2 (fd, STDERR_FILENO);
                 close (fd);
@@ -1790,15 +1895,22 @@ gdm_session_worker_start_user_session (GdmSessionWorker  *worker,
 }
 
 static gboolean
-gdm_session_worker_open_user_session (GdmSessionWorker  *worker,
-                                      GError           **error)
+gdm_session_worker_open_session (GdmSessionWorker  *worker,
+                                 GError           **error)
 {
         int error_code;
+        int flags;
 
         g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
         g_assert (geteuid () == 0);
 
-        error_code = pam_open_session (worker->priv->pam_handle, 0);
+        flags = 0;
+
+        if (worker->priv->is_program_session) {
+                flags |= PAM_SILENT;
+        }
+
+        error_code = pam_open_session (worker->priv->pam_handle, flags);
 
         if (error_code != PAM_SUCCESS) {
                 g_set_error (error,
@@ -1926,6 +2038,36 @@ on_set_session_name (GdmSessionWorker *worker,
 }
 
 static void
+gdm_session_worker_set_session_type (GdmSessionWorker *worker,
+                                     const char       *session_type)
+{
+        g_free (worker->priv->session_type);
+        worker->priv->session_type = g_strdup (session_type);
+}
+
+static void
+on_set_session_type (GdmSessionWorker *worker,
+                     DBusMessage      *message)
+{
+        DBusError   error;
+        const char *session_type;
+        dbus_bool_t res;
+
+        dbus_error_init (&error);
+        res = dbus_message_get_args (message,
+                                     &error,
+                                     DBUS_TYPE_STRING, &session_type,
+                                     DBUS_TYPE_INVALID);
+        if (res) {
+                g_debug ("GdmSessionWorker: session type set to %s", session_type);
+                gdm_session_worker_set_session_type (worker, session_type);
+        } else {
+                g_warning ("Unable to get arguments: %s", error.message);
+                dbus_error_free (&error);
+        }
+}
+
+static void
 gdm_session_worker_set_language_name (GdmSessionWorker *worker,
                                       const char       *language_name)
 {
@@ -2060,8 +2202,10 @@ do_authenticate (GdmSessionWorker *worker)
         /* we're authenticated.  Let's make sure we've been given
          * a valid username for the system
          */
-        g_debug ("GdmSessionWorker: trying to get updated username");
-        gdm_session_worker_update_username (worker);
+        if (!worker->priv->is_program_session) {
+                g_debug ("GdmSessionWorker: trying to get updated username");
+                gdm_session_worker_update_username (worker);
+        }
 
         send_dbus_void_method (worker->priv->connection, "Authenticated");
 }
@@ -2176,7 +2320,7 @@ do_open_session (GdmSessionWorker *worker)
         gboolean res;
 
         error = NULL;
-        res = gdm_session_worker_open_user_session (worker, &error);
+        res = gdm_session_worker_open_session (worker, &error);
         if (! res) {
                 send_dbus_string_method (worker->priv->connection,
                                          "OpenFailed",
@@ -2195,7 +2339,7 @@ do_start_session (GdmSessionWorker *worker)
         gboolean res;
 
         error = NULL;
-        res = gdm_session_worker_start_user_session (worker, &error);
+        res = gdm_session_worker_start_session (worker, &error);
         if (! res) {
                 send_dbus_string_method (worker->priv->connection,
                                          "StartFailed",
@@ -2447,6 +2591,48 @@ on_setup_for_user (GdmSessionWorker *worker,
 }
 
 static void
+on_setup_for_program (GdmSessionWorker *worker,
+                      DBusMessage      *message)
+{
+        DBusError   error;
+        char *service;
+        char *x11_display_name;
+        char *x11_authority_file;
+        char *log_file;
+        dbus_bool_t res;
+
+        if (worker->priv->state != GDM_SESSION_WORKER_STATE_NONE) {
+                g_debug ("GdmSessionWorker: ignoring spurious setup for program while in state %s", get_state_name (worker->priv->state));
+                return;
+        }
+
+        dbus_error_init (&error);
+        res = dbus_message_get_args (message,
+                                     &error,
+                                     DBUS_TYPE_STRING, &service,
+                                     DBUS_TYPE_STRING, &x11_display_name,
+                                     DBUS_TYPE_STRING, &x11_authority_file,
+                                     DBUS_TYPE_STRING, &log_file,
+                                     DBUS_TYPE_INVALID);
+        if (res) {
+                g_debug ("GdmSessionWorker: program with log file '%s'", log_file);
+
+                queue_state_change (worker);
+                worker->priv->service = g_strdup (service);
+                worker->priv->username = g_strdup (GDM_USERNAME);
+                worker->priv->x11_display_name = g_strdup (x11_display_name);
+                worker->priv->x11_authority_file = g_strdup (x11_authority_file);
+                worker->priv->log_file = g_strdup (log_file);
+                worker->priv->is_program_session = TRUE;
+
+                queue_state_change (worker);
+        } else {
+                g_warning ("Unable to get arguments: %s", error.message);
+                dbus_error_free (&error);
+        }
+}
+
+static void
 on_authenticate (GdmSessionWorker *worker,
                  DBusMessage      *message)
 {
@@ -2562,6 +2748,8 @@ worker_dbus_handle_message (DBusConnection *connection,
                 on_setup (worker, message);
         } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "SetupForUser")) {
                 on_setup_for_user (worker, message);
+        } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "SetupForProgram")) {
+                on_setup_for_program (worker, message);
         } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "Authenticate")) {
                 on_authenticate (worker, message);
         } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "Authorize")) {
@@ -2584,6 +2772,8 @@ worker_dbus_handle_message (DBusConnection *connection,
                 on_set_language_name (worker, message);
         } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "SetSessionName")) {
                 on_set_session_name (worker, message);
+        } else if (dbus_message_is_signal (message, GDM_SESSION_DBUS_INTERFACE, "SetSessionType")) {
+                on_set_session_type (worker, message);
         } else {
                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
         }
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 200e3d7..5ba9fd1 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -126,6 +126,26 @@ gdm_session_setup_for_user (GdmSession *session,
 }
 
 void
+gdm_session_setup_for_program (GdmSession *session,
+                               const char *service_name,
+                               const char *log_file)
+{
+        g_return_if_fail (GDM_IS_SESSION (session));
+
+        GDM_SESSION_GET_IFACE (session)->setup_for_program (session, service_name, log_file);
+}
+
+void
+gdm_session_set_environment_variable (GdmSession *session,
+                                      const char *key,
+                                      const char *value)
+{
+        g_return_if_fail (GDM_IS_SESSION (session));
+
+        GDM_SESSION_GET_IFACE (session)->set_environment_variable (session, key, value);
+}
+
+void
 gdm_session_authenticate (GdmSession *session,
                           const char *service_name)
 {
@@ -164,6 +184,23 @@ gdm_session_answer_query (GdmSession *session,
 }
 
 void
+gdm_session_select_program (GdmSession *session,
+                            const char *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (session));
+
+        GDM_SESSION_GET_IFACE (session)->select_program (session, text);
+}
+
+void
+gdm_session_select_session_type (GdmSession *session,
+                                 const char *text)
+{
+        g_return_if_fail (GDM_IS_SESSION (session));
+
+        GDM_SESSION_GET_IFACE (session)->select_session_type (session, text);
+}
+void
 gdm_session_select_session (GdmSession *session,
                             const char *text)
 {
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index ab16031..17accb2 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -56,6 +56,12 @@ struct _GdmSessionIface
         void (* setup_for_user)              (GdmSession   *session,
                                               const char   *service_name,
                                               const char   *username);
+        void (* setup_for_program)           (GdmSession   *session,
+                                              const char   *service_name,
+                                              const char   *log_file);
+        void (* set_environment_variable)    (GdmSession   *session,
+                                              const char   *key,
+                                              const char   *value);
         void (* reset)                       (GdmSession   *session);
         void (* authenticate)                (GdmSession   *session,
                                               const char   *service_name);
@@ -71,6 +77,10 @@ struct _GdmSessionIface
                                               const char   *text);
         void (* select_language)             (GdmSession   *session,
                                               const char   *text);
+        void (* select_program)              (GdmSession   *session,
+                                              const char   *text);
+        void (* select_session_type)         (GdmSession   *session,
+                                              const char   *session_type);
         void (* select_session)              (GdmSession   *session,
                                               const char   *text);
         void (* select_user)                 (GdmSession   *session,
@@ -157,6 +167,12 @@ void     gdm_session_setup                       (GdmSession *session,
 void     gdm_session_setup_for_user              (GdmSession *session,
                                                   const char *service_name,
                                                   const char *username);
+void     gdm_session_setup_for_program           (GdmSession *session,
+                                                  const char *service_name,
+                                                  const char *log_file);
+void     gdm_session_set_environment_variable    (GdmSession *session,
+                                                  const char *key,
+                                                  const char *value);
 void     gdm_session_reset                       (GdmSession *session);
 void     gdm_session_authenticate                (GdmSession *session,
                                                   const char *service_name);
@@ -174,6 +190,10 @@ void     gdm_session_close                       (GdmSession *session);
 void     gdm_session_answer_query                (GdmSession *session,
                                                   const char *service_name,
                                                   const char *text);
+void     gdm_session_select_program              (GdmSession *session,
+                                                  const char *command_line);
+void     gdm_session_select_session_type         (GdmSession *session,
+                                                  const char *session_type);
 void     gdm_session_select_session              (GdmSession *session,
                                                   const char *session_name);
 void     gdm_session_select_language             (GdmSession *session,
diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c
index 04b3d07..63000f1 100644
--- a/daemon/gdm-welcome-session.c
+++ b/daemon/gdm-welcome-session.c
@@ -44,6 +44,8 @@
 #include "gdm-common.h"
 #include "ck-connector.h"
 
+#include "gdm-session.h"
+#include "gdm-session-direct.h"
 #include "gdm-welcome-session.h"
 
 #define DBUS_LAUNCH_COMMAND BINDIR "/dbus-launch"
@@ -56,10 +58,8 @@ extern char **environ;
 
 struct GdmWelcomeSessionPrivate
 {
+        GdmSession     *session;
         char           *command;
-        GPid            pid;
-
-        CkConnector    *ckc;
 
         char           *user_name;
         char           *group_name;
@@ -72,8 +72,6 @@ struct GdmWelcomeSessionPrivate
         char           *x11_authority_file;
         gboolean        x11_display_is_local;
 
-        guint           child_watch_id;
-
         GPid            dbus_pid;
         char           *dbus_bus_address;
         char           *server_dbus_path;
@@ -130,116 +128,6 @@ listify_hash (const char *key,
         g_ptr_array_add (env, str);
 }
 
-static gboolean
-open_welcome_session (GdmWelcomeSession *welcome_session)
-{
-        struct passwd *pwent;
-        const char    *session_type;
-        const char    *hostname;
-        const char    *x11_display_device;
-        int            res;
-        gboolean       ret;
-        DBusError      error;
-
-        ret = FALSE;
-
-        g_debug ("GdmWelcomeSession: Registering session with ConsoleKit");
-
-        session_type = "LoginWindow";
-
-        gdm_get_pwent_for_name (welcome_session->priv->user_name, &pwent);
-        if (pwent == NULL) {
-                /* FIXME: */
-                g_warning ("Couldn't look up uid");
-                goto out;
-        }
-
-        welcome_session->priv->ckc = ck_connector_new ();
-        if (welcome_session->priv->ckc == NULL) {
-                g_warning ("Couldn't create new ConsoleKit connector");
-                goto out;
-        }
-
-        if (welcome_session->priv->x11_display_hostname != NULL) {
-                hostname = welcome_session->priv->x11_display_hostname;
-        } else {
-                hostname = "";
-        }
-
-        if (welcome_session->priv->x11_display_device != NULL) {
-                x11_display_device = welcome_session->priv->x11_display_device;
-        } else {
-                x11_display_device = "";
-        }
-
-        g_debug ("GdmWelcomeSession: Opening ConsoleKit session for user:%d x11-display:'%s' x11-display-device:'%s' remote-host-name:'%s' is-local:%d",
-                 pwent->pw_uid,
-                 welcome_session->priv->x11_display_name,
-                 x11_display_device,
-                 hostname,
-                 welcome_session->priv->x11_display_is_local);
-
-        dbus_error_init (&error);
-        res = ck_connector_open_session_with_parameters (welcome_session->priv->ckc,
-                                                         &error,
-                                                         "unix-user", &pwent->pw_uid,
-                                                         "session-type", &session_type,
-                                                         "x11-display", &welcome_session->priv->x11_display_name,
-                                                         "x11-display-device", &x11_display_device,
-                                                         "remote-host-name", &hostname,
-                                                         "is-local", &welcome_session->priv->x11_display_is_local,
-                                                         NULL);
-        if (! res) {
-                if (dbus_error_is_set (&error)) {
-                        g_warning ("%s\n", error.message);
-                        dbus_error_free (&error);
-                } else {
-                        g_warning ("cannot open CK session: OOM, D-Bus system bus not available,\n"
-                                   "ConsoleKit not available or insufficient privileges.\n");
-                }
-                goto out;
-        }
-
-        ret = TRUE;
-
- out:
-        return ret;
-}
-
-static gboolean
-close_welcome_session (GdmWelcomeSession *welcome_session)
-{
-        int       res;
-        gboolean  ret;
-        DBusError error;
-
-        ret = FALSE;
-
-        if (welcome_session->priv->ckc == NULL) {
-                return FALSE;
-        }
-
-        g_debug ("GdmWelcomeSession: De-registering session from ConsoleKit");
-
-        dbus_error_init (&error);
-        res = ck_connector_close_session (welcome_session->priv->ckc, &error);
-        if (! res) {
-                if (dbus_error_is_set (&error)) {
-                        g_warning ("%s\n", error.message);
-                        dbus_error_free (&error);
-                } else {
-                        g_warning ("cannot open CK session: OOM, D-Bus system bus not available,\n"
-                                   "ConsoleKit not available or insufficient privileges.\n");
-                }
-                goto out;
-        }
-
-        ret = TRUE;
- out:
-
-        return ret;
-}
-
 static void
 load_lang_config_file (const char  *config_file,
                        const char **str_array)
@@ -343,11 +231,10 @@ next_line:
         g_free (contents);
 }
 
-static GPtrArray *
-get_welcome_environment (GdmWelcomeSession *welcome_session,
-                         gboolean           start_session)
+static GHashTable *
+build_welcome_environment (GdmWelcomeSession *welcome_session,
+                           gboolean           start_session)
 {
-        GPtrArray     *env;
         GHashTable    *hash;
         struct passwd *pwent;
         static const char * const optional_environment[] = {
@@ -362,7 +249,6 @@ get_welcome_environment (GdmWelcomeSession *welcome_session,
 
         load_lang_config_file (LANG_CONFIG_FILE,
                                (const char **) optional_environment);
-        env = g_ptr_array_new ();
 
         /* create a hash table of current environment, then update keys has necessary */
         hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
@@ -400,14 +286,6 @@ get_welcome_environment (GdmWelcomeSession *welcome_session,
         g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (welcome_session->priv->x11_authority_file));
         g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (welcome_session->priv->x11_display_name));
 
-        if (welcome_session->priv->ckc != NULL) {
-                const char *cookie;
-                cookie = ck_connector_get_cookie (welcome_session->priv->ckc);
-                if (cookie != NULL) {
-                        g_hash_table_insert (hash, g_strdup ("XDG_SESSION_COOKIE"), g_strdup (cookie));
-                }
-        }
-
         g_hash_table_insert (hash, g_strdup ("LOGNAME"), g_strdup (welcome_session->priv->user_name));
         g_hash_table_insert (hash, g_strdup ("USER"), g_strdup (welcome_session->priv->user_name));
         g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (welcome_session->priv->user_name));
@@ -445,6 +323,19 @@ get_welcome_environment (GdmWelcomeSession *welcome_session,
         g_hash_table_insert (hash, g_strdup ("GVFS_DISABLE_FUSE"), g_strdup ("1"));
         g_hash_table_insert (hash, g_strdup ("DCONF_PROFILE"), g_strdup ("gdm"));
 
+        return hash;
+}
+
+static GPtrArray *
+get_welcome_environment (GdmWelcomeSession *welcome_session,
+                         gboolean           start_session)
+{
+        GHashTable    *hash;
+        GPtrArray     *env;
+
+        hash = build_welcome_environment (welcome_session, start_session);
+
+        env = g_ptr_array_new ();
         g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
         g_hash_table_destroy (hash);
 
@@ -453,7 +344,6 @@ get_welcome_environment (GdmWelcomeSession *welcome_session,
         return env;
 }
 
-
 static gboolean
 stop_dbus_daemon (GdmWelcomeSession *welcome_session)
 {
@@ -472,37 +362,6 @@ stop_dbus_daemon (GdmWelcomeSession *welcome_session)
 }
 
 static void
-welcome_session_child_watch (GPid               pid,
-                             int                status,
-                             GdmWelcomeSession *session)
-{
-        g_debug ("GdmWelcomeSession: child (pid:%d) done (%s:%d)",
-                 (int) pid,
-                 WIFEXITED (status) ? "status"
-                 : WIFSIGNALED (status) ? "signal"
-                 : "unknown",
-                 WIFEXITED (status) ? WEXITSTATUS (status)
-                 : WIFSIGNALED (status) ? WTERMSIG (status)
-                 : -1);
-
-        if (WIFEXITED (status)) {
-                int code = WEXITSTATUS (status);
-                g_signal_emit (session, signals [EXITED], 0, code);
-        } else if (WIFSIGNALED (status)) {
-                int num = WTERMSIG (status);
-                g_signal_emit (session, signals [DIED], 0, num);
-        }
-
-        g_spawn_close_pid (session->priv->pid);
-        session->priv->pid = -1;
-
-        if (session->priv->ckc != NULL) {
-                close_welcome_session (session);
-        }
-        stop_dbus_daemon (session);
-}
-
-static void
 rotate_logs (const char *path,
              guint       n_copies)
 {
@@ -712,62 +571,6 @@ spawn_command_line_sync_as_user (const char *command_line,
 }
 
 static gboolean
-spawn_command_line_async_as_user (const char *command_line,
-                                  const char *user_name,
-                                  const char *group_name,
-                                  const char *seat_id,
-                                  const char *runtime_dir,
-                                  const char *log_file,
-                                  char      **env,
-                                  GPid       *child_pid,
-                                  GError    **error)
-{
-        char           **argv;
-        GError          *local_error;
-        gboolean         ret;
-        gboolean         res;
-        SpawnChildData   data;
-
-        ret = FALSE;
-
-        argv = NULL;
-        local_error = NULL;
-        if (! g_shell_parse_argv (command_line, NULL, &argv, &local_error)) {
-                g_warning ("Could not parse command: %s", local_error->message);
-                g_propagate_error (error, local_error);
-                goto out;
-        }
-
-        data.user_name = user_name;
-        data.group_name = group_name;
-        data.runtime_dir = runtime_dir;
-        data.log_file = log_file;
-        data.seat_id = seat_id;
-
-        local_error = NULL;
-        res = g_spawn_async (NULL,
-                             argv,
-                             env,
-                             G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
-                             (GSpawnChildSetupFunc)spawn_child_setup,
-                             &data,
-                             child_pid,
-                             &local_error);
-
-        if (! res) {
-                g_warning ("Could not spawn command: %s", local_error->message);
-                g_propagate_error (error, local_error);
-                goto out;
-        }
-
-        ret = TRUE;
- out:
-        g_strfreev (argv);
-
-        return ret;
-}
-
-static gboolean
 parse_value_as_integer (const char *value,
                         int        *intval)
 {
@@ -895,69 +698,105 @@ start_dbus_daemon (GdmWelcomeSession *welcome_session)
         return res;
 }
 
-static gboolean
-gdm_welcome_session_spawn (GdmWelcomeSession *welcome_session)
+static void
+on_session_setup_complete (GdmSession        *session,
+                           const char        *service_name,
+                           GdmWelcomeSession *welcome_session)
 {
-        GError          *error;
-        GPtrArray       *env;
-        gboolean         ret;
-        gboolean         res;
-        char            *log_path;
-        char            *log_file;
+        GHashTable       *hash;
+        GHashTableIter    iter;
+        gpointer          key, value;
 
-        ret = FALSE;
-
-        g_debug ("GdmWelcomeSession: Running welcome_session process: %s", welcome_session->priv->command);
+        hash = build_welcome_environment (welcome_session, TRUE);
 
-        if (welcome_session->priv->register_ck_session) {
-                open_welcome_session (welcome_session);
+        g_hash_table_iter_init (&iter, hash);
+        while (g_hash_table_iter_next (&iter, &key, &value)) {
+                gdm_session_set_environment_variable (GDM_SESSION (welcome_session->priv->session), key, value);
         }
+        g_hash_table_destroy (hash);
 
-        res = start_dbus_daemon (welcome_session);
-        if (! res) {
-                /* FIXME: */
-        }
+        gdm_session_select_session_type (GDM_SESSION (welcome_session->priv->session), "LoginWindow");
 
-        env = get_welcome_environment (welcome_session, TRUE);
+        gdm_session_authenticate (GDM_SESSION (welcome_session->priv->session), service_name);
+}
 
-        error = NULL;
+static void
+on_session_authenticated (GdmSession        *session,
+                          const char        *service_name,
+                          GdmWelcomeSession *welcome_session)
+{
+        gdm_session_authorize (GDM_SESSION (welcome_session->priv->session),
+                               service_name);
+}
 
-        log_file = g_strdup_printf ("%s-greeter.log", welcome_session->priv->x11_display_name);
-        log_path = g_build_filename (LOGDIR, log_file, NULL);
-        g_free (log_file);
+static void
+on_session_authorized (GdmSession        *session,
+                       const char        *service_name,
+                       GdmWelcomeSession *welcome_session)
+{
+        gdm_session_accredit (GDM_SESSION (welcome_session->priv->session),
+                              service_name,
+                              GDM_SESSION_CRED_ESTABLISH);
+}
 
-        ret = spawn_command_line_async_as_user (welcome_session->priv->command,
-                                                welcome_session->priv->user_name,
-                                                welcome_session->priv->group_name,
-                                                welcome_session->priv->x11_display_seat_id,
-                                                welcome_session->priv->runtime_dir,
-                                                log_path,
-                                                (char **)env->pdata,
-                                                &welcome_session->priv->pid,
-                                                &error);
+static void
+on_session_accredited (GdmSession        *session,
+                       const char        *service_name,
+                       GdmWelcomeSession *welcome_session)
+{
+        gdm_session_open_session (GDM_SESSION (welcome_session->priv->session), service_name);
+}
 
-        g_ptr_array_foreach (env, (GFunc)g_free, NULL);
-        g_ptr_array_free (env, TRUE);
+static void
+on_session_opened (GdmSession        *session,
+                   const char        *service_name,
+                   GdmWelcomeSession *welcome_session)
+{
+        gdm_session_start_session (GDM_SESSION (welcome_session->priv->session),
+                                   service_name);
+}
 
-        g_free (log_path);
+static void
+on_session_started (GdmSession        *session,
+                    const char        *service_name,
+                    int                pid,
+                    GdmWelcomeSession *welcome_session)
+{
+        g_signal_emit (G_OBJECT (welcome_session), signals [STARTED], 0);
+}
 
-        if (! ret) {
-                g_warning ("Could not start command '%s': %s",
-                           welcome_session->priv->command,
-                           error->message);
-                g_error_free (error);
-                goto out;
-        } else {
-                g_debug ("GdmWelcomeSession: WelcomeSession on pid %d", (int)welcome_session->priv->pid);
-        }
+static void
+on_session_exited (GdmSession        *session,
+                   int                exit_code,
+                   GdmWelcomeSession *welcome_session)
+{
+        g_signal_emit (G_OBJECT (welcome_session), signals [EXITED], 0, exit_code);
+}
+
+static void
+on_session_died (GdmSession        *session,
+                 int                signal_number,
+                 GdmWelcomeSession *welcome_session)
+{
+        g_signal_emit (G_OBJECT (welcome_session), signals [DIED], 0, signal_number);
+}
 
-        welcome_session->priv->child_watch_id = g_child_watch_add (welcome_session->priv->pid,
-                                                                   (GChildWatchFunc)welcome_session_child_watch,
-                                                                   welcome_session);
+static void
+on_conversation_started (GdmSession        *session,
+                         const char        *service_name,
+                         GdmWelcomeSession *welcome_session)
+{
+        char             *log_path;
+        char             *log_file;
 
- out:
+        log_file = g_strdup_printf ("%s-greeter.log", welcome_session->priv->x11_display_name);
+        log_path = g_build_filename (LOGDIR, log_file, NULL);
+        g_free (log_file);
 
-        return ret;
+        gdm_session_setup_for_program (GDM_SESSION (welcome_session->priv->session),
+                                       "gdm-welcome",
+                                       log_path);
+        g_free (log_path);
 }
 
 /**
@@ -969,66 +808,76 @@ gdm_welcome_session_spawn (GdmWelcomeSession *welcome_session)
 gboolean
 gdm_welcome_session_start (GdmWelcomeSession *welcome_session)
 {
-        gboolean    res;
+        gboolean          res;
 
         g_debug ("GdmWelcomeSession: Starting welcome...");
+        res = start_dbus_daemon (welcome_session);
 
-        res = gdm_welcome_session_spawn (welcome_session);
-
-        if (res) {
-
-        }
-
-
-        return res;
-}
-
-static void
-welcome_session_died (GdmWelcomeSession *welcome_session)
-{
-        int exit_status;
-
-        g_debug ("GdmWelcomeSession: Waiting on process %d", welcome_session->priv->pid);
-        exit_status = gdm_wait_on_pid (welcome_session->priv->pid);
-
-        if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
-                g_debug ("GdmWelcomeSession: Wait on child process failed");
-        } else {
-                /* exited normally */
+        if (!res) {
+                return FALSE;
         }
 
-        g_spawn_close_pid (welcome_session->priv->pid);
-        welcome_session->priv->pid = -1;
-
-        g_debug ("GdmWelcomeSession: WelcomeSession died");
+        welcome_session->priv->session = GDM_SESSION (gdm_session_direct_new (NULL,
+                                                                              welcome_session->priv->x11_display_name,
+                                                                              welcome_session->priv->x11_display_hostname,
+                                                                              welcome_session->priv->x11_display_device,
+                                                                              welcome_session->priv->x11_authority_file,
+                                                                              welcome_session->priv->x11_display_is_local));
+
+        g_signal_connect (GDM_SESSION (welcome_session->priv->session),
+                          "conversation-started",
+                          G_CALLBACK (on_conversation_started),
+                          welcome_session);
+        g_signal_connect (welcome_session->priv->session,
+                          "setup-complete",
+                          G_CALLBACK (on_session_setup_complete),
+                          welcome_session);
+        g_signal_connect (welcome_session->priv->session,
+                          "authenticated",
+                          G_CALLBACK (on_session_authenticated),
+                          welcome_session);
+        g_signal_connect (welcome_session->priv->session,
+                          "authorized",
+                          G_CALLBACK (on_session_authorized),
+                          welcome_session);
+        g_signal_connect (welcome_session->priv->session,
+                          "accredited",
+                          G_CALLBACK (on_session_accredited),
+                          welcome_session);
+        g_signal_connect (welcome_session->priv->session,
+                          "session-opened",
+                          G_CALLBACK (on_session_opened),
+                          welcome_session);
+        g_signal_connect (GDM_SESSION (welcome_session->priv->session),
+                          "session-started",
+                          G_CALLBACK (on_session_started),
+                          welcome_session);
+        g_signal_connect (GDM_SESSION (welcome_session->priv->session),
+                          "session-exited",
+                          G_CALLBACK (on_session_exited),
+                          welcome_session);
+        g_signal_connect (GDM_SESSION (welcome_session->priv->session),
+                          "session-died",
+                          G_CALLBACK (on_session_died),
+                          welcome_session);
+
+        gdm_session_start_conversation (GDM_SESSION (welcome_session->priv->session),
+                                        "gdm-welcome");
+        gdm_session_select_program (GDM_SESSION (welcome_session->priv->session),
+                                    welcome_session->priv->command);
+        return TRUE;
 }
 
 gboolean
 gdm_welcome_session_stop (GdmWelcomeSession *welcome_session)
 {
-        int res;
-
-        if (welcome_session->priv->pid <= 1) {
-                return TRUE;
-        }
-
-        /* remove watch source before we can wait on child */
-        if (welcome_session->priv->child_watch_id > 0) {
-                g_source_remove (welcome_session->priv->child_watch_id);
-                welcome_session->priv->child_watch_id = 0;
-        }
+        if (welcome_session->priv->session != NULL) {
+                gdm_session_stop_conversation (GDM_SESSION (welcome_session->priv->session),
+                                               "gdm-welcome");
+                gdm_session_close (GDM_SESSION (welcome_session->priv->session));
 
-        g_debug ("GdmWelcomeSession: Stopping welcome_session");
-
-        res = gdm_signal_pid (welcome_session->priv->pid, SIGTERM);
-        if (res < 0) {
-                g_warning ("Unable to kill welcome session process");
-        } else {
-                welcome_session_died (welcome_session);
-        }
-
-        if (welcome_session->priv->ckc != NULL) {
-                close_welcome_session (welcome_session);
+                g_object_unref (welcome_session->priv->session);
+                welcome_session->priv->session = NULL;
         }
 
         stop_dbus_daemon (welcome_session);
@@ -1085,7 +934,6 @@ _gdm_welcome_session_set_x11_display_is_local (GdmWelcomeSession *welcome_sessio
         welcome_session->priv->x11_display_is_local = is_local;
 }
 
-
 static void
 _gdm_welcome_session_set_x11_authority_file (GdmWelcomeSession *welcome_session,
                                              const char        *file)
@@ -1447,9 +1295,8 @@ gdm_welcome_session_init (GdmWelcomeSession *welcome_session)
 
         welcome_session->priv = GDM_WELCOME_SESSION_GET_PRIVATE (welcome_session);
 
-        welcome_session->priv->pid = -1;
-
         welcome_session->priv->command = NULL;
+        welcome_session->priv->session = NULL;
 }
 
 static void
@@ -1466,8 +1313,8 @@ gdm_welcome_session_finalize (GObject *object)
 
         gdm_welcome_session_stop (welcome_session);
 
-        if (welcome_session->priv->ckc != NULL) {
-                ck_connector_unref (welcome_session->priv->ckc);
+        if (welcome_session->priv->session) {
+                g_object_unref (welcome_session->priv->session);
         }
 
         g_free (welcome_session->priv->command);
diff --git a/data/Makefile.am b/data/Makefile.am
index 1a70994..aa2f265 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -94,6 +94,7 @@ EXTRA_DIST =			\
 	Xsession.in 		\
 	gdm 			\
 	gdm-autologin 		\
+	gdm-welcome 		\
 	Init.in 		\
 	PreSession.in 		\
 	PostSession.in 		\
@@ -140,6 +141,7 @@ uninstall-hook:
 	$(DESTDIR)$(postdir)/Default \
 	$(DESTDIR)$(PAM_PREFIX)/pam.d/gdm \
 	$(DESTDIR)$(PAM_PREFIX)/pam.d/gdm-autologin \
+	$(DESTDIR)$(PAM_PREFIX)/pam.d/gdm-welcome \
 	$(DESTDIR)$(workingdir)/.gconf.path \
 	$(DESTDIR)$(sysconfdir)/dconf/db/gdm \
 	$(DESTDIR)$(sysconfdir)/dconf/profile/gdm \
@@ -222,8 +224,11 @@ install-data-hook: gdm.conf-custom Xsession Init PostSession PreSession gconf.pa
 	   if test $$system = Linux && test '!' -f $(DESTDIR)$(PAM_PREFIX)/pam.d/gdm-autologin; then \
 		$(INSTALL_DATA) $(srcdir)/gdm-autologin $(DESTDIR)$(PAM_PREFIX)/pam.d/gdm-autologin; \
 	   fi; \
+	   if test $$system = Linux && test '!' -f $(DESTDIR)$(PAM_PREFIX)/pam.d/gdm-welcome; then \
+		$(INSTALL_DATA) $(srcdir)/gdm-welcome $(DESTDIR)$(PAM_PREFIX)/pam.d/gdm-welcome; \
+	   fi; \
 	   if test $$system = SunOS; then \
-		echo "Please add PAM authentication for gdm and gdm-autologin in $(PAM_PREFIX)/pam.conf!"; \
+		echo "Please add PAM authentication for gdm, gdm-autologin and gdm-welcome in $(PAM_PREFIX)/pam.conf!"; \
 	   fi; \
 	fi
 
diff --git a/data/gdm-welcome b/data/gdm-welcome
new file mode 100644
index 0000000..9f64259
--- /dev/null
+++ b/data/gdm-welcome
@@ -0,0 +1,4 @@
+#%PAM-1.0
+session    optional    pam_keyinit.so force revoke
+session    include     system-auth
+session    required    pam_loginuid.so



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]