From 39d908e63a98a6b70a708f6693dd20a7744a6d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 16 Jan 2012 22:42:22 -0500 Subject: [PATCH] tty: Open a new vt if not running on a VT This is typically when launcing from a pty such as an X (or Wayland) terminal or from an ssh session. Opening a new vt typically requires root priviledges, so weston must be setuid root or laucnhed as root for this to work. --- src/tty.c | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/src/tty.c b/src/tty.c index 7b68ff16..6fdc781a 100644 --- a/src/tty.c +++ b/src/tty.c @@ -80,6 +80,41 @@ on_tty_input(int fd, uint32_t mask, void *data) return 1; } +static int +try_open_vt(void) +{ + int tty0, vt, fd; + char filename[16]; + + tty0 = open("/dev/tty0", O_WRONLY | O_CLOEXEC); + if (tty0 < 0) { + fprintf(stderr, "could not open tty0: %m\n"); + return -1; + } + + if (ioctl(tty0, VT_OPENQRY, &vt) < 0 || vt == -1) { + fprintf(stderr, "could not open tty0: %m\n"); + close(tty0); + return -1; + } + + close(tty0); + snprintf(filename, sizeof filename, "/dev/tty%d", vt); + fprintf(stderr, "compositor: using new vt %s\n", filename); + fd = open(filename, O_RDWR | O_NOCTTY | O_CLOEXEC); + if (fd < 0) + return fd; + + if (ioctl(fd, VT_ACTIVATE, vt) < 0 || + ioctl(fd, VT_WAITACTIVE, vt) < 0) { + fprintf(stderr, "failed to swtich to new vt\n"); + close(fd); + return -1; + } + + return fd; +} + struct tty * tty_create(struct weston_compositor *compositor, tty_vt_func_t vt_func, int tty_nr) @@ -103,8 +138,14 @@ tty_create(struct weston_compositor *compositor, tty_vt_func_t vt_func, snprintf(filename, sizeof filename, "/dev/tty%d", tty_nr); fprintf(stderr, "compositor: using %s\n", filename); tty->fd = open(filename, O_RDWR | O_NOCTTY | O_CLOEXEC); - } else { + } else if (fstat(tty->fd, &buf) == 0 && + major(buf.st_rdev) == TTY_MAJOR && + minor(buf.st_rdev) > 0) { tty->fd = fcntl(0, F_DUPFD_CLOEXEC, 0); + } else { + /* Fall back to try opening a new VT. This typically + * requires root. */ + tty->fd = try_open_vt(); } if (tty->fd <= 0) { @@ -112,13 +153,6 @@ tty_create(struct weston_compositor *compositor, tty_vt_func_t vt_func, return NULL; } - if (fstat(tty->fd, &buf) < 0 || - major(buf.st_rdev) != TTY_MAJOR || minor(buf.st_rdev) == 0) { - fprintf(stderr, "stdin not a vt (%d, %d)\n", - major(buf.st_dev), minor(buf.st_dev)); - return NULL; - } - if (tcgetattr(tty->fd, &tty->terminal_attributes) < 0) { fprintf(stderr, "could not get terminal attributes: %m\n"); return NULL;