main neuswc / libswc / launch.c
  1/* swc: libswc/launch.c
  2 *
  3 * Copyright (c) 2013, 2014 Michael Forney
  4 *
  5 * Permission is hereby granted, free of charge, to any person obtaining a copy
  6 * of this software and associated documentation files (the "Software"), to deal
  7 * in the Software without restriction, including without limitation the rights
  8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9 * copies of the Software, and to permit persons to whom the Software is
 10 * furnished to do so, subject to the following conditions:
 11 *
 12 * The above copyright notice and this permission notice shall be included in
 13 * all copies or substantial portions of the Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 21 * SOFTWARE.
 22 */
 23
 24#include "launch.h"
 25#include "event.h"
 26#include "internal.h"
 27#include "launch/protocol.h"
 28#include "util.h"
 29
 30#include <fcntl.h>
 31#include <sys/uio.h>
 32#include <unistd.h>
 33#include <wayland-server.h>
 34
 35static struct {
 36	int socket;
 37	struct wl_event_source *source;
 38	uint32_t next_serial;
 39} launch;
 40
 41static bool
 42handle_event(struct swc_launch_event *event)
 43{
 44	switch (event->type) {
 45	case SWC_LAUNCH_EVENT_ACTIVATE:
 46		swc_activate();
 47		break;
 48	case SWC_LAUNCH_EVENT_DEACTIVATE:
 49		swc_deactivate();
 50		break;
 51	default:
 52		return false;
 53	}
 54
 55	return true;
 56}
 57
 58static int
 59handle_data(int fd, uint32_t mask, void *data)
 60{
 61	struct swc_launch_event event;
 62	struct iovec iov[1] = {
 63	    {.iov_base = &event, .iov_len = sizeof(event)},
 64	};
 65
 66	if (receive_fd(fd, NULL, iov, 1) != -1) {
 67		handle_event(&event);
 68	}
 69	return 1;
 70}
 71
 72bool
 73launch_initialize(void)
 74{
 75	char *socket_string, *end;
 76
 77	if (!(socket_string = getenv(SWC_LAUNCH_SOCKET_ENV))) {
 78		return false;
 79	}
 80
 81	launch.socket = strtol(socket_string, &end, 10);
 82	if (*end != '\0') {
 83		return false;
 84	}
 85
 86	unsetenv(SWC_LAUNCH_SOCKET_ENV);
 87	if (fcntl(launch.socket, F_SETFD, FD_CLOEXEC) < 0) {
 88		return false;
 89	}
 90
 91	launch.source = wl_event_loop_add_fd(swc.event_loop, launch.socket,
 92	                                     WL_EVENT_READABLE, &handle_data, NULL);
 93	if (!launch.source) {
 94		return false;
 95	}
 96
 97	return true;
 98}
 99
100void
101launch_finalize(void)
102{
103	wl_event_source_remove(launch.source);
104	close(launch.socket);
105}
106
107static bool
108send_request(struct swc_launch_request *request, const void *data, size_t size,
109             struct swc_launch_event *event, int out_fd, int *in_fd)
110{
111	struct iovec request_iov[2] = {
112	    {.iov_base = request, .iov_len = sizeof(*request)},
113	    {.iov_base = (void *)data, .iov_len = size},
114	};
115	struct iovec response_iov[1] = {
116	    {.iov_base = event, .iov_len = sizeof(*event)},
117	};
118
119	request->serial = ++launch.next_serial;
120
121	if (send_fd(launch.socket, out_fd, request_iov, 1 + (size > 0)) == -1) {
122		return false;
123	}
124
125	while (receive_fd(launch.socket, in_fd, response_iov, 1) != -1) {
126		if (event->type == SWC_LAUNCH_EVENT_RESPONSE &&
127		    event->serial == request->serial) {
128			return true;
129		}
130		handle_event(event);
131	}
132
133	return false;
134}
135
136int
137launch_open_device(const char *path, int flags)
138{
139	struct swc_launch_request request;
140	struct swc_launch_event response;
141	int fd;
142
143	request.type = SWC_LAUNCH_REQUEST_OPEN_DEVICE;
144	request.flags = flags;
145
146	if (!send_request(&request, path, strlen(path) + 1, &response, -1, &fd)) {
147		return -1;
148	}
149
150	return fd;
151}
152
153bool
154launch_activate_vt(unsigned vt)
155{
156	struct swc_launch_request request;
157	struct swc_launch_event response;
158
159	request.type = SWC_LAUNCH_REQUEST_ACTIVATE_VT;
160	request.vt = vt;
161
162	if (!send_request(&request, NULL, 0, &response, -1, NULL)) {
163		return false;
164	}
165
166	return response.success;
167}