diff options
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.patch | 195 |
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 + |