blob: 930f4e0c05827a18a62056e9d31bb7721e4bba13 [file] [log] [blame]
Jasper St. Pierre72dea062015-09-23 10:46:47 -07001/*
2 * Copyright © 2012 Benjamin Franzke
3 * Copyright © 2013 Intel Corporation
4 *
Yong Bakos53361532017-01-23 06:17:44 -08005 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
Jasper St. Pierre72dea062015-09-23 10:46:47 -070012 *
Yong Bakos53361532017-01-23 06:17:44 -080013 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
Jasper St. Pierre72dea062015-09-23 10:46:47 -070025 */
26
27#include "config.h"
28
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030029#include <stdint.h>
Jasper St. Pierre72dea062015-09-23 10:46:47 -070030#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include <errno.h>
35#include <signal.h>
36#include <sys/socket.h>
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <sys/uio.h>
40#include <sys/ioctl.h>
41#include <fcntl.h>
42#include <unistd.h>
43#include <linux/vt.h>
44#include <linux/kd.h>
45#include <linux/major.h>
46
47#include "compositor.h"
48#include "weston-launch.h"
49#include "launcher-impl.h"
50
51#define DRM_MAJOR 226
52
53#ifndef KDSKBMUTE
54#define KDSKBMUTE 0x4B51
55#endif
56
57#ifdef HAVE_LIBDRM
58
59#include <xf86drm.h>
60
Jasper St. Pierre72dea062015-09-23 10:46:47 -070061#else
62
63static inline int
64drmDropMaster(int drm_fd)
65{
66 return 0;
67}
68
69static inline int
70drmSetMaster(int drm_fd)
71{
72 return 0;
73}
74
Jasper St. Pierre72dea062015-09-23 10:46:47 -070075#endif
76
77
78union cmsg_data { unsigned char b[4]; int fd; };
79
80struct launcher_weston_launch {
81 struct weston_launcher base;
82 struct weston_compositor *compositor;
83 struct wl_event_loop *loop;
84 int fd;
85 struct wl_event_source *source;
86
87 int kb_mode, tty, drm_fd;
Jasper St. Pierre72dea062015-09-23 10:46:47 -070088};
89
90static int
91launcher_weston_launch_open(struct weston_launcher *launcher_base,
92 const char *path, int flags)
93{
94 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
95 int n, ret;
96 struct msghdr msg;
97 struct cmsghdr *cmsg;
98 struct iovec iov;
99 union cmsg_data *data;
100 char control[CMSG_SPACE(sizeof data->fd)];
101 ssize_t len;
102 struct weston_launcher_open *message;
103
104 n = sizeof(*message) + strlen(path) + 1;
105 message = malloc(n);
106 if (!message)
107 return -1;
108
109 message->header.opcode = WESTON_LAUNCHER_OPEN;
110 message->flags = flags;
111 strcpy(message->path, path);
112
113 do {
114 len = send(launcher->fd, message, n, 0);
115 } while (len < 0 && errno == EINTR);
116 free(message);
117
118 memset(&msg, 0, sizeof msg);
119 iov.iov_base = &ret;
120 iov.iov_len = sizeof ret;
121 msg.msg_iov = &iov;
122 msg.msg_iovlen = 1;
123 msg.msg_control = control;
124 msg.msg_controllen = sizeof control;
Yong Bakos53361532017-01-23 06:17:44 -0800125
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700126 do {
127 len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
128 } while (len < 0 && errno == EINTR);
129
130 if (len != sizeof ret ||
131 ret < 0)
132 return -1;
133
134 cmsg = CMSG_FIRSTHDR(&msg);
135 if (!cmsg ||
136 cmsg->cmsg_level != SOL_SOCKET ||
137 cmsg->cmsg_type != SCM_RIGHTS) {
138 fprintf(stderr, "invalid control message\n");
139 return -1;
140 }
141
142 data = (union cmsg_data *) CMSG_DATA(cmsg);
143 if (data->fd == -1) {
144 fprintf(stderr, "missing drm fd in socket request\n");
145 return -1;
146 }
147
148 return data->fd;
149}
150
151static void
152launcher_weston_launch_close(struct weston_launcher *launcher_base, int fd)
153{
154 close(fd);
155}
156
157static void
158launcher_weston_launch_restore(struct weston_launcher *launcher_base)
159{
160 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
161 struct vt_mode mode = { 0 };
162
163 if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
164 ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
165 weston_log("failed to restore kb mode: %m\n");
166
167 if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
168 weston_log("failed to set KD_TEXT mode on tty: %m\n");
169
170 /* We have to drop master before we switch the VT back in
171 * VT_AUTO, so we don't risk switching to a VT with another
172 * display server, that will then fail to set drm master. */
173 drmDropMaster(launcher->drm_fd);
174
175 mode.mode = VT_AUTO;
176 if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
177 weston_log("could not reset vt handling\n");
178}
179
180static int
181launcher_weston_launch_data(int fd, uint32_t mask, void *data)
182{
183 struct launcher_weston_launch *launcher = data;
184 int len, ret;
185
186 if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
187 weston_log("launcher socket closed, exiting\n");
188 /* Normally the weston-launch will reset the tty, but
189 * in this case it died or something, so do it here so
190 * we don't end up with a stuck vt. */
191 launcher_weston_launch_restore(&launcher->base);
192 exit(-1);
193 }
194
195 do {
196 len = recv(launcher->fd, &ret, sizeof ret, 0);
197 } while (len < 0 && errno == EINTR);
198
199 switch (ret) {
200 case WESTON_LAUNCHER_ACTIVATE:
201 launcher->compositor->session_active = 1;
202 wl_signal_emit(&launcher->compositor->session_signal,
203 launcher->compositor);
204 break;
205 case WESTON_LAUNCHER_DEACTIVATE:
206 launcher->compositor->session_active = 0;
207 wl_signal_emit(&launcher->compositor->session_signal,
208 launcher->compositor);
209 break;
210 default:
211 weston_log("unexpected event from weston-launch\n");
212 break;
213 }
214
215 return 1;
216}
217
218static int
219launcher_weston_launch_activate_vt(struct weston_launcher *launcher_base, int vt)
220{
221 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
222 return ioctl(launcher->tty, VT_ACTIVATE, vt);
223}
224
225static int
226launcher_weston_launch_connect(struct weston_launcher **out, struct weston_compositor *compositor,
227 int tty, const char *seat_id, bool sync_drm)
228{
229 struct launcher_weston_launch *launcher;
230 struct wl_event_loop *loop;
231
232 launcher = malloc(sizeof *launcher);
233 if (launcher == NULL)
234 return -ENOMEM;
235
236 launcher->base.iface = &launcher_weston_launch_iface;
237 * (struct launcher_weston_launch **) out = launcher;
238 launcher->compositor = compositor;
239 launcher->drm_fd = -1;
Derek Foremane7d868a2015-09-24 14:30:38 -0500240 launcher->fd = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700241 if (launcher->fd != -1) {
242 launcher->tty = weston_environment_get_fd("WESTON_TTY_FD");
243 /* We don't get a chance to read out the original kb
244 * mode for the tty, so just hard code K_UNICODE here
245 * in case we have to clean if weston-launch dies. */
246 launcher->kb_mode = K_UNICODE;
247
248 loop = wl_display_get_event_loop(compositor->wl_display);
249 launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
250 WL_EVENT_READABLE,
251 launcher_weston_launch_data,
252 launcher);
253 if (launcher->source == NULL) {
254 free(launcher);
255 return -ENOMEM;
256 }
257
258 return 0;
259 } else {
260 return -1;
261 }
262}
263
264static void
265launcher_weston_launch_destroy(struct weston_launcher *launcher_base)
266{
267 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
268
269 if (launcher->fd != -1) {
270 close(launcher->fd);
271 wl_event_source_remove(launcher->source);
272 } else {
273 launcher_weston_launch_restore(&launcher->base);
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700274 }
275
276 if (launcher->tty >= 0)
277 close(launcher->tty);
278
279 free(launcher);
280}
281
Giulio Camuffoa32986e2016-12-05 14:50:36 +0100282static int
283launcher_weston_launch_get_vt(struct weston_launcher *base)
284{
285 struct launcher_weston_launch *launcher = wl_container_of(base, launcher, base);
286 struct stat s;
287 if (fstat(launcher->tty, &s) < 0)
288 return -1;
289
290 return minor(s.st_rdev);
291}
292
Emil Velikov8f7201e2017-02-10 20:14:22 +0000293const struct launcher_interface launcher_weston_launch_iface = {
Emil Velikov4d6eb172017-02-10 20:14:23 +0000294 .connect = launcher_weston_launch_connect,
295 .destroy = launcher_weston_launch_destroy,
296 .open = launcher_weston_launch_open,
297 .close = launcher_weston_launch_close,
298 .activate_vt = launcher_weston_launch_activate_vt,
299 .restore = launcher_weston_launch_restore,
300 .get_vt = launcher_weston_launch_get_vt,
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700301};