blob: a7535ce70b43a80f83f2422d629d06471edbda50 [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>
Daniel Stonec4d7f662017-03-13 16:32:18 +000037#include <sys/sysmacros.h>
Jasper St. Pierre72dea062015-09-23 10:46:47 -070038#include <sys/types.h>
39#include <sys/stat.h>
40#include <sys/uio.h>
41#include <sys/ioctl.h>
42#include <fcntl.h>
43#include <unistd.h>
44#include <linux/vt.h>
45#include <linux/kd.h>
46#include <linux/major.h>
47
48#include "compositor.h"
49#include "weston-launch.h"
50#include "launcher-impl.h"
51
52#define DRM_MAJOR 226
53
54#ifndef KDSKBMUTE
55#define KDSKBMUTE 0x4B51
56#endif
57
58#ifdef HAVE_LIBDRM
59
60#include <xf86drm.h>
61
Jasper St. Pierre72dea062015-09-23 10:46:47 -070062#else
63
64static inline int
65drmDropMaster(int drm_fd)
66{
67 return 0;
68}
69
70static inline int
71drmSetMaster(int drm_fd)
72{
73 return 0;
74}
75
Jasper St. Pierre72dea062015-09-23 10:46:47 -070076#endif
77
78
79union cmsg_data { unsigned char b[4]; int fd; };
80
81struct launcher_weston_launch {
82 struct weston_launcher base;
83 struct weston_compositor *compositor;
84 struct wl_event_loop *loop;
85 int fd;
86 struct wl_event_source *source;
87
88 int kb_mode, tty, drm_fd;
Jasper St. Pierre72dea062015-09-23 10:46:47 -070089};
90
91static int
92launcher_weston_launch_open(struct weston_launcher *launcher_base,
93 const char *path, int flags)
94{
95 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
96 int n, ret;
97 struct msghdr msg;
98 struct cmsghdr *cmsg;
99 struct iovec iov;
100 union cmsg_data *data;
101 char control[CMSG_SPACE(sizeof data->fd)];
102 ssize_t len;
103 struct weston_launcher_open *message;
104
105 n = sizeof(*message) + strlen(path) + 1;
106 message = malloc(n);
107 if (!message)
108 return -1;
109
110 message->header.opcode = WESTON_LAUNCHER_OPEN;
111 message->flags = flags;
112 strcpy(message->path, path);
113
114 do {
115 len = send(launcher->fd, message, n, 0);
116 } while (len < 0 && errno == EINTR);
117 free(message);
118
119 memset(&msg, 0, sizeof msg);
120 iov.iov_base = &ret;
121 iov.iov_len = sizeof ret;
122 msg.msg_iov = &iov;
123 msg.msg_iovlen = 1;
124 msg.msg_control = control;
125 msg.msg_controllen = sizeof control;
Yong Bakos53361532017-01-23 06:17:44 -0800126
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700127 do {
128 len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
129 } while (len < 0 && errno == EINTR);
130
131 if (len != sizeof ret ||
132 ret < 0)
133 return -1;
134
135 cmsg = CMSG_FIRSTHDR(&msg);
136 if (!cmsg ||
137 cmsg->cmsg_level != SOL_SOCKET ||
138 cmsg->cmsg_type != SCM_RIGHTS) {
139 fprintf(stderr, "invalid control message\n");
140 return -1;
141 }
142
143 data = (union cmsg_data *) CMSG_DATA(cmsg);
144 if (data->fd == -1) {
145 fprintf(stderr, "missing drm fd in socket request\n");
146 return -1;
147 }
148
149 return data->fd;
150}
151
152static void
153launcher_weston_launch_close(struct weston_launcher *launcher_base, int fd)
154{
155 close(fd);
156}
157
158static void
159launcher_weston_launch_restore(struct weston_launcher *launcher_base)
160{
161 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
162 struct vt_mode mode = { 0 };
163
164 if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
165 ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
166 weston_log("failed to restore kb mode: %m\n");
167
168 if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
169 weston_log("failed to set KD_TEXT mode on tty: %m\n");
170
171 /* We have to drop master before we switch the VT back in
172 * VT_AUTO, so we don't risk switching to a VT with another
173 * display server, that will then fail to set drm master. */
174 drmDropMaster(launcher->drm_fd);
175
176 mode.mode = VT_AUTO;
177 if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
178 weston_log("could not reset vt handling\n");
179}
180
181static int
182launcher_weston_launch_data(int fd, uint32_t mask, void *data)
183{
184 struct launcher_weston_launch *launcher = data;
185 int len, ret;
186
187 if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
188 weston_log("launcher socket closed, exiting\n");
189 /* Normally the weston-launch will reset the tty, but
190 * in this case it died or something, so do it here so
191 * we don't end up with a stuck vt. */
192 launcher_weston_launch_restore(&launcher->base);
193 exit(-1);
194 }
195
196 do {
197 len = recv(launcher->fd, &ret, sizeof ret, 0);
198 } while (len < 0 && errno == EINTR);
199
200 switch (ret) {
201 case WESTON_LAUNCHER_ACTIVATE:
202 launcher->compositor->session_active = 1;
203 wl_signal_emit(&launcher->compositor->session_signal,
204 launcher->compositor);
205 break;
206 case WESTON_LAUNCHER_DEACTIVATE:
207 launcher->compositor->session_active = 0;
208 wl_signal_emit(&launcher->compositor->session_signal,
209 launcher->compositor);
210 break;
211 default:
212 weston_log("unexpected event from weston-launch\n");
213 break;
214 }
215
216 return 1;
217}
218
219static int
220launcher_weston_launch_activate_vt(struct weston_launcher *launcher_base, int vt)
221{
222 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
223 return ioctl(launcher->tty, VT_ACTIVATE, vt);
224}
225
226static int
227launcher_weston_launch_connect(struct weston_launcher **out, struct weston_compositor *compositor,
228 int tty, const char *seat_id, bool sync_drm)
229{
230 struct launcher_weston_launch *launcher;
231 struct wl_event_loop *loop;
232
233 launcher = malloc(sizeof *launcher);
234 if (launcher == NULL)
235 return -ENOMEM;
236
237 launcher->base.iface = &launcher_weston_launch_iface;
238 * (struct launcher_weston_launch **) out = launcher;
239 launcher->compositor = compositor;
240 launcher->drm_fd = -1;
Derek Foremane7d868a2015-09-24 14:30:38 -0500241 launcher->fd = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700242 if (launcher->fd != -1) {
243 launcher->tty = weston_environment_get_fd("WESTON_TTY_FD");
244 /* We don't get a chance to read out the original kb
245 * mode for the tty, so just hard code K_UNICODE here
246 * in case we have to clean if weston-launch dies. */
247 launcher->kb_mode = K_UNICODE;
248
249 loop = wl_display_get_event_loop(compositor->wl_display);
250 launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
251 WL_EVENT_READABLE,
252 launcher_weston_launch_data,
253 launcher);
254 if (launcher->source == NULL) {
255 free(launcher);
256 return -ENOMEM;
257 }
258
259 return 0;
260 } else {
261 return -1;
262 }
263}
264
265static void
266launcher_weston_launch_destroy(struct weston_launcher *launcher_base)
267{
268 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
269
270 if (launcher->fd != -1) {
271 close(launcher->fd);
272 wl_event_source_remove(launcher->source);
273 } else {
274 launcher_weston_launch_restore(&launcher->base);
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700275 }
276
277 if (launcher->tty >= 0)
278 close(launcher->tty);
279
280 free(launcher);
281}
282
Giulio Camuffoa32986e2016-12-05 14:50:36 +0100283static int
284launcher_weston_launch_get_vt(struct weston_launcher *base)
285{
286 struct launcher_weston_launch *launcher = wl_container_of(base, launcher, base);
287 struct stat s;
288 if (fstat(launcher->tty, &s) < 0)
289 return -1;
290
291 return minor(s.st_rdev);
292}
293
Emil Velikov8f7201e2017-02-10 20:14:22 +0000294const struct launcher_interface launcher_weston_launch_iface = {
Emil Velikov4d6eb172017-02-10 20:14:23 +0000295 .connect = launcher_weston_launch_connect,
296 .destroy = launcher_weston_launch_destroy,
297 .open = launcher_weston_launch_open,
298 .close = launcher_weston_launch_close,
299 .activate_vt = launcher_weston_launch_activate_vt,
300 .restore = launcher_weston_launch_restore,
301 .get_vt = launcher_weston_launch_get_vt,
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700302};