diff --git a/hw/xfree86/man/Xorg.man b/hw/xfree86/man/Xorg.man index 3ff6aef89..ddf135866 100644 --- a/hw/xfree86/man/Xorg.man +++ b/hw/xfree86/man/Xorg.man @@ -271,9 +271,9 @@ is ignored if is anything other than \(oqPCI\(cq. .TP 8 .B \-keeptty -Prevent the server from detaching its initial controlling terminal. -This option is only useful when debugging the server. Not all platforms -support (or can use) this option. +Prevent the server from detaching its initial controlling terminal. If you +want to use systemd-logind integration you must specify this option. +Not all platforms support (or can use) this option. .TP 8 .BI \-keyboard " keyboard-name" Use the xorg.conf(__filemansuffix__) file diff --git a/hw/xfree86/man/Xorg.wrap.man b/hw/xfree86/man/Xorg.wrap.man index 11090f1f4..f3f30a6c4 100644 --- a/hw/xfree86/man/Xorg.wrap.man +++ b/hw/xfree86/man/Xorg.wrap.man @@ -55,7 +55,7 @@ The default is \fIconsole\fP. \fBneeds_root_rights\fP = \fIyes\fP|\fIno\fP|\fIauto\fP Configure if the wrapper should drop its elevated (root) rights before starting the X server. Use \fIyes\fP to force execution as root, \fIno\fP to force -execution with all suid rights dropped, and \fIauto\fP to letter the wrapper +execution with all suid rights dropped, and \fIauto\fP to let the wrapper auto-detect. The default is \fIauto\fP. .PP When auto-detecting the wrapper will drop rights if kms graphics are available diff --git a/hw/xfree86/os-support/linux/linux.h b/hw/xfree86/os-support/linux/linux.h new file mode 100644 index 000000000..83506fd38 --- /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 + +int linux_parse_vt_settings(int may_fail); +int linux_get_keeptty(void); + +#endif diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c index a0e6782b0..ec06a059e 100644 --- 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" @@ -79,72 +80,108 @@ switch_to(int vt, const char *from) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" -void -xf86OpenConsole(void) +int +linux_parse_vt_settings(int may_fail) { 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 }; + + /* Only do this once */ + static int vt_settings_parsed = 0; + + if (vt_settings_parsed) + return 1; + + /* + * setup the virtual terminal manager + */ + if (xf86Info.vtno != -1) { + from = X_CMDLINE; + } + else { + + i = 0; + while (tty0[i] != NULL) { + if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) + break; + i++; + } + + if (fd < 0) { + if (may_fail) + return 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) { + if (may_fail) + return 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) { + if (may_fail) + return 0; + FatalError("parse_vt_settings: Cannot find a free VT: " + "%s\n", strerror(errno)); + } + if (xf86Info.vtno == -1) { + if (may_fail) + return 0; + 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; + return 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) { - /* - * setup the virtual terminal manager - */ - if (xf86Info.vtno != -1) { - from = X_CMDLINE; - } - else { - - 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); - } - - 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; - } + linux_parse_vt_settings(FALSE); if (!KeepTty) { pid_t ppid = getppid(); diff --git a/hw/xfree86/os-support/linux/systemd-logind.c b/hw/xfree86/os-support/linux/systemd-logind.c index 4ad41a374..2612d9e23 100644 --- a/hw/xfree86/os-support/linux/systemd-logind.c +++ b/hw/xfree86/os-support/linux/systemd-logind.c @@ -34,6 +34,7 @@ #include "os.h" #include "dbus-core.h" +#include "linux.h" #include "xf86.h" #include "xf86platformBus.h" #include "xf86Xinput.h" @@ -506,6 +507,24 @@ connect_hook(DBusConnection *connection, void *data) goto cleanup; } + dbus_bus_add_match(connection, + "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.login1.Session',member='PauseDevice'", + &error); + if (dbus_error_is_set(&error)) { + LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n", + error.message); + goto cleanup; + } + + dbus_bus_add_match(connection, + "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.login1.Session',member='ResumeDevice'", + &error); + if (dbus_error_is_set(&error)) { + LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n", + error.message); + goto cleanup; + } + /* * HdG: This is not useful with systemd <= 208 since the signal only * contains invalidated property names there, rather than property, val @@ -596,6 +615,13 @@ static struct dbus_core_hook core_hook = { int systemd_logind_init(void) { + if (linux_parse_vt_settings(TRUE) && !linux_get_keeptty()) { + LogMessage(X_INFO, + "systemd-logind: logind integration requires -keeptty and " + "-keeptty was not provided, disabling logind integration\n"); + return 1; + } + return dbus_core_add_hook(&core_hook); }