kmscon: allow paths with --vt=<xy>
authorDavid Herrmann <dh.herrmann@googlemail.com>
Sun, 30 Sep 2012 17:00:45 +0000 (19:00 +0200)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Sun, 30 Sep 2012 17:13:02 +0000 (19:13 +0200)
The getty variants out there (including agetty) require an relative path
to the /dev directory as argument. This is really odd but we want to be
backwards-compatible to them so we allow this, too.

--vt now accepts:
  * A positive number which is internally converted into /dev/ttyXY
  * A string that does not start with '/' or '.' which is interpreted
    relative to /dev as /dev/%s
  * Everything else is interpreted as path

This option still selects only the TTY on seat0. On all other seats we do
not use controlling TTYs.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
Makefile.am
src/main.c
src/main.h
src/uterm.h
src/uterm_vt.c
tests/test_vt.c

index e7aafda..f8215a8 100644 (file)
@@ -415,6 +415,7 @@ endif
 
 kmscon_SOURCES = \
        $(SHL_DLIST) \
+       $(SHL_MISC) \
        src/main.c
 kmscon_LDADD = \
        libuterm.la \
index eef6454..7e1d1b4 100644 (file)
@@ -37,6 +37,7 @@
 #include "log.h"
 #include "main.h"
 #include "shl_dlist.h"
+#include "shl_misc.h"
 #include "text.h"
 #include "ui.h"
 #include "uterm.h"
@@ -589,6 +590,48 @@ const struct conf_type conf_grab = {
                    _mem, \
                    _def)
 
