summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'gnome-base/gdm/files/gdm-2.32.0-fix-vt-problems.patch')
-rw-r--r--gnome-base/gdm/files/gdm-2.32.0-fix-vt-problems.patch195
1 files changed, 195 insertions, 0 deletions
diff --git a/gnome-base/gdm/files/gdm-2.32.0-fix-vt-problems.patch b/gnome-base/gdm/files/gdm-2.32.0-fix-vt-problems.patch
new file mode 100644
index 0000000..f219a14
--- /dev/null
+++ b/gnome-base/gdm/files/gdm-2.32.0-fix-vt-problems.patch
@@ -0,0 +1,195 @@
+From 64002e623fea54ab10040206d164c5fdee4a43d2 Mon Sep 17 00:00:00 2001
+From: Nirbheek Chauhan <nirbheek@gentoo.org>
+Date: Fri, 15 Apr 2011 22:13:44 +0530
+Subject: [PATCH] Fix VT grab race with getty causing X to grab the wrong VT
+
+On bootup, if X is spawned without any args, it'll take up the first unused VT.
+If GDM starts up before gettys are spawned, X takes up VT1 or VT2 depending on
+the init system and bootsplash.
+
+This is problematic because afterwards getty will come up underneath X, and
+cause keyboard problems and eventually crash X.
+
+So we read /etc/inittab, check for open VTs, compare the two values, and take
+the conservative one.
+---
+ configure.ac | 4 ++
+ daemon/Makefile.am | 1 +
+ daemon/gdm-server.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 110 insertions(+), 1 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index ca0f8bb..b9e7462 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -302,6 +302,10 @@ AC_CHECK_TYPE(socklen_t,,
+ AC_CHECK_HEADERS(sys/sockio.h)
+ AC_CHECK_FUNCS([setresuid setenv unsetenv clearenv])
+
++dnl Needed for querying the kernel for free VTs
++AC_CHECK_HEADERS(sys/vt.h)
++AC_CHECK_HEADERS(sys/ioctl.h)
++
+ dnl checks needed for Darwin compatibility to linux **environ.
+ AC_CHECK_HEADERS(crt_externs.h)
+ AC_CHECK_FUNCS(_NSGetEnviron)
+diff --git a/daemon/Makefile.am b/daemon/Makefile.am
+index da18835..c1b6bda 100644
+--- a/daemon/Makefile.am
++++ b/daemon/Makefile.am
+@@ -14,6 +14,7 @@ AM_CPPFLAGS = \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DLOGDIR=\"$(logdir)\" \
+ -DSBINDIR=\"$(sbindir)\" \
++ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+ -DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \
+ -DGDM_SCREENSHOT_DIR=\"$(GDM_SCREENSHOT_DIR)\" \
+diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
+index 339f3cc..29d16dc 100644
+--- a/daemon/gdm-server.c
++++ b/daemon/gdm-server.c
+@@ -26,6 +26,8 @@
+ #include <unistd.h>
+ #include <string.h>
+ #include <sys/types.h>
++#include <sys/ioctl.h>
++#include <sys/vt.h>
+ #include <sys/wait.h>
+ #include <errno.h>
+ #include <ctype.h>
+@@ -42,6 +44,7 @@
+ #include <glib/gi18n.h>
+ #include <glib/gstdio.h>
+ #include <glib-object.h>
++#include <gio/gio.h>
+
+ #include <X11/Xlib.h> /* for Display */
+
+@@ -54,6 +57,8 @@ extern char **environ;
+
+ #define GDM_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SERVER, GdmServerPrivate))
+
++#define INITTAB SYSCONFDIR"/inittab"
++
+ /* These are the servstat values, also used as server
+ * process exit codes */
+ #define SERVER_TIMEOUT 2 /* Server didn't start */
+@@ -674,6 +679,105 @@ gdm_server_spawn (GdmServer *server,
+ }
+
+ /**
++ * Parse the inittab file used by getty to spawn VTs to find unused ttys
++ */
++static int
++get_free_vt_from_inittab ()
++{
++ GFile *gfile;
++ GFileInputStream *contents;
++ GDataInputStream *dstream;
++ GRegex *getty;
++ GMatchInfo *tty_match = NULL;
++ GSList *tty_list = NULL;
++ GError *error = NULL;
++ gchar *temp = NULL;
++ int vtno = 0;
++
++ gfile = g_file_new_for_path (INITTAB);
++ contents = g_file_read (gfile, NULL, &error);
++ g_object_unref (gfile);
++ if (!contents) {
++ if (error) {
++ g_debug ("Unable to open file %s", INITTAB);
++ g_error_free (error);
++ }
++ goto out;
++ }
++
++ dstream = g_data_input_stream_new (G_INPUT_STREAM (contents));
++ getty = g_regex_new ("^c[0-9]+:.+getty.+tty([0-9]+)", 0, 0, NULL);
++ g_object_unref (contents);
++
++ while (1) {
++ temp = g_data_input_stream_read_line (dstream, NULL, NULL, &error);
++ if (!temp)
++ break;
++ if (!g_regex_match (getty, temp, 0, &tty_match))
++ continue;
++ g_free (temp);
++ temp = g_match_info_fetch (tty_match, 1);
++ if (!temp)
++ continue;
++ tty_list = g_slist_insert_sorted (tty_list, temp, (GCompareFunc)g_strcmp0);
++ g_match_info_free (tty_match);
++ }
++
++ if (error) {
++ g_debug ("Unable to read line from %s", INITTAB);
++ g_error_free (error);
++ goto free;
++ }
++
++ /* Ignore holes in vt allocation, just take the last one */
++ temp = g_slist_last (tty_list)->data;
++ if (temp)
++ vtno = (int) g_ascii_strtoull (temp, NULL, 10) + 1;
++
++free:
++ g_object_unref (dstream);
++ g_regex_unref (getty);
++ g_slist_free_full (tty_list, g_free);
++ g_free (error);
++out:
++ return vtno;
++}
++
++/**
++ * Query the VT_* kernel ioctls to find an empty tty
++ */
++static int
++get_free_vt_from_kernel()
++{
++ int fd, vtno = 0;
++
++ fd = open ("/dev/tty0", O_WRONLY, 0);
++ if ((ioctl(fd, VT_OPENQRY, &vtno) < 0) || (vtno == -1)) {
++ vtno = 0;
++ g_debug ("Unable to find a free vt, falling back to Xorg autodetect");
++ }
++ return vtno;
++}
++
++static gchar*
++get_free_vt ()
++{
++ int inittab_vtno, kernel_vtno;
++ gchar* vt = NULL;
++
++ inittab_vtno = get_free_vt_from_inittab();
++ if (inittab_vtno > 0)
++ g_debug ("Inittab says vt%i is free\n", inittab_vtno);
++ kernel_vtno = get_free_vt_from_kernel();
++ if (kernel_vtno > 0)
++ g_debug ("Kernel says vt%i is free\n", kernel_vtno);
++ /* Select the greater of the two because getty will use the others */
++ if (kernel_vtno != 0 && inittab_vtno != 0)
++ vt = g_strdup_printf ("vt%i", kernel_vtno > inittab_vtno ? kernel_vtno : inittab_vtno);
++ return vt;
++}
++
++/**
+ * gdm_server_start:
+ * @disp: Pointer to a GdmDisplay structure
+ *
+@@ -686,7 +790,7 @@ gdm_server_start (GdmServer *server)
+ gboolean res;
+
+ /* fork X server process */
+- res = gdm_server_spawn (server, NULL);
++ res = gdm_server_spawn (server, get_free_vt());
+
+ return res;
+ }
+--
+1.7.3.4
+