Initial commit.

This has the basic event loop, and a first cut of the libffi dispatcher.
diff --git a/client.c b/client.c
new file mode 100644
index 0000000..8312be8
--- /dev/null
+++ b/client.c
@@ -0,0 +1,109 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <ctype.h>
+
+static const char socket_name[] = "\0wayland";
+
+struct method {
+	const char *name;
+	uint32_t opcode;
+};
+
+static const struct method display_methods[] = {
+	{ "get_interface", 0 },
+	{ "create_surface", 1 },
+	{ NULL }
+};
+
+static const struct method surface_methods[] = {
+	{ "get_interface", 0 },
+	{ "post", 1 },
+	{ NULL }
+};
+
+struct interface {
+	const char *name;
+	const struct method *methods;
+};
+
+static const struct interface interfaces[] = {
+	{ "display", display_methods },
+	{ "surface", surface_methods },
+	{ NULL },
+};
+
+int send_request(int sock, const char *buffer, int buffer_len)
+{
+	const struct method *methods;
+	char interface[32], method[32];
+	uint32_t request[3], id, new_id;
+	int i;
+
+	if (sscanf(buffer, "%d/%32[^:]:%32s %d\n",
+		   &id, interface, method, &new_id) != 4) {
+		printf("invalid input, expected <id>/<interface>:<method>\n");
+		return -1;
+	}
+
+	printf("got object id %d, interface \"%s\", name \"%s\"\n",
+	       id, interface, method);
+
+	for (i = 0; interfaces[i].name != NULL; i++) {
+		if (strcmp(interfaces[i].name, interface) == 0)
+			break;
+	}
+	if (interfaces[i].name == NULL) {
+		printf("unknown interface \"%s\"\n", interface);
+		return -1;
+	}
+
+	methods = interfaces[i].methods;
+	for (i = 0; methods[i].name != NULL; i++) {
+		if (strcmp(methods[i].name, method) == 0)
+			break;
+	}
+
+	if (methods[i].name == NULL) {
+		printf("unknown request \"%s\"\n", method);
+		return -1;
+	}
+
+	request[0] = id;
+	request[1] = methods[i].opcode;
+	request[2] = new_id;
+
+	return write(sock, request, sizeof request);
+}
+
+int main(int argc, char *argv[])
+{
+	struct sockaddr_un name;
+	socklen_t size;
+	int sock, len;
+	char buffer[256];
+
+	sock = socket(PF_LOCAL, SOCK_STREAM, 0);
+	if (sock < 0)
+		return -1;
+
+	name.sun_family = AF_LOCAL;
+	memcpy(name.sun_path, socket_name, sizeof socket_name);
+
+	size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
+
+	if (connect (sock, (struct sockaddr *) &name, size) < 0)
+		return -1;
+
+	while (len = read(STDIN_FILENO, buffer, sizeof buffer), len > 0)
+		if (send_request(sock, buffer, len) < 0)
+			break;
+
+	return 0;
+}