launcher: Handle drm set/drop master and vt switch signals in launcher
diff --git a/src/weston-launch.c b/src/weston-launch.c
index 80c06a8..87f4641 100644
--- a/src/weston-launch.c
+++ b/src/weston-launch.c
@@ -68,6 +68,7 @@
 	int tty;
 	int ttynr;
 	int sock[2];
+	int drm_fd;
 	struct passwd *pw;
 
 	int signalfd;
@@ -223,6 +224,8 @@
 	sigaddset(&mask, SIGCHLD);
 	sigaddset(&mask, SIGINT);
 	sigaddset(&mask, SIGTERM);
+	sigaddset(&mask, SIGUSR1);
+	sigaddset(&mask, SIGUSR2);
 	ret = sigprocmask(SIG_BLOCK, &mask, NULL);
 	assert(ret == 0);
 
@@ -243,48 +246,15 @@
 }
 
 static int
-handle_setmaster(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
+send_reply(struct weston_launch *wl, int reply)
 {
-	int ret = -1;
-	struct cmsghdr *cmsg;
-	struct weston_launcher_set_master *message;
-	union cmsg_data *data;
+	int len;
 
-	if (len != sizeof(*message)) {
-		error(0, 0, "missing value in setmaster request");
-		goto out;
-	}
-
-	message = msg->msg_iov->iov_base;
-
-	cmsg = CMSG_FIRSTHDR(msg);
-	if (!cmsg ||
-	    cmsg->cmsg_level != SOL_SOCKET ||
-	    cmsg->cmsg_type != SCM_RIGHTS) {
-		error(0, 0, "invalid control message");
-		goto out;
-	}
-
-	data = (union cmsg_data *) CMSG_DATA(cmsg);
-	if (data->fd == -1) {
-		error(0, 0, "missing drm fd in socket request");
-		goto out;
-	}
-
-	if (message->set_master)
-		ret = drmSetMaster(data->fd);
-	else
-		ret = drmDropMaster(data->fd);
-
-	close(data->fd);
-out:
 	do {
-		len = send(wl->sock[0], &ret, sizeof ret, 0);
+		len = send(wl->sock[0], &reply, sizeof reply, 0);
 	} while (len < 0 && errno == EINTR);
-	if (len < 0)
-		return -1;
 
-	return 0;
+	return len;
 }
 
 static int
@@ -354,6 +324,9 @@
 	if (len < 0)
 		return -1;
 
+	if (major(s.st_rdev) == DRM_MAJOR)
+		wl->drm_fd = fd;
+
 	return 0;
 }
 
@@ -388,9 +361,6 @@
 	case WESTON_LAUNCHER_OPEN:
 		ret = handle_open(wl, &msg, len);
 		break;
-	case WESTON_LAUNCHER_DRM_SET_MASTER:
-		ret = handle_setmaster(wl, &msg, len);
-		break;
 	}
 
 	return ret;
@@ -451,6 +421,16 @@
 		if (wl->child)
 			kill(wl->child, sig.ssi_signo);
 		break;
+	case SIGUSR1:
+		send_reply(wl, WESTON_LAUNCHER_DEACTIVATE);
+		drmDropMaster(wl->drm_fd);
+		ioctl(wl->tty, VT_RELDISP, 1);
+		break;
+	case SIGUSR2:
+		ioctl(wl->tty, VT_RELDISP, VT_ACKACQ);
+		drmSetMaster(wl->drm_fd);
+		send_reply(wl, WESTON_LAUNCHER_ACTIVATE);
+		break;
 	default:
 		return -1;
 	}
@@ -462,6 +442,7 @@
 setup_tty(struct weston_launch *wl, const char *tty)
 {
 	struct stat buf;
+	struct vt_mode mode = { 0 };
 	char *t;
 
 	if (!wl->new_user) {
@@ -500,6 +481,12 @@
 		wl->ttynr = minor(buf.st_rdev);
 	}
 
+	mode.mode = VT_PROCESS;
+	mode.relsig = SIGUSR1;
+	mode.acqsig = SIGUSR2;
+	if (ioctl(wl->tty, VT_SETMODE, &mode) < 0)
+		error(1, errno, "failed to take control of vt handling\n");
+
 	return 0;
 }