main wf/howl / src / client.c
  1#include <stdio.h>
  2#include <stdlib.h>
  3#include <string.h>
  4#include <unistd.h>
  5#include <sys/socket.h>
  6#include <sys/un.h>
  7
  8#include "howl.h"
  9#include "types.h"
 10#include "ipc.h"
 11
 12struct command {
 13	const char *name;
 14	enum cmd id;
 15	int argc;
 16	bool config;
 17};
 18
 19static const struct command commands[] = {
 20	{ "move",                cmd_move,                2, false },
 21	{ "move_absolute",       cmd_move_absolute,       2, false },
 22	{ "resize",              cmd_resize,              2, false },
 23	{ "resize_absolute",     cmd_resize_absolute,     2, false },
 24	{ "teleport",            cmd_teleport,            4, false },
 25	{ "center",              cmd_center,              0, false },
 26	{ "fullscreen",          cmd_fullscreen,          0, false },
 27	{ "hide",                cmd_hide,                0, false },
 28	{ "show",                cmd_show,                0, false },
 29	{ "lower",               cmd_lower,               0, false },
 30	{ "raise",               cmd_raise,               0, false },
 31	{ "focus_prev",          cmd_focus_prev,          0, false },
 32	{ "focus_next",          cmd_focus_next,          0, false },
 33	{ "close",               cmd_close,               0, false },
 34	{ "workspace",           cmd_workspace,           1, false },
 35	{ "move_workspace",      cmd_move_workspace,      1, false },
 36	{ "get_geometry",        cmd_get_geometry,        0, false },
 37	{ "get_pid",             cmd_get_pid,             0, false },
 38	{ "get_title",           cmd_get_title,           0, false },
 39	{ "get_app_id",          cmd_get_app_id,          0, false },
 40	{ "get_focus",           cmd_get_focus,           0, false },
 41	{ "get_workspace",       cmd_get_workspace,       0, false },
 42	{ "get_screen_geometry", cmd_get_screen_geometry, 0, false },
 43	{ "get_cursor_position", cmd_get_cursor_position, 0, false },
 44	{ "list_windows",        cmd_list_windows,        0, false },
 45	{ "bind",                cmd_bind,                2, false },
 46	{ "unbind",              cmd_unbind,              1, false },
 47	{ "modkey",              cmd_modkey,              1, true  },
 48	{ "inner_focus_color",   cmd_inner_focus_color,   1, true  },
 49	{ "inner_unfocus_color", cmd_inner_unfocus_color, 1, true  },
 50	{ "outer_focus_color",   cmd_outer_focus_color,   1, true  },
 51	{ "outer_unfocus_color", cmd_outer_unfocus_color, 1, true  },
 52	{ "inner_border_width",  cmd_inner_border_width,  1, true  },
 53	{ "outer_border_width",  cmd_outer_border_width,  1, true  },
 54	{ "title_format",        cmd_title_format,        1, true  },
 55	{ "set_decor",           cmd_set_decor,           1, true  },
 56	{ "quit",                cmd_quit,                0, false }
 57};
 58
 59static int
 60ipc_msg(const struct command *cmd, int argc, char **argv) {
 61	char buf[512];
 62	size_t n = 0;
 63
 64	struct sockaddr_un addr = {0};
 65	addr.sun_family = AF_UNIX;
 66	strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
 67
 68	int fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
 69	if (fd < 0) {
 70		perror("couldn't open IPC socket");
 71		return 1;
 72	}
 73
 74	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
 75		perror("couldn't connect to IPC socket");
 76		close(fd);
 77		return 1;
 78	}
 79
 80	if (cmd->config) {
 81		int r = snprintf(buf + n, sizeof(buf) - n, "%d %d", cmd_config, cmd->id);
 82		n += r;
 83	} else {
 84		int r = snprintf(buf + n, sizeof(buf) - n, "%d", cmd->id);
 85		n += r;
 86	}
 87
 88	for (int i = 2; i < argc; i++) {
 89		int r = snprintf(buf + n, sizeof(buf) - n, " %s", argv[i]);
 90		n += r;
 91	}
 92
 93	buf[n] = '\0';
 94	if (write(fd, buf, strlen(buf)) < 0) {
 95		perror("couldn't send IPC message");
 96		close(fd);
 97		return 1;
 98	}
 99
100	char buf2[512];
101	if ((n = read(fd, buf2, sizeof(buf2) - 1)) <= 0) {
102		perror("couldn't read from IPC socket");
103		close(fd);
104		return 1;
105	}
106	buf2[n] = '\0';
107
108	char *ans;
109	long ret = strtol(buf2, &ans, 10);
110	if (ans == buf2)
111		ret = 0;
112
113	while (*ans == ' ')
114		ans++;
115
116	if (strcmp(ans, "") != 0) {
117		if (ret == 0)
118			fprintf(stderr, "%s", ans);
119		else
120			printf("%s", ans);
121	}
122	return (int)ret;
123}
124
125int
126main(int argc, char **argv) {
127	if (argc < 2) {
128		fprintf(stderr, "Usage: howlc cmd [args...]\n");
129		return 1;
130	}
131
132	for (int i = 0; i < (int)(sizeof commands / sizeof commands[0]); i++) {
133		if (strcmp(argv[1], commands[i].name) == 0) {
134			if (argc - 2 < commands[i].argc) {
135				fprintf(stderr, "Wrong number of arguments for %s (need %d)\n", commands[i].name, commands[i].argc);
136				return 1;
137			}
138			return ipc_msg(&commands[i], argc, argv);
139		}
140	}
141	
142	fprintf(stderr, "No such command: %s\n", argv[1]);
143	return 1;
144}