[gdm/wip/wayland] hackity hack, sketchity sketch



commit 15c32e6467093ab4cc582aa609015f10b4a4aac4
Author: Ray Strode <rstrode redhat com>
Date:   Fri Sep 13 17:06:02 2013 -0400

    hackity hack, sketchity sketch
    
    This commit is a rough start at trying to get wayland sessions working
    from the login screen.
    
    It's not fully functional, but I can log in (just not log out).

 daemon/gdm-session-worker-job.c |    2 +
 daemon/gdm-session-worker.c     |  237 +++++++++++++++++++++++++++++----------
 daemon/gdm-session.c            |   48 ++++++++
 daemon/gdm-session.h            |    1 +
 daemon/gdm-simple-slave.c       |   10 ++
 daemon/gdm-slave.c              |    1 +
 6 files changed, 242 insertions(+), 57 deletions(-)
---
diff --git a/daemon/gdm-session-worker-job.c b/daemon/gdm-session-worker-job.c
index 557c452..7193d5d 100644
--- a/daemon/gdm-session-worker-job.c
+++ b/daemon/gdm-session-worker-job.c
@@ -86,9 +86,11 @@ static void
 session_worker_job_child_setup (GdmSessionWorkerJob *session_worker_job)
 {
         /* Terminate the process when the parent dies */
+#if 0
 #ifdef HAVE_SYS_PRCTL_H
         prctl (PR_SET_PDEATHSIG, SIGTERM);
 #endif
+#endif
 }
 
 static void
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 7307872..e6a725c 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -54,6 +54,10 @@
 #include <systemd/sd-journal.h>
 #endif
 
+#include <linux/vt.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
 #ifdef HAVE_SELINUX
 #include <selinux/selinux.h>
 #endif /* HAVE_SELINUX */
@@ -152,6 +156,7 @@ struct GdmSessionWorkerPrivate
         gboolean          password_is_required;
 
         int               cred_flags;
+        int               vt;
 
         char            **arguments;
         guint32           cancelled : 1;
@@ -1024,11 +1029,7 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
                                    GError          **error)
 {
         struct pam_conv        pam_conversation;
-#ifdef PAM_XAUTHDATA
-        struct pam_xauth_data *pam_xauth;
-#endif
         int                    error_code;
-        char                  *pam_tty;
 
         g_assert (worker->priv->pam_handle == NULL);
 
@@ -1089,25 +1090,6 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
                 }
         }
 
-        /* set TTY */
-        pam_tty = _get_tty_for_pam (x11_display_name, display_device);
-        if (pam_tty != NULL && pam_tty[0] != '\0') {
-                error_code = pam_set_item (worker->priv->pam_handle, PAM_TTY, pam_tty);
-        }
-
-        if (error_code != PAM_SUCCESS) {
-                g_debug ("error informing authentication system of user's console %s: %s",
-                         pam_tty,
-                         pam_strerror (worker->priv->pam_handle, error_code));
-                g_free (pam_tty);
-                g_set_error (error,
-                             GDM_SESSION_WORKER_ERROR,
-                             GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
-                             "%s", "");
-                goto out;
-        }
-        g_free (pam_tty);
-
 #ifdef WITH_SYSTEMD
         /* set seat ID */
         if (seat_id != NULL && seat_id[0] != '\0' && LOGIND_RUNNING()) {
@@ -1119,40 +1101,6 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
                 gdm_session_worker_set_environment_variable (worker, "XDG_SESSION_CLASS", "greeter");
         }
 
