diff options
author | Drew DeVault <sir@cmpwn.com> | 2015-11-27 09:50:04 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2015-11-27 09:50:04 -0500 |
commit | 27f03c705d8851a8ef6ca9e8f7828c1a2bfd9a88 (patch) | |
tree | 740a9e384149879a2c106220212bef36c05f58f3 /common/ipc-client.c | |
parent | Fix build warnings (diff) | |
download | sway-27f03c705d8851a8ef6ca9e8f7828c1a2bfd9a88.tar.gz sway-27f03c705d8851a8ef6ca9e8f7828c1a2bfd9a88.tar.zst sway-27f03c705d8851a8ef6ca9e8f7828c1a2bfd9a88.zip |
Move IPC client into common, refactor IPC
Diffstat (limited to 'common/ipc-client.c')
-rw-r--r-- | common/ipc-client.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/common/ipc-client.c b/common/ipc-client.c new file mode 100644 index 00000000..916676a9 --- /dev/null +++ b/common/ipc-client.c | |||
@@ -0,0 +1,78 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | #include <getopt.h> | ||
5 | #include <stdint.h> | ||
6 | #include <sys/un.h> | ||
7 | #include <sys/socket.h> | ||
8 | #include <unistd.h> | ||
9 | #include "log.h" | ||
10 | #include "stringop.h" | ||
11 | #include "ipc-server.h" | ||
12 | #include "readline.h" | ||
13 | |||
14 | static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; | ||
15 | static const size_t ipc_header_size = sizeof(ipc_magic)+8; | ||
16 | |||
17 | char *get_socketpath(void) { | ||
18 | FILE *fp = popen("sway --get-socketpath", "r"); | ||
19 | if (!fp) { | ||
20 | return NULL; | ||
21 | } | ||
22 | char *line = read_line(fp); | ||
23 | pclose(fp); | ||
24 | return line; | ||
25 | } | ||
26 | |||
27 | char *ipc_single_command(const char *socket_path, uint32_t type, const char *payload, uint32_t len) { | ||
28 | struct sockaddr_un addr; | ||
29 | int socketfd; | ||
30 | if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { | ||
31 | sway_abort("Unable to open Unix socket"); | ||
32 | } | ||
33 | addr.sun_family = AF_UNIX; | ||
34 | strcpy(addr.sun_path, socket_path); | ||
35 | int l = sizeof(addr.sun_family) + strlen(addr.sun_path); | ||
36 | if (connect(socketfd, (struct sockaddr *)&addr, l) == -1) { | ||
37 | sway_abort("Unable to connect to %s", socket_path); | ||
38 | } | ||
39 | |||
40 | char data[ipc_header_size]; | ||
41 | uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic)); | ||
42 | memcpy(data, ipc_magic, sizeof(ipc_magic)); | ||
43 | data32[0] = len; | ||
44 | data32[1] = type; | ||
45 | |||
46 | if (write(socketfd, data, ipc_header_size) == -1) { | ||
47 | sway_abort("Unable to send IPC header"); | ||
48 | } | ||
49 | |||
50 | if (write(socketfd, payload, len) == -1) { | ||
51 | sway_abort("Unable to send IPC payload"); | ||
52 | } | ||
53 | |||
54 | size_t total = 0; | ||
55 | while (total < ipc_header_size) { | ||
56 | ssize_t received = recv(socketfd, data + total, ipc_header_size - total, 0); | ||
57 | if (received < 0) { | ||
58 | sway_abort("Unable to receive IPC response"); | ||
59 | } | ||
60 | total += received; | ||
61 | } | ||
62 | |||
63 | total = 0; | ||
64 | len = data32[0]; | ||
65 | char *response = malloc(len + 1); | ||
66 | while (total < len) { | ||
67 | ssize_t received = recv(socketfd, response + total, len - total, 0); | ||
68 | if (received < 0) { | ||
69 | sway_abort("Unable to receive IPC response"); | ||
70 | } | ||
71 | total += received; | ||
72 | } | ||
73 | response[len] = '\0'; | ||
74 | |||
75 | close(socketfd); | ||
76 | |||
77 | return response; | ||
78 | } | ||