]> git.sur5r.net Git - i3/i3/blob - i3-msg/main.c
Merge branch 'next' into testcases
[i3/i3] / i3-msg / main.c
1 /*
2  * vim:ts=8:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  *
6  * © 2009 Michael Stapelberg and contributors
7  *
8  * See file LICENSE for license information.
9  *
10  * i3-msg/main.c: Utility which sends messages to a running i3-instance using
11  * IPC via UNIX domain sockets.
12  *
13  * This serves as an example for how to send your own messages to i3.
14  * Additionally, it’s even useful sometimes :-).
15  *
16  */
17 #include <ev.h>
18 #include <stdio.h>
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <err.h>
27 #include <stdint.h>
28 #include <getopt.h>
29
30 /*
31  * Formats a message (payload) of the given size and type and sends it to i3 via
32  * the given socket file descriptor.
33  *
34  */
35 static void ipc_send_message(int sockfd, uint32_t message_size,
36                              uint32_t message_type, uint8_t *payload) {
37         int buffer_size = strlen("i3-ipc") + sizeof(uint32_t) + sizeof(uint32_t) + message_size;
38         char msg[buffer_size];
39         char *walk = msg;
40
41         strcpy(walk, "i3-ipc");
42         walk += strlen("i3-ipc");
43         memcpy(walk, &message_size, sizeof(uint32_t));
44         walk += sizeof(uint32_t);
45         memcpy(walk, &message_type, sizeof(uint32_t));
46         walk += sizeof(uint32_t);
47         memcpy(walk, payload, message_size);
48
49         int sent_bytes = 0;
50         int bytes_to_go = buffer_size;
51         while (sent_bytes < bytes_to_go) {
52                 int n = write(sockfd, msg + sent_bytes, bytes_to_go);
53                 if (n == -1)
54                         err(EXIT_FAILURE, "write() failed");
55
56                 sent_bytes += n;
57                 bytes_to_go -= n;
58         }
59 }
60
61 int main(int argc, char *argv[]) {
62         char *socket_path = "/tmp/i3-ipc.sock";
63         int o, option_index = 0;
64
65         static struct option long_options[] = {
66                 {"socket", required_argument, 0, 's'},
67                 {"type", required_argument, 0, 't'},
68                 {"version", no_argument, 0, 'v'},
69                 {"help", no_argument, 0, 'h'},
70                 {0, 0, 0, 0}
71         };
72
73         char *options_string = "s:t:vh";
74
75         while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) {
76                 if (o == 's') {
77                         socket_path = strdup(optarg);
78                         break;
79                 } else if (o == 't') {
80                         printf("currently only commands are implemented\n");
81                 } else if (o == 'v') {
82                         printf("i3-msg " I3_VERSION);
83                         return 0;
84                 } else if (o == 'h') {
85                         printf("i3-msg " I3_VERSION);
86                         printf("i3-msg [-s <socket>] [-t <type>] <message>\n");
87                         return 0;
88                 }
89         }
90
91         if (optind >= argc) {
92                 fprintf(stderr, "Error: missing message\n");
93                 fprintf(stderr, "i3-msg [-s <socket>] [-t <type>] <message>\n");
94                 return 1;
95         }
96
97         int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
98         if (sockfd == -1)
99                 err(EXIT_FAILURE, "Could not create socket");
100
101         struct sockaddr_un addr;
102         memset(&addr, 0, sizeof(struct sockaddr_un));
103         addr.sun_family = AF_LOCAL;
104         strcpy(addr.sun_path, socket_path);
105         if (connect(sockfd, (const struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0)
106                 err(EXIT_FAILURE, "Could not connect to i3");
107
108         ipc_send_message(sockfd, strlen(argv[optind]), 0, (uint8_t*)argv[optind]);
109
110         close(sockfd);
111
112         return 0;
113 }