-#ifdef PAM_XDISPLAY
-        /* set XDISPLAY */
-        error_code = pam_set_item (worker->priv->pam_handle, PAM_XDISPLAY, x11_display_name);
-
-        if (error_code != PAM_SUCCESS) {
-                g_debug ("error informing authentication system of display string %s: %s",
-                         x11_display_name,
-                         pam_strerror (worker->priv->pam_handle, error_code));
-                g_set_error (error,
-                             GDM_SESSION_WORKER_ERROR,
-                             GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
-                             "%s", "");
-                goto out;
-        }
-#endif
-#ifdef PAM_XAUTHDATA
-        /* set XAUTHDATA */
-        pam_xauth = _get_xauth_for_pam (x11_authority_file);
-        error_code = pam_set_item (worker->priv->pam_handle, PAM_XAUTHDATA, pam_xauth);
-        if (error_code != PAM_SUCCESS) {
-                g_debug ("error informing authentication system of display string %s: %s",
-                         x11_display_name,
-                         pam_strerror (worker->priv->pam_handle, error_code));
-                g_free (pam_xauth);
-
-                g_set_error (error,
-                             GDM_SESSION_WORKER_ERROR,
-                             GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
-                             "%s", "");
-                goto out;
-        }
-        g_free (pam_xauth);
-#endif
-
         g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
         worker->priv->state = GDM_SESSION_WORKER_STATE_SETUP_COMPLETE;
 
@@ -1783,6 +1731,18 @@ out:
         return fd;
 }
 
+static void
+jump_to_vt (GdmSessionWorker  *worker,
+            int                vt_number)
+{
+        int fd;
+
+        fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
+        ioctl(fd, VT_ACTIVATE, vt_number);
+        ioctl(fd, VT_WAITACTIVE, vt_number);
+        close(fd);
+}
+
 static gboolean
 gdm_session_worker_start_session (GdmSessionWorker  *worker,
                                   GError           **error)
