From 81b49639495f22f1d8f8a6978029db3d0b07fe0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 17 Sep 2013 22:43:22 -0700 Subject: [PATCH] launcher: Handle tty setup and teardown in launcher --- src/compositor-drm.c | 32 +++++++++++++++++++------------ src/tty.c | 24 +++++++++++------------ src/weston-launch.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 25 deletions(-) diff --git a/src/compositor-drm.c b/src/compositor-drm.c index 4ee068bf..b53cd9fe 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -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: diff --git a/src/tty.c b/src/tty.c index 2ac7236c..6beeb3c1 100644 --- 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: diff --git a/src/weston-launch.c b/src/weston-launch.c index 87f46417..059010c4 100644 --- a/src/weston-launch.c +++ b/src/weston-launch.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ #include #include #include +#include #include #include @@ -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;