launcher: Handle tty setup and teardown in launcher
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 18 Sep 2013 05:43:22 +0000 (22:43 -0700)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 18 Sep 2013 18:14:14 +0000 (11:14 -0700)
src/compositor-drm.c
src/tty.c
src/weston-launch.c

index 4ee068b..b53cd9f 100644 (file)
@@ -2242,9 +2242,11 @@ drm_restore(struct weston_compositor *ec)
 {
        struct drm_compositor *d = (struct drm_compositor *) ec;
 
-       if (ec->launcher == NULL && drmDropMaster(d->drm.fd) < 0)
-               weston_log("failed to drop master: %m\n");
-       tty_reset(d->tty);
+       if (ec->launcher == NULL) {
+               if (drmDropMaster(d->drm.fd) < 0)
+                       weston_log("failed to drop master: %m\n");
+               tty_reset(d->tty);
+       }
 }
 
 static void
@@ -2266,9 +2268,11 @@ drm_destroy(struct weston_compositor *ec)
        if (d->gbm)
                gbm_device_destroy(d->gbm);
 
-       if (d->base.launcher == NULL && drmDropMaster(d->drm.fd) < 0)
-               weston_log("failed to drop master: %m\n");
-       tty_destroy(d->tty);
+       if (d->base.launcher == NULL) {
+               if (drmDropMaster(d->drm.fd) < 0)
+                       weston_log("failed to drop master: %m\n");
+               tty_destroy(d->tty);
+       }
 
        close(d->drm.fd);
 
