/*
* Copyright (C) 2010-2011 Robert Ancell.
* Author: Robert Ancell <robert.ancell@canonical.com>
- *
+ *
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
static GList *used_vts = NULL;
static gint
-open_console (void)
+open_tty (void)
{
int fd;
- fd = g_open ("/dev/console", O_RDONLY | O_NOCTTY);
+ fd = g_open ("/dev/tty0", O_RDONLY | O_NOCTTY, 0);
if (fd < 0)
- g_warning ("Error opening /dev/console: %s", strerror (errno));
+ g_warning ("Error opening /dev/tty0: %s", strerror (errno));
return fd;
}
+gboolean
+vt_can_multi_seat (void)
+{
+ /* Quick check to see if we can multi seat. This is intentionally the
+ same check logind does, just without actually reading from the files.
+ Existence will prove whether we have CONFIG_VT built into the kernel. */
+ return access ("/dev/tty0", F_OK) == 0 &&
+ access ("/sys/class/tty/tty0/active", F_OK) == 0;
+}
+
gint
vt_get_active (void)
{
#ifdef __linux__
- gint console_fd;
+ gint tty_fd;
gint active = -1;
/* Pretend always active */
if (getuid () != 0)
return 1;
- console_fd = open_console ();
- if (console_fd >= 0)
+ tty_fd = open_tty ();
+ if (tty_fd >= 0)
{
- struct vt_stat console_state = { 0 };
- if (ioctl (console_fd, VT_GETSTATE, &console_state) < 0)
- g_warning ("Error using VT_GETSTATE on /dev/console: %s", strerror (errno));
+ struct vt_stat vt_state = { 0 };
+ if (ioctl (tty_fd, VT_GETSTATE, &vt_state) < 0)
+ g_warning ("Error using VT_GETSTATE on /dev/tty0: %s", strerror (errno));
else
- active = console_state.v_active;
- close (console_fd);
+ active = vt_state.v_active;
+ close (tty_fd);
}
return active;
vt_set_active (gint number)
{
#ifdef __linux__
- gint console_fd;
+ gint tty_fd;
g_debug ("Activating VT %d", number);
-
+
/* Pretend always active */
if (getuid () != 0)
- return;
+ return;
- console_fd = open_console ();
- if (console_fd >= 0)
+ tty_fd = open_tty ();
+ if (tty_fd >= 0)
{
int n = number;
- if (ioctl (console_fd, VT_ACTIVATE, n) < 0)
- g_warning ("Error using VT_ACTIVATE %d on /dev/console: %s", n, strerror (errno));
- close (console_fd);
+
+ if (ioctl (tty_fd, VT_ACTIVATE, n) < 0)
+ {
+ g_warning ("Error using VT_ACTIVATE %d on /dev/tty0: %s", n, strerror (errno));
+ close (tty_fd);
+ return;
+ }
+
+ /* Wait for the VT to become active to avoid a suspected
+ * race condition somewhere between LightDM, X, ConsoleKit and the kernel.
+ * See https://bugs.launchpad.net/bugs/851612 */
+ if (ioctl (tty_fd, VT_WAITACTIVE, n) < 0)
+ g_warning ("Error using VT_WAITACTIVE %d on /dev/tty0: %s", n, strerror (errno));
+
+ close (tty_fd);
}
#endif
}
number = vt_get_min ();
while (vt_is_used (number))
number++;
-
+
return number;
}
vt_ref (gint number)
{
g_debug ("Using VT %d", number);
- used_vts = g_list_append (used_vts, GINT_TO_POINTER (number));
+ used_vts = g_list_append (used_vts, GINT_TO_POINTER (number));
}
void