diff options
author | Drew DeVault <sir@cmpwn.com> | 2015-11-26 15:06:41 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2015-11-26 15:06:41 -0500 |
commit | a1018f32801320bab67261828394c76dd0fe0c45 (patch) | |
tree | 65ce2056743d8403da295dc1215fcfd1b205727c /swaymsg | |
parent | Parse command line args for swaymsg (diff) | |
download | sway-a1018f32801320bab67261828394c76dd0fe0c45.tar.gz sway-a1018f32801320bab67261828394c76dd0fe0c45.tar.zst sway-a1018f32801320bab67261828394c76dd0fe0c45.zip |
Implement swaymsg IPC behavior
Diffstat (limited to 'swaymsg')
-rw-r--r-- | swaymsg/main.c | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/swaymsg/main.c b/swaymsg/main.c index 7c643758..9c799b54 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c | |||
@@ -3,11 +3,17 @@ | |||
3 | #include <string.h> | 3 | #include <string.h> |
4 | #include <getopt.h> | 4 | #include <getopt.h> |
5 | #include <stdint.h> | 5 | #include <stdint.h> |
6 | #include <sys/un.h> | ||
7 | #include <sys/socket.h> | ||
8 | #include <unistd.h> | ||
6 | #include "stringop.h" | 9 | #include "stringop.h" |
7 | #include "ipc.h" | 10 | #include "ipc.h" |
8 | #include "readline.h" | 11 | #include "readline.h" |
9 | #include "log.h" | 12 | #include "log.h" |
10 | 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 | |||
11 | void sway_terminate(void) { | 17 | void sway_terminate(void) { |
12 | exit(1); | 18 | exit(1); |
13 | } | 19 | } |
@@ -22,11 +28,66 @@ char *get_socketpath(void) { | |||
22 | return line; | 28 | return line; |
23 | } | 29 | } |
24 | 30 | ||
31 | char *do_ipc(const char *socket_path, uint32_t type, const char *payload, uint32_t len) { | ||
32 | struct sockaddr_un addr; | ||
33 | int socketfd; | ||
34 | if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { | ||
35 | sway_abort("Unable to open Unix socket"); | ||
36 | } | ||
37 | addr.sun_family = AF_UNIX; | ||
38 | strcpy(addr.sun_path, socket_path); | ||
39 | int l = sizeof(addr.sun_family) + strlen(addr.sun_path); | ||
40 | if (connect(socketfd, (struct sockaddr *)&addr, l) == -1) { | ||
41 | sway_abort("Unable to connect to %s", socket_path); | ||
42 | } | ||
43 | |||
44 | char data[ipc_header_size]; | ||
45 | uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic)); | ||
46 | memcpy(data, ipc_magic, sizeof(ipc_magic)); | ||
47 | data32[0] = len; | ||
48 | data32[1] = type; | ||
49 | |||
50 | if (write(socketfd, data, ipc_header_size) == -1) { | ||
51 | sway_abort("Unable to send IPC header"); | ||
52 | } | ||
53 | |||
54 | if (write(socketfd, payload, len) == -1) { | ||
55 | sway_abort("Unable to send IPC payload"); | ||
56 | } | ||
57 | |||
58 | size_t total = 0; | ||
59 | while (total < ipc_header_size) { | ||
60 | ssize_t received = recv(socketfd, data + total, ipc_header_size - total, 0); | ||
61 | if (received < 0) { | ||
62 | sway_abort("Unable to receive IPC response"); | ||
63 | } | ||
64 | total += received; | ||
65 | } | ||
66 | |||
67 | total = 0; | ||
68 | len = data32[0]; | ||
69 | char *response = malloc(len + 1); | ||
70 | while (total < len) { | ||
71 | ssize_t received = recv(socketfd, response + total, len - total, 0); | ||
72 | if (received < 0) { | ||
73 | sway_abort("Unable to receive IPC response"); | ||
74 | } | ||
75 | total += received; | ||
76 | } | ||
77 | response[len] = '\0'; | ||
78 | |||
79 | close(socketfd); | ||
80 | |||
81 | return response; | ||
82 | } | ||
83 | |||
25 | int main(int argc, char **argv) { | 84 | int main(int argc, char **argv) { |
26 | static int quiet = 0; | 85 | static int quiet = 0; |
27 | char *socket_path = NULL; | 86 | char *socket_path = NULL; |
28 | char *cmdtype = NULL; | 87 | char *cmdtype = NULL; |
29 | 88 | ||
89 | init_log(L_INFO); | ||
90 | |||
30 | static struct option long_options[] = { | 91 | static struct option long_options[] = { |
31 | {"quiet", no_argument, &quiet, 'q'}, | 92 | {"quiet", no_argument, &quiet, 'q'}, |
32 | {"version", no_argument, NULL, 'v'}, | 93 | {"version", no_argument, NULL, 'v'}, |
@@ -63,7 +124,7 @@ int main(int argc, char **argv) { | |||
63 | } | 124 | } |
64 | 125 | ||
65 | if (!cmdtype) { | 126 | if (!cmdtype) { |
66 | cmdtype = "command"; | 127 | cmdtype = strdup("command"); |
67 | } | 128 | } |
68 | if (!socket_path) { | 129 | if (!socket_path) { |
69 | socket_path = get_socketpath(); | 130 | socket_path = get_socketpath(); |
@@ -89,13 +150,20 @@ int main(int argc, char **argv) { | |||
89 | } else if (strcasecmp(cmdtype, "get_version") == 0) { | 150 | } else if (strcasecmp(cmdtype, "get_version") == 0) { |
90 | type = IPC_GET_VERSION; | 151 | type = IPC_GET_VERSION; |
91 | } | 152 | } |
153 | free(cmdtype); | ||
92 | 154 | ||
93 | char *command = strdup(""); | 155 | char *command = strdup(""); |
94 | if (optind < argc) { | 156 | if (optind < argc) { |
95 | command = join_args(argv + optind, argc - optind); | 157 | command = join_args(argv + optind, argc - optind); |
96 | } | 158 | } |
97 | 159 | ||
98 | printf("%s", command); | 160 | char *resp = do_ipc(socket_path, type, command, strlen(command)); |
161 | if (!quiet) { | ||
162 | printf("%s", resp); | ||
163 | } | ||
164 | |||
165 | free(command); | ||
166 | free(resp); | ||
99 | free(socket_path); | 167 | free(socket_path); |
100 | return 0; | 168 | return 0; |
101 | } | 169 | } |