@@ -1802,6 +1762,10 @@ gdm_session_worker_start_session (GdmSessionWorker  *worker,
 
         error_code = PAM_SUCCESS;
 
+        if (worker->priv->vt > 0) {
+                jump_to_vt (worker, worker->priv->vt);
+        }
+
         session_pid = fork ();
 
         if (session_pid < 0) {
@@ -1958,6 +1922,159 @@ gdm_session_worker_start_session (GdmSessionWorker  *worker,
         return TRUE;
 }
 
+static const char **
+get_system_session_dirs (void)
+{
+        static const char *search_dirs[] = {
+                "/etc/X11/sessions/",
+                DMCONFDIR "/Sessions/",
+                DATADIR "/xsessions/",
+                DATADIR "/gdm/BuiltInSessions/",
+                NULL
+        };
+
+        return search_dirs;
+}
+
+static gboolean
+gdm_session_worker_needs_vt (GdmSessionWorker *worker)
+{
+        GError     *error;
+        GKeyFile   *key_file;
+        gboolean    res;
+        gboolean    needs_vt = FALSE;
+        char       *session_name, *filename;
+
+        session_name = gdm_session_settings_get_session_name (worker->priv->user_settings);
+        filename = g_strdup_printf ("%s.desktop", session_name);
+        g_free (session_name);
+
+        key_file = g_key_file_new ();
+        error = NULL;
+        res = g_key_file_load_from_dirs (key_file,
+                                         filename,
+                                         get_system_session_dirs (),
+                                         NULL,
+                                         G_KEY_FILE_NONE,
+                                         &error);
+        if (! res) {
+                g_debug ("GdmSession: File '%s' not found: %s", filename, error->message);
+                goto out;
+        }
+
+        error = NULL;
+        res = g_key_file_has_key (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-NeedsVT", NULL);
+        if (!res) {
+                goto out;
+        } else {
+                needs_vt = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-NeedsVT", 
&error);
+                if (error) {
+                        needs_vt = FALSE;
+                        g_error_free (error);
+                        goto out;
+                }
+                if (needs_vt) {
+                        g_debug ("GdmSession: Session %s needs VT", filename);
+                }
+        }
+
+out:
+        g_free (filename);
+        return needs_vt;
+}
+
+static gboolean
+set_up_for_new_vt (GdmSessionWorker  *worker,
+                   GError           **error)
+{
+        int fd;
+        char vt_string[256] = "", tty_string[256] = "";
+        int vt_number = 0;
+
+        fd = open("/dev/tty0", O_RDWR | O_NOCTTY);
+        ioctl(fd, VT_OPENQRY, &vt_number);
+        worker->priv->vt = vt_number;
+        close(fd);
+
+        g_snprintf(vt_string, 256, "%d", vt_number);
+        g_snprintf(tty_string, 256, "tty%d", vt_number);
+
+        gdm_session_worker_set_environment_variable (worker,
+                                                     "XDG_VTNR",
+                                                     vt_string);
+
+        pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
+
+        return TRUE;
+}
+
+static gboolean
+set_up_for_current_vt (GdmSessionWorker  *worker,
+                       GError           **error)
+{
+#ifdef PAM_XAUTHDATA
+        struct pam_xauth_data *pam_xauth;
+#endif
+        int                    error_code;
+        char                  *pam_tty;
+
+        /* set TTY */
+        pam_tty = _get_tty_for_pam (worker->priv->x11_display_name, worker->priv->display_device);
+        if (pam_tty != NULL && pam_tty[0] != '\0') {
+                error_code = pam_set_item (worker->priv->pam_handle, PAM_TTY, pam_tty);
+        }
+
+        if (error_code != PAM_SUCCESS) {
+                g_debug ("error informing authentication system of user's console %s: %s",
+                         pam_tty,
+                         pam_strerror (worker->priv->pam_handle, error_code));
+                g_free (pam_tty);
+                g_set_error (error,
+                             GDM_SESSION_WORKER_ERROR,
+                             GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
+                             "%s", "");
+                goto out;
+        }
+        g_free (pam_tty);
+
+#ifdef PAM_XDISPLAY
+        /* set XDISPLAY */
+        error_code = pam_set_item (worker->priv->pam_handle, PAM_XDISPLAY, worker->priv->x11_display_name);
+
+        if (error_code != PAM_SUCCESS) {
+                g_debug ("error informing authentication system of display string %s: %s",
+                         worker->priv->x11_display_name,
+                         pam_strerror (worker->priv->pam_handle, error_code));
+                g_set_error (error,
+                             GDM_SESSION_WORKER_ERROR,
+                             GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
+                             "%s", "");
+                goto out;
+        }
+#endif
+#ifdef PAM_XAUTHDATA
+        /* set XAUTHDATA */
+        pam_xauth = _get_xauth_for_pam (worker->priv->x11_authority_file);
+        error_code = pam_set_item (worker->priv->pam_handle, PAM_XAUTHDATA, pam_xauth);
+        if (error_code != PAM_SUCCESS) {
+                g_debug ("error informing authentication system of display string %s: %s",
+                         worker->priv->x11_display_name,
+                         pam_strerror (worker->priv->pam_handle, error_code));
+                g_free (pam_xauth);
+
+                g_set_error (error,
+                             GDM_SESSION_WORKER_ERROR,
+                             GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
+                             "%s", "");
+                goto out;
+        }
+        g_free (pam_xauth);
+#endif
+        return TRUE;
+out:
+        return FALSE;
+}
+
 static gboolean
 gdm_session_worker_open_session (GdmSessionWorker  *worker,
                                  GError           **error)
@@ -1969,6 +2086,12 @@ gdm_session_worker_open_session (GdmSessionWorker  *worker,
         g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
         g_assert (geteuid () == 0);
 
+        if (gdm_session_worker_needs_vt (worker)) {
+                set_up_for_new_vt (worker, NULL);
+        } else {
+                set_up_for_current_vt (worker, NULL);
+        }
+
         flags = 0;
 
         if (worker->priv->is_program_session) {
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index d74bed6..c9b9440 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -2719,6 +2719,54 @@ out:
         return bypasses_xsession;
 }
 
+gboolean
+gdm_session_needs_vt (GdmSession *self)
+{
+        GError     *error;
+        GKeyFile   *key_file;
+        gboolean    res;
+        gboolean    needs_vt = FALSE;
+        char       *filename;
+
+        g_return_val_if_fail (self != NULL, FALSE);
+        g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
+
+        filename = g_strdup_printf ("%s.desktop", get_session_name (self));
+
+        key_file = g_key_file_new ();
+        error = NULL;
+        res = g_key_file_load_from_dirs (key_file,
+                                         filename,
+                                         get_system_session_dirs (),
+                                         NULL,
+                                         G_KEY_FILE_NONE,
+                                         &error);
+        if (! res) {
+                g_debug ("GdmSession: File '%s' not found: %s", filename, error->message);
+                goto out;
+        }
+
+        error = NULL;
+        res = g_key_file_has_key (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-NeedsVT", NULL);
+        if (!res) {
+                goto out;
+        } else {
+                needs_vt = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-NeedsVT", 
&error);
+                if (error) {
+                        needs_vt = FALSE;
+                        g_error_free (error);
+                        goto out;
+                }
+                if (needs_vt) {
+                        g_debug ("GdmSession: Session %s runs on its own VT", filename);
+                }
+        }
+
+out:
+        g_free (filename);
+        return needs_vt;
+}
+
 void
 gdm_session_select_program (GdmSession *self,
                             const char *text)
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index 2511eca..3af06c1 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -110,6 +110,7 @@ char             *gdm_session_get_display_device          (GdmSession     *sessi
 char             *gdm_session_get_display_seat_id         (GdmSession     *session);
 char             *gdm_session_get_session_id              (GdmSession     *session);
 gboolean          gdm_session_bypasses_xsession           (GdmSession     *session);
+gboolean          gdm_session_needs_vt                    (GdmSession *self);
 
 void              gdm_session_start_conversation          (GdmSession *session,
                                                            const char *service_name);
diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
index 217c33b..e74d38b 100644
--- a/daemon/gdm-simple-slave.c
+++ b/daemon/gdm-simple-slave.c
@@ -129,6 +129,7 @@ static void create_new_session (GdmSimpleSlave  *slave);
 static void start_session      (GdmSimpleSlave  *slave);
 static void queue_start_session (GdmSimpleSlave *slave,
                                  const char     *service_name);
+static void setup_session (GdmSimpleSlave *slave);
 
 static gboolean
 chown_file (GFile   *file,
@@ -519,10 +520,16 @@ static gboolean
 start_session_timeout (GdmSimpleSlave  *slave)
 {
         gboolean migrated;
+        gboolean needs_vt;
         gboolean fail_if_already_switched = TRUE;
 
         g_debug ("GdmSimpleSlave: accredited");
 
+        needs_vt = gdm_session_needs_vt (slave->priv->session);
+        if (needs_vt) {
+                fail_if_already_switched = FALSE;
+        }
+
         /* If there's already a session running, jump to it.
          * If the only session running is the one we just opened,
          * start a session on it.
@@ -537,6 +544,7 @@ start_session_timeout (GdmSimpleSlave  *slave)
                    when Xorg exits it switches to the VT it was
                    started from.  That interferes with fast
                    user switching. */
+                // WAYLAND FIXME: we need to disown the session and create a new one
                 gdm_session_reset (slave->priv->session);
 
                 slave->priv->start_session_id = 0;
@@ -969,6 +977,7 @@ create_new_session (GdmSimpleSlave  *slave)
                           "session-started",
                           G_CALLBACK (on_session_started),
                           slave);
+#if 0
         g_signal_connect (slave->priv->session,
                           "session-exited",
                           G_CALLBACK (on_session_exited),
@@ -977,6 +986,7 @@ create_new_session (GdmSimpleSlave  *slave)
                           "session-died",
                           G_CALLBACK (on_session_died),
                           slave);
+#endif
 
         start_autologin_conversation_if_necessary (slave);
 
diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
index 128a800..3636b68 100644
--- a/daemon/gdm-slave.c
+++ b/daemon/gdm-slave.c
@@ -1264,6 +1264,7 @@ gdm_slave_get_primary_session_id_for_user_from_systemd (GdmSlave   *slave,
                         continue;
                 }
 
+                /* WAYLAND FIXME:  WE CAN"T FILTER OUT X11 session here unless we can make wayland show up 
as an X11 session */
                 is_x11 = g_strcmp0 (type, "x11") == 0;
                 free (type);
 


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