From 1dba5a0b194653b0effb01a918bd7338b0c6bcb9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 21 Jan 2015 09:31:39 +0100 Subject: [PATCH] linux: Add linux_parse_vt_settings and linux_get_keeptty helpers systemd-logind integration does not work when starting X on a new tty, as that detaches X from the current session and after hat systemd-logind revokes all rights on any already open fds and refuses to open new fds for X. This means that currently e.g. "startx -- vt7" breaks, and breaks badly, requiring ssh access to the system to kill X. The fix for this is easy, we must not use systemd-logind integration when not using KeepTty, or iow we may only use systemd-logind integration together with KeepTty. But the final KeepTty value is not known until the code to chose which vtno to run on has been called, which currently happens after intializing systemd-logind. This commit is step 1 in fixing the "startx -- vt7" breakage, it factors out the linux xf86OpenConsole bits which set xf86Info.vtno and keepTty so that these can be called earlier. Calling this earlier is safe as this code has no side effects other than setting xf86Info.vtno and keepTty. Note this basically only moves a large chunk of xf86OpenConsole() into linux_parse_vt_settings() without changing a single line of it, this is hard to see in the diff because the identation level has changed. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer --- hw/xfree86/os-support/linux/linux.h | 32 ++++++++ hw/xfree86/os-support/linux/lnx_init.c | 126 +++++++++++++++++++-------------- 2 files changed, 107 insertions(+), 51 deletions(-) create mode 100644 hw/xfree86/os-support/linux/linux.h --- /dev/null +++ b/hw/xfree86/os-support/linux/linux.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Hans de Goede + */ + +#ifndef XF86_LINUX_H +#define XF86_LINUX_H + +void linux_parse_vt_settings(void); +int linux_get_keeptty(void); + +#endif --- a/hw/xfree86/os-support/linux/lnx_init.c +++ b/hw/xfree86/os-support/linux/lnx_init.c @@ -31,6 +31,7 @@ #include #include "compiler.h" +#include "linux.h" #include "xf86.h" #include "xf86Priv.h" @@ -87,71 +88,94 @@ switch_to(int vt, const char *from, Bool #pragma GCC diagnostic ignored "-Wformat-nonliteral" void -xf86OpenConsole(void) +linux_parse_vt_settings(void) { int i, fd = -1, ret, current_vt = -1; - struct vt_mode VT; struct vt_stat vts; struct stat st; MessageType from = X_PROBED; const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; - const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; - if (serverGeneration == 1) { - /* - * setup the virtual terminal manager - */ - if (xf86Info.vtno != -1) { - from = X_CMDLINE; - } - else { + /* Only do this once */ + static int vt_settings_parsed = 0; - i = 0; - while (tty0[i] != NULL) { - if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) - break; - i++; - } - - if (fd < 0) - FatalError("xf86OpenConsole: Cannot open /dev/tty0 (%s)\n", - strerror(errno)); - - if (xf86Info.ShareVTs) { - SYSCALL(ret = ioctl(fd, VT_GETSTATE, &vts)); - if (ret < 0) - FatalError("xf86OpenConsole: Cannot find the current" - " VT (%s)\n", strerror(errno)); - xf86Info.vtno = vts.v_active; - } - else { - SYSCALL(ret = ioctl(fd, VT_OPENQRY, &xf86Info.vtno)); - if (ret < 0) - FatalError("xf86OpenConsole: Cannot find a free VT: " - "%s\n", strerror(errno)); - if (xf86Info.vtno == -1) - FatalError("xf86OpenConsole: Cannot find a free VT\n"); - } - close(fd); - } + if (vt_settings_parsed) + return; - xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno); + /* + * setup the virtual terminal manager + */ + if (xf86Info.vtno != -1) { + from = X_CMDLINE; + } + else { - /* Some of stdin / stdout / stderr maybe redirected to a file */ - for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) { - ret = fstat(i, &st); - if (ret == 0 && S_ISCHR(st.st_mode) && major(st.st_rdev) == 4) { - current_vt = minor(st.st_rdev); + i = 0; + while (tty0[i] != NULL) { + if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) break; - } + i++; } - if (!KeepTty && current_vt == xf86Info.vtno) { - xf86Msg(X_PROBED, - "controlling tty is VT number %d, auto-enabling KeepTty\n", - current_vt); - KeepTty = TRUE; + if (fd < 0) + FatalError("parse_vt_settings: Cannot open /dev/tty0 (%s)\n", + strerror(errno)); + + if (xf86Info.ShareVTs) { + SYSCALL(ret = ioctl(fd, VT_GETSTATE, &vts)); + if (ret < 0) + FatalError("parse_vt_settings: Cannot find the current" + " VT (%s)\n", strerror(errno)); + xf86Info.vtno = vts.v_active; } + else { + SYSCALL(ret = ioctl(fd, VT_OPENQRY, &xf86Info.vtno)); + if (ret < 0) + FatalError("parse_vt_settings: Cannot find a free VT: " + "%s\n", strerror(errno)); + if (xf86Info.vtno == -1) + FatalError("parse_vt_settings: Cannot find a free VT\n"); + } + close(fd); + } + + xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno); + + /* Some of stdin / stdout / stderr maybe redirected to a file */ + for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) { + ret = fstat(i, &st); + if (ret == 0 && S_ISCHR(st.st_mode) && major(st.st_rdev) == 4) { + current_vt = minor(st.st_rdev); + break; + } + } + + if (!KeepTty && current_vt == xf86Info.vtno) { + xf86Msg(X_PROBED, + "controlling tty is VT number %d, auto-enabling KeepTty\n", + current_vt); + KeepTty = TRUE; + } + + vt_settings_parsed = 1; +} + +int +linux_get_keeptty(void) +{ + return KeepTty; +} + +void +xf86OpenConsole(void) +{ + int i, ret; + struct vt_stat vts; + struct vt_mode VT; + const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL }; + + if (serverGeneration == 1) { + linux_parse_vt_settings(); if (!KeepTty) { pid_t ppid = getppid();