summaryrefslogtreecommitdiffstats
path: root/sway/ipc.c
blob: ac5246d2a70904d31d1bfea004b71559252976a4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <wlc/wlc.h>
#include <unistd.h>
#include "log.h"
#include "config.h"
#include "commands.h"

static int ipc_socket = -1;

int ipc_handle_connection(int fd, uint32_t mask, void *data);

void init_ipc() {
	ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
	if (ipc_socket == -1) {
		sway_abort("Unable to create IPC socket");
	}

	struct sockaddr_un ipc_sockaddr = {
		.sun_family = AF_UNIX,
		// TODO: use a proper socket path
		.sun_path = "/tmp/sway.sock"
	};

	unlink(ipc_sockaddr.sun_path);
	if (bind(ipc_socket, (struct sockaddr *)&ipc_sockaddr, sizeof(ipc_sockaddr)) == -1) {
		sway_abort("Unable to bind IPC socket");
	}

	if (listen(ipc_socket, 3) == -1) {
		sway_abort("Unable to listen on IPC socket");
	}

	wlc_event_loop_add_fd(ipc_socket, WLC_EVENT_READABLE, ipc_handle_connection, NULL);
}

int ipc_handle_connection(int /*fd*/, uint32_t /*mask*/, void */*data*/) {
	int client_socket = accept(ipc_socket, NULL, NULL);
	if (client_socket == -1) {
		char error[256];
		strerror_r(errno, error, sizeof(error));
		sway_log(L_INFO, "Unable to accept IPC client connection: %s", error);
		return 0;
	}

	char buf[1024];
	if (recv(client_socket, buf, sizeof(buf), 0) == -1) {
		char error[256];
		strerror_r(errno, error, sizeof(error));
		sway_log(L_INFO, "Unable to receive from IPC client: %s", error);
		close(client_socket);
		return 0;
	}

	sway_log(L_INFO, "Executing IPC command: %s", buf);

	bool success = handle_command(config, buf);
	snprintf(buf, sizeof(buf), "{\"success\":%s}\n", success ? "true" : "false");

	if (send(client_socket, buf, strlen(buf), 0) == -1) {
		char error[256];
		strerror_r(errno, error, sizeof(error));
		sway_log(L_INFO, "Unable to send to IPC client: %s", error);
	}

	close(client_socket);
	return 0;
}