blob: ad919f18bad8848564a682a7b8f5a9cc808d07ca [file] [log] [blame]
Jasper St. Pierre72dea062015-09-23 10:46:47 -07001/*
2 * Copyright © 2012 Benjamin Franzke
3 * Copyright © 2013 Intel Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#include "config.h"
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include <errno.h>
31#include <signal.h>
32#include <sys/socket.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <sys/uio.h>
36#include <sys/ioctl.h>
37#include <fcntl.h>
38#include <unistd.h>
39#include <linux/vt.h>
40#include <linux/kd.h>
41#include <linux/major.h>
42
43#include "compositor.h"
44#include "weston-launch.h"
45#include "launcher-impl.h"
46
47#define DRM_MAJOR 226
48
49#ifndef KDSKBMUTE
50#define KDSKBMUTE 0x4B51
51#endif
52
53#ifdef HAVE_LIBDRM
54
55#include <xf86drm.h>
56
57static inline int
58is_drm_master(int drm_fd)
59{
60 drm_magic_t magic;
61
62 return drmGetMagic(drm_fd, &magic) == 0 &&
63 drmAuthMagic(drm_fd, magic) == 0;
64}
65
66#else
67
68static inline int
69drmDropMaster(int drm_fd)
70{
71 return 0;
72}
73
74static inline int
75drmSetMaster(int drm_fd)
76{
77 return 0;
78}
79
80static inline int
81is_drm_master(int drm_fd)
82{
83 return 0;
84}
85
86#endif
87
88
89union cmsg_data { unsigned char b[4]; int fd; };
90
91struct launcher_weston_launch {
92 struct weston_launcher base;
93 struct weston_compositor *compositor;
94 struct wl_event_loop *loop;
95 int fd;
96 struct wl_event_source *source;
97
98 int kb_mode, tty, drm_fd;
Jasper St. Pierre72dea062015-09-23 10:46:47 -070099};
100
101static int
102launcher_weston_launch_open(struct weston_launcher *launcher_base,
103 const char *path, int flags)
104{
105 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
106 int n, ret;
107 struct msghdr msg;
108 struct cmsghdr *cmsg;
109 struct iovec iov;
110 union cmsg_data *data;
111 char control[CMSG_SPACE(sizeof data->fd)];
112 ssize_t len;
113 struct weston_launcher_open *message;
114
115 n = sizeof(*message) + strlen(path) + 1;
116 message = malloc(n);
117 if (!message)
118 return -1;
119
120 message->header.opcode = WESTON_LAUNCHER_OPEN;
121 message->flags = flags;
122 strcpy(message->path, path);
123
124 do {
125 len = send(launcher->fd, message, n, 0);
126 } while (len < 0 && errno == EINTR);
127 free(message);
128
129 memset(&msg, 0, sizeof msg);
130 iov.iov_base = &ret;
131 iov.iov_len = sizeof ret;
132 msg.msg_iov = &iov;
133 msg.msg_iovlen = 1;
134 msg.msg_control = control;
135 msg.msg_controllen = sizeof control;
136
137 do {
138 len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
139 } while (len < 0 && errno == EINTR);
140
141 if (len != sizeof ret ||
142 ret < 0)
143 return -1;
144
145 cmsg = CMSG_FIRSTHDR(&msg);
146 if (!cmsg ||
147 cmsg->cmsg_level != SOL_SOCKET ||
148 cmsg->cmsg_type != SCM_RIGHTS) {
149 fprintf(stderr, "invalid control message\n");
150 return -1;
151 }
152
153 data = (union cmsg_data *) CMSG_DATA(cmsg);
154 if (data->fd == -1) {
155 fprintf(stderr, "missing drm fd in socket request\n");
156 return -1;
157 }
158
159 return data->fd;
160}
161
162static void
163launcher_weston_launch_close(struct weston_launcher *launcher_base, int fd)
164{
165 close(fd);
166}
167
168static void
169launcher_weston_launch_restore(struct weston_launcher *launcher_base)
170{
171 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
172 struct vt_mode mode = { 0 };
173
174 if (ioctl(launcher->tty, KDSKBMUTE, 0) &&
175 ioctl(launcher->tty, KDSKBMODE, launcher->kb_mode))
176 weston_log("failed to restore kb mode: %m\n");
177
178 if (ioctl(launcher->tty, KDSETMODE, KD_TEXT))
179 weston_log("failed to set KD_TEXT mode on tty: %m\n");
180
181 /* We have to drop master before we switch the VT back in
182 * VT_AUTO, so we don't risk switching to a VT with another
183 * display server, that will then fail to set drm master. */
184 drmDropMaster(launcher->drm_fd);
185
186 mode.mode = VT_AUTO;
187 if (ioctl(launcher->tty, VT_SETMODE, &mode) < 0)
188 weston_log("could not reset vt handling\n");
189}
190
191static int
192launcher_weston_launch_data(int fd, uint32_t mask, void *data)
193{
194 struct launcher_weston_launch *launcher = data;
195 int len, ret;
196
197 if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
198 weston_log("launcher socket closed, exiting\n");
199 /* Normally the weston-launch will reset the tty, but
200 * in this case it died or something, so do it here so
201 * we don't end up with a stuck vt. */
202 launcher_weston_launch_restore(&launcher->base);
203 exit(-1);
204 }
205
206 do {
207 len = recv(launcher->fd, &ret, sizeof ret, 0);
208 } while (len < 0 && errno == EINTR);
209
210 switch (ret) {
211 case WESTON_LAUNCHER_ACTIVATE:
212 launcher->compositor->session_active = 1;
213 wl_signal_emit(&launcher->compositor->session_signal,
214 launcher->compositor);
215 break;
216 case WESTON_LAUNCHER_DEACTIVATE:
217 launcher->compositor->session_active = 0;
218 wl_signal_emit(&launcher->compositor->session_signal,
219 launcher->compositor);
220 break;
221 default:
222 weston_log("unexpected event from weston-launch\n");
223 break;
224 }
225
226 return 1;
227}
228
229static int
230launcher_weston_launch_activate_vt(struct weston_launcher *launcher_base, int vt)
231{
232 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
233 return ioctl(launcher->tty, VT_ACTIVATE, vt);
234}
235
236static int
237launcher_weston_launch_connect(struct weston_launcher **out, struct weston_compositor *compositor,
238 int tty, const char *seat_id, bool sync_drm)
239{
240 struct launcher_weston_launch *launcher;
241 struct wl_event_loop *loop;
242
243 launcher = malloc(sizeof *launcher);
244 if (launcher == NULL)
245 return -ENOMEM;
246
247 launcher->base.iface = &launcher_weston_launch_iface;
248 * (struct launcher_weston_launch **) out = launcher;
249 launcher->compositor = compositor;
250 launcher->drm_fd = -1;
Derek Foremane7d868a2015-09-24 14:30:38 -0500251 launcher->fd = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700252 if (launcher->fd != -1) {
253 launcher->tty = weston_environment_get_fd("WESTON_TTY_FD");
254 /* We don't get a chance to read out the original kb
255 * mode for the tty, so just hard code K_UNICODE here
256 * in case we have to clean if weston-launch dies. */
257 launcher->kb_mode = K_UNICODE;
258
259 loop = wl_display_get_event_loop(compositor->wl_display);
260 launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
261 WL_EVENT_READABLE,
262 launcher_weston_launch_data,
263 launcher);
264 if (launcher->source == NULL) {
265 free(launcher);
266 return -ENOMEM;
267 }
268
269 return 0;
270 } else {
271 return -1;
272 }
273}
274
275static void
276launcher_weston_launch_destroy(struct weston_launcher *launcher_base)
277{
278 struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
279
280 if (launcher->fd != -1) {
281 close(launcher->fd);
282 wl_event_source_remove(launcher->source);
283 } else {
284 launcher_weston_launch_restore(&launcher->base);
Jasper St. Pierre72dea062015-09-23 10:46:47 -0700285 }
286
287 if (launcher->tty >= 0)
288 close(launcher->tty);
289
290 free(launcher);
291}
292
293struct launcher_interface launcher_weston_launch_iface = {
294 launcher_weston_launch_connect,
295 launcher_weston_launch_destroy,
296 launcher_weston_launch_open,
297 launcher_weston_launch_close,
298 launcher_weston_launch_activate_vt,
299 launcher_weston_launch_restore,
300};