@@ -2366,7 +2370,8 @@ switch_vt_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *d
 {
        struct drm_compositor *ec = data;
 
-       tty_activate_vt(ec->tty, key - KEY_F1 + 1);
+       if (ec->tty)
+               tty_activate_vt(ec->tty, key - KEY_F1 + 1);
 }
 
 /*
@@ -2585,10 +2590,12 @@ drm_compositor_create(struct wl_display *display,
        ec->base.wl_display = display;
        ec->session_listener.notify = session_notify;
        wl_signal_add(&ec->base.session_signal, &ec->session_listener);
-       ec->tty = tty_create(&ec->base, tty);
-       if (!ec->tty) {
-               weston_log("failed to initialize tty\n");
-               goto err_udev;
+       if (ec->base.launcher == NULL) {
+               ec->tty = tty_create(&ec->base, tty);
+               if (!ec->tty) {
+                       weston_log("failed to initialize tty\n");
+                       goto err_udev;
+               }
        }
 
        drm_device = find_primary_gpu(ec, seat_id);
@@ -2692,7 +2699,8 @@ err_udev_dev:
 err_tty:
        if (ec->base.launcher == NULL && drmDropMaster(ec->drm.fd) < 0)
                weston_log("failed to drop master: %m\n");
-       tty_destroy(ec->tty);
+       if (ec->tty)
+               tty_destroy(ec->tty);
 err_udev:
        udev_unref(ec->udev);
 err_compositor:
index 2ac7236..6beeb3c 100644 (file)
--- a/src/tty.c
+++ b/src/tty.c
@@ -219,21 +219,19 @@ tty_create(struct weston_compositor *compositor, int tty_nr)
                goto err_kdkbmode;
        }
 
-       if (compositor->launcher == NULL) {
-               mode.mode = VT_PROCESS;
-               mode.relsig = SIGUSR1;
-               mode.acqsig = SIGUSR1;
-               if (ioctl(tty->fd, VT_SETMODE, &mode) < 0) {
-                       weston_log("failed to take control of vt handling\n");
-                       goto err_kdmode;
-               }
-
-               tty->vt_source =
-                       wl_event_loop_add_signal(loop, SIGUSR1, vt_handler, tty);
-               if (!tty->vt_source)
-                       goto err_vtmode;
+       mode.mode = VT_PROCESS;
+       mode.relsig = SIGUSR1;
+       mode.acqsig = SIGUSR1;
+       if (ioctl(tty->fd, VT_SETMODE, &mode) < 0) {
+               weston_log("failed to take control of vt handling\n");
+               goto err_kdmode;
        }
 
+       tty->vt_source =
+               wl_event_loop_add_signal(loop, SIGUSR1, vt_handler, tty);
+       if (!tty->vt_source)
+               goto err_vtmode;
+
        return tty;
 
 err_vtmode:
index 87f4641..059010c 100644 (file)
@@ -28,6 +28,7 @@
 #include <assert.h>
 #include <poll.h>
 #include <errno.h>
+#include <termios.h>
 
 #include <error.h>
 #include <getopt.h>
@@ -45,6 +46,7 @@
 #include <termios.h>
 #include <linux/vt.h>
 #include <linux/major.h>
+#include <linux/kd.h>
 
 #include <pwd.h>
 #include <grp.h>
@@ -69,6 +71,8 @@ struct weston_launch {
        int ttynr;
        int sock[2];
        int drm_fd;
+       struct termios terminal_attributes;
+       int kb_mode;
        struct passwd *pw;
 
        int signalfd;
@@ -369,6 +373,7 @@ handle_socket_msg(struct weston_launch *wl)
 static void
 quit(struct weston_launch *wl, int status)
 {
+       struct vt_mode mode = { 0 };
        int err;
 
        close(wl->signalfd);
@@ -382,6 +387,20 @@ quit(struct weston_launch *wl, int status)
                pam_end(wl->ph, err);
        }
 
+       if (ioctl(wl->tty, KDSKBMODE, wl->kb_mode))
+               fprintf(stderr, "failed to restore keyboard mode: %m\n");
+
+       if (ioctl(wl->tty, KDSETMODE, KD_TEXT))
+               fprintf(stderr, "failed to set KD_TEXT mode on tty: %m\n");
+
+       if (tcsetattr(wl->tty, TCSANOW, &wl->terminal_attributes) < 0)
+               fprintf(stderr,
+                       "could not restore terminal to canonical mode\n");
+
+       mode.mode = VT_AUTO;
+       if (ioctl(wl->tty, VT_SETMODE, &mode) < 0)
+               fprintf(stderr, "could not reset vt handling\n");
+
        exit(status);
 }
 
@@ -441,9 +460,11 @@ handle_signal(struct weston_launch *wl)
 static int
 setup_tty(struct weston_launch *wl, const char *tty)
 {
+       struct termios raw_attributes;
        struct stat buf;
        struct vt_mode mode = { 0 };
        char *t;
+       int ret;
 
        if (!wl->new_user) {
                wl->tty = STDIN_FILENO;
@@ -481,6 +502,30 @@ setup_tty(struct weston_launch *wl, const char *tty)
                wl->ttynr = minor(buf.st_rdev);
        }
 
+       if (tcgetattr(wl->tty, &wl->terminal_attributes) < 0)
+               error(1, errno, "could not get terminal attributes: %m\n");
+
+       /* Ignore control characters and disable echo */
+       raw_attributes = wl->terminal_attributes;
+       cfmakeraw(&raw_attributes);
+
+       /* Fix up line endings to be normal (cfmakeraw hoses them) */
+       raw_attributes.c_oflag |= OPOST | OCRNL;
+
+       if (tcsetattr(wl->tty, TCSANOW, &raw_attributes) < 0)
+               error(1, errno, "could not put terminal into raw mode: %m\n");
+
+       ioctl(wl->tty, KDGKBMODE, &wl->kb_mode);
+       ret = ioctl(wl->tty, KDSKBMODE, K_OFF);
+       if (ret)
+               ret = ioctl(wl->tty, KDSKBMODE, K_RAW);
+       if (ret)
+               error(1, errno, "failed to set keyboard mode on tty: %m\n");
+
+       ret = ioctl(wl->tty, KDSETMODE, KD_GRAPHICS);
+       if (ret)
+               error(1, errno, "failed to set KD_GRAPHICS mode on tty: %m\n");
+
        mode.mode = VT_PROCESS;
        mode.relsig = SIGUSR1;
        mode.acqsig = SIGUSR2;