+int conf_parse_vt(struct conf_option *opt, bool on, const char *arg)
+{
+       static const char prefix[] = "/dev/";
+       unsigned int val;
+       char *str;
+       int ret;
+
+       if (!shl_strtou(arg, &val)) {
+               ret = asprintf(&str, "%stty%u", prefix, val);
+               if (ret == -1)
+                       return -ENOMEM;
+       } else if (*arg && *arg != '.' && *arg != '/') {
+               str = malloc(sizeof(prefix) + strlen(arg));
+               if (!str)
+                       return -ENOMEM;
+
+               strcpy(str, prefix);
+               strcat(str, arg);
+       } else {
+               str = strdup(arg);
+               if (!str)
+                       return -ENOMEM;
+       }
+
+
+       opt->type->free(opt);
+       *(void**)opt->mem = str;
+       return 0;
+}
+
+void conf_default_vt(struct conf_option *opt)
+{
+       *(void**)opt->mem = opt->def;
+}
+
+const struct conf_type conf_vt = {
+       .flags = CONF_HAS_ARG,
+       .parse = conf_parse_vt,
+       .free = conf_free_value,
+       .set_default = conf_default_vt,
+};
+
 static int aftercheck_debug(struct conf_option *opt, int argc, char **argv,
                            int idx)
 {
@@ -679,7 +722,7 @@ struct conf_option options[] = {
        CONF_OPTION_UINT(0, "fps", NULL, &kmscon_conf.fps, 50),
        CONF_OPTION_STRING(0, "render-engine", NULL, &kmscon_conf.render_engine, NULL),
        CONF_OPTION_BOOL(0, "render-timing", NULL, &kmscon_conf.render_timing, false),
-       CONF_OPTION_INT(0, "vt", NULL, &kmscon_conf.vt, UTERM_VT_DEFAULT),
+       CONF_OPTION(0, 0, "vt", &conf_vt, NULL, &kmscon_conf.vt, NULL),
        CONF_OPTION_BOOL('s', "switchvt", NULL, &kmscon_conf.switchvt, false),
        CONF_OPTION_BOOL('l', "login", aftercheck_login, &kmscon_conf.login, false),
        CONF_OPTION_STRING('t', "term", NULL, &kmscon_conf.term, "xterm-256color"),
index c192226..03cc549 100644 (file)
@@ -47,7 +47,7 @@ struct kmscon_conf_t {
        /* disable notices and warnings */
        bool silent;
        /* VT number to run on on seat0 */
-       int vt;
+       char *vt;
        /* enter new VT directly */
        bool switchvt;
        /* use framebuffers instead of DRM */
index 3359c39..98232ad 100644 (file)
@@ -334,8 +334,6 @@ enum uterm_vt_mode {
        UTERM_VT_DEAD,
 };
 
-#define UTERM_VT_DEFAULT (-1)
-
 typedef int (*uterm_vt_cb) (struct uterm_vt *vt, unsigned int action,
                            void *data);
 
@@ -346,7 +344,7 @@ void uterm_vt_master_unref(struct uterm_vt_master *vtm);
 
 int uterm_vt_allocate(struct uterm_vt_master *vt, struct uterm_vt **out,
                      const char *seat, struct uterm_input *input,
-                     int vt_for_seat0, uterm_vt_cb cb, void *data);
+                     const char *vt_for_seat0, uterm_vt_cb cb, void *data);
 void uterm_vt_deallocate(struct uterm_vt *vt);
 void uterm_vt_ref(struct uterm_vt *vt);
 void uterm_vt_unref(struct uterm_vt *vt);
index d7e11a7..8f713af 100644 (file)
@@ -38,6 +38,7 @@
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/signalfd.h>
+#include <sys/stat.h>
 #include <termios.h>
 #include <unistd.h>
 #include <xkbcommon/xkbcommon-keysyms.h>
@@ -159,15 +160,16 @@ static void real_input(struct ev_fd *fd, int mask, void *data)
        tcflush(vt->real_fd, TCIFLUSH);
 }
 
-static int open_tty(int id, int *tty_fd, int *tty_num)
+static int open_tty(const char *dev, int *tty_fd, int *tty_num)
 {
-       int fd, err1;
+       int fd, err1, id, ret;
        char filename[16];
+       struct stat st;
 
        if (!tty_fd || !tty_num)
                return -EINVAL;
 
-       if (id < 0) {
+       if (!dev) {
                fd = open("/dev/tty0", O_NONBLOCK | O_NOCTTY | O_CLOEXEC);
                if (fd < 0) {
                        err1 = errno;
@@ -186,24 +188,34 @@ static int open_tty(int id, int *tty_fd, int *tty_num)
                        return -EINVAL;
                }
                close(fd);
+
+               snprintf(filename, sizeof(filename), "/dev/tty%d", id);
+               filename[sizeof(filename) - 1] = 0;
+               dev = filename;
        }
 
-       snprintf(filename, sizeof(filename), "/dev/tty%d", id);
-       filename[sizeof(filename) - 1] = 0;
-       log_notice("using tty %s", filename);
+       log_notice("using tty %s", dev);
 
-       fd = open(filename, O_RDWR | O_NOCTTY | O_CLOEXEC);
+       fd = open(dev, O_RDWR | O_NOCTTY | O_CLOEXEC);
        if (fd < 0) {
-               log_err("cannot open tty %s", filename);
+               log_err("cannot open tty %s", dev);
+               return -errno;
+       }
+
+       ret = fstat(fd, &st);
+       if (ret) {
+               log_error("cannot introspect tty %s (%d): %m", dev, errno);
+               close(fd);
                return -errno;
        }
+       id = minor(st.st_rdev);
 
        *tty_fd = fd;
        *tty_num = id;
        return 0;
 }
 
-static int real_open(struct uterm_vt *vt, int vt_for_seat0)
+static int real_open(struct uterm_vt *vt, const char *vt_for_seat0)
 {
        struct termios raw_attribs;
        struct vt_mode mode;
@@ -251,7 +263,7 @@ static int real_open(struct uterm_vt *vt, int vt_for_seat0)
                log_warn("cannot put terminal into raw mode");
 
        if (ioctl(vt->real_fd, KDSETMODE, KD_GRAPHICS)) {
-               log_err("vt: cannot set graphics mode\n");
+               log_err("vt: cannot set graphics mode");
                ret = -errno;
                goto err_reset;
        }
@@ -455,7 +467,7 @@ int uterm_vt_allocate(struct uterm_vt_master *vtm,
                      struct uterm_vt **out,
                      const char *seat,
                      struct uterm_input *input,
-                     int vt_for_seat0,
+                     const char *vt_for_seat0,
                      uterm_vt_cb cb,
                      void *data)
 {
index bc3e235..9ce7bd0 100644 (file)
@@ -102,8 +102,7 @@ int main(int argc, char **argv)
        if (ret)
                goto err_exit;
 
-       ret = uterm_vt_allocate(vtm, &vt, NULL, NULL, UTERM_VT_DEFAULT, NULL,
-                               NULL);
+       ret = uterm_vt_allocate(vtm, &vt, NULL, NULL, NULL, NULL, NULL);
        if (ret)
                goto err_vtm;