summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xbuild.sh17
-rw-r--r--child.c106
-rw-r--r--child.h2
-rw-r--r--fdwatcher.c128
-rw-r--r--fdwatcher.h18
-rw-r--r--logging.h29
-rw-r--r--main.c40
-rw-r--r--network.c55
-rw-r--r--network.h4
-rw-r--r--parent.c86
-rw-r--r--parent.h2
11 files changed, 487 insertions, 0 deletions
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..6f1ddad
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+set -e; # exit on error
+
+#CC="x86_64-unknown-linux-musl-gcc"
+CC="gcc"
+
+roll_print() { printf "\t\t%s\t%s\n" "$1" "$2"; }
+
+for i in fdwatcher network parent child main; do
+	roll_print "CC" "$i.o"
+	"$CC" -I. -c -o "$i.o" "$i.c"
+done
+
+"$CC" -static -o aura fdwatcher.o network.o parent.o child.o main.o
+strip aura
+
diff --git a/child.c b/child.c
new file mode 100644
index 0000000..58ee999
--- /dev/null
+++ b/child.c
@@ -0,0 +1,106 @@
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "fdwatcher.h"
+#include "logging.h"
+
+struct ConnectionDataBuffer {
+	size_t capacity;
+	size_t length;
+	char buf[];
+};
+
+struct ConnectionData {
+	struct ConnectionDataBuffer *buffer;
+};
+
+static int
+aura_addbufferdata(struct ConnectionDataBuffer *buffer, char *data, size_t length)
+{
+	if (buffer->length + length > buffer->capacity) {
+		aura_printf("FUCK!\n");
+		aura_printf("buffer->length: %ld\n", buffer->length);
+		aura_printf("buffer->capacity: %ld\n", buffer->capacity);
+		aura_printf("length: %ld\n", length);
+
+		abort();
+	}
+
+	memcpy(buffer->buf, data, length);
+	buffer->length = buffer->length + length;
+
+	return 0;
+}
+
+static int
+meowiero(struct FDWatchHandle *handle, enum FDWatch_EventType type, int fd, void *data)
+{
+	struct ConnectionData *connectiondata = (struct ConnectionData *)data;
+	char c = 0;
+
+	switch (type) {
+	case FDWATCH_EVENT_INP:
+		aura_printf("INPUT event in fd:%d\n", fd);
+
+		read(fd, &c, 2);
+		aura_addbufferdata(connectiondata->buffer, &c, 2);
+
+		aura_printf("%c\n", c);
+		break;
+	case FDWATCH_EVENT_HUP:
+		aura_printf("HANGUP event in fd:%d, exiting\n", fd);
+		fdwatcher_remove(handle, fd);
+		close(fd);
+		return 0;
+	}
+
+	return 1;
+}
+
+/* init */
+int childProcessMain(int argc, char **argv)
+{
+	struct ConnectionData *connectiondata = { 0 };
+	struct FDWatchHandle fdhandle = { 0 };
+	int sockie = 0;
+	int ret = 0;
+
+	connectiondata = (struct ConnectionData *)malloc(sizeof(struct ConnectionData));
+	if (errno != 0) {
+		perror("malloc(3)");
+		return 1;
+	}
+
+	connectiondata->buffer = malloc(sizeof(struct ConnectionDataBuffer) + 65536);
+	if (errno != 0) {
+		perror("malloc(3)");
+		return 1;
+	}
+	connectiondata->buffer->capacity = 65536;
+
+	/* socket fd int in argv[2]! ^w^ */
+	sscanf(argv[2], "%d", &sockie);
+	aura_printf("received fd:%d\n", sockie);
+
+	ret = fdwatcher_initialise(&fdhandle, 1);
+	if (ret < 0) {
+		aura_fprintf(stderr, "fdwatcher_initialise failed\n");
+		return 1;
+	}
+
+	ret = fdwatcher_add(&fdhandle, sockie, (void *)connectiondata);
+	if (ret < 0) {
+		aura_fprintf(stderr, "fdwatcher_add failed\n");
+		return 1;
+	}
+
+	fdwatcher_watch(&fdhandle, meowiero);
+	aura_printf("finished\n");
+
+	return 0;
+}
+
diff --git a/child.h b/child.h
new file mode 100644
index 0000000..2a63c2d
--- /dev/null
+++ b/child.h
@@ -0,0 +1,2 @@
+int childProcessMain(int, char **);
+
diff --git a/fdwatcher.c b/fdwatcher.c
new file mode 100644
index 0000000..8e0cb97
--- /dev/null
+++ b/fdwatcher.c
@@ -0,0 +1,128 @@
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <poll.h>
+
+#include <fdwatcher.h>
+
+int
+fdwatcher_initialise(struct FDWatchHandle *handle, int maxWatchedFds)
+{
+	size_t pollfdSize = maxWatchedFds * sizeof(handle->watchedFds);
+	size_t pointersSize = maxWatchedFds * sizeof(void *);
+
+	handle->watchedFds = malloc(pollfdSize);
+	if (errno != 0) {
+		perror("fdwatcher_initialise: malloc(3)");
+		return -errno;
+	}
+
+	handle->arbitraryData = malloc(pointersSize);
+	if (errno != 0) {
+		perror("fdwatcher_initialise: malloc(3)");
+		return -errno;
+	}
+
+	memset(handle->watchedFds, 0, pollfdSize);
+	handle->maxWatchedFds = maxWatchedFds;
+	return 0;
+}
+
+int
+fdwatcher_add(struct FDWatchHandle *handle, int fd, void *arbitrary)
+{
+	struct pollfd *watchedFd = NULL;
+
+	if (handle->maxWatchedFds == handle->watchedFdCount) {
+		printf("meow\n");
+		return -EMFILE;
+	}
+
+	handle->arbitraryData[handle->watchedFdCount] = arbitrary;
+	watchedFd = &(handle->watchedFds[handle->watchedFdCount]);
+	watchedFd->events = POLLIN | POLLHUP | POLLRDHUP;
+	watchedFd->revents = 0;
+	watchedFd->fd = fd;
+
+	handle->watchedFdCount = handle->watchedFdCount + 1;
+	return 0;
+}
+
+static int
+_fdwatcher_handleEvents_revents(struct pollfd *pollie, struct FDWatchHandle *handle,
+			      int (*meow)(struct FDWatchHandle *, enum FDWatch_EventType, int, void *),
+			      size_t elementNumber)
+{
+	int ret = 0;
+
+	if (pollie->revents & POLLHUP || pollie->revents & POLLRDHUP) {
+		ret = meow(handle, FDWATCH_EVENT_HUP, pollie->fd, handle->arbitraryData[elementNumber]);
+		if (ret == 0) {
+			return 1;
+		}
+	}
+
+	if (pollie->revents & POLLIN) {
+		meow(handle, FDWATCH_EVENT_INP, pollie->fd, handle->arbitraryData[elementNumber]);
+	}
+	return 0;
+}
+
+static int
+_fdwatcher_handleEvents(struct FDWatchHandle *handle, int (*meow)(struct FDWatchHandle *handle, enum FDWatch_EventType, int, void *))
+{
+	size_t i = 0;
+	int ret = 0;
+
+	while (1) {
+		if (i == handle->watchedFdCount) break;
+
+		struct pollfd *watchedFdEntry = NULL;
+		watchedFdEntry = &handle->watchedFds[i];
+
+		if (watchedFdEntry->revents != 0) {
+			ret = _fdwatcher_handleEvents_revents(watchedFdEntry, handle, meow, i);
+			watchedFdEntry->revents = 0;
+
+			if (ret != 0) {
+				return 1;
+			}
+		}
+		i++;
+	}
+
+	return 0;
+}
+
+int
+fdwatcher_watch(struct FDWatchHandle *handle, int (*meow)(struct FDWatchHandle *handle, enum FDWatch_EventType, int, void *))
+{
+	int ret = 0;
+
+	while (1) {
+		ret = poll(handle->watchedFds, handle->watchedFdCount, INT_MAX);
+		if (errno != 0) {
+			ret = meow(handle, FDWATCH_EVENT_ERR, 0, NULL);
+
+			if (ret == 1) break;
+			errno = 0;
+			continue;
+		}
+
+		ret = _fdwatcher_handleEvents(handle, meow);
+		if (ret == 1) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/* TODO */
+int
+fdwatcher_remove(struct FDWatchHandle *handle, int fd)
+{
+	abort();
+}
diff --git a/fdwatcher.h b/fdwatcher.h
new file mode 100644
index 0000000..ce90198
--- /dev/null
+++ b/fdwatcher.h
@@ -0,0 +1,18 @@
+struct FDWatchHandle {
+	int maxWatchedFds;
+	int watchedFdCount;
+	struct pollfd *watchedFds;
+	void **arbitraryData;
+};
+
+enum FDWatch_EventType {
+	FDWATCH_EVENT_ERR = 0,
+	FDWATCH_EVENT_INP = 1,
+	FDWATCH_EVENT_OUT = 2,
+	FDWATCH_EVENT_HUP = 3
+};
+
+int fdwatcher_watch(struct FDWatchHandle *, int (*)(struct FDWatchHandle *, enum FDWatch_EventType, int, void *));
+int fdwatcher_initialise(struct FDWatchHandle *, int);
+int fdwatcher_remove(struct FDWatchHandle *, int);
+int fdwatcher_add(struct FDWatchHandle *, int, void *);
diff --git a/logging.h b/logging.h
new file mode 100644
index 0000000..6ad5729
--- /dev/null
+++ b/logging.h
@@ -0,0 +1,29 @@
+#include <stdarg.h>
+#include <unistd.h>
+
+static void
+aura_printf(const char *fmt, ...)
+{
+	va_list args = { 0 };
+
+	printf("[%d] ", getpid());
+	va_start(args, fmt);
+	vprintf(fmt, args);
+	va_end(args);
+
+	return;
+}
+
+static void
+aura_fprintf(FILE *stream, const char *fmt, ...)
+{
+	va_list args = { 0 };
+
+	fprintf(stream, "[%d] ", getpid());
+	va_start(args, fmt);
+	vfprintf(stream, fmt, args);
+	va_end(args);
+
+	return;
+}
+
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..8a87442
--- /dev/null
+++ b/main.c
@@ -0,0 +1,40 @@
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "fdwatcher.h"
+#include "logging.h"
+#include "network.h"
+#include "parent.h"
+#include "child.h"
+
+int
+isChildProcess(int argc, char **argv)
+{
+	if (argc < 3) {
+		return 0;
+	}
+
+	if (strcmp(argv[1], "childprocess") != 0) {
+		return 0;
+	}
+
+	return 1;
+}
+
+int
+main(int argc, char **argv)
+{
+	#ifdef __OpenBSD__
+	aura_printf("hello, OpenBSD user. for paranoia's sake, pledge(3) will be run.\n");
+	pledge("stdio inet", "stdio inet");
+	aura_printf("yippie\n");
+	#endif
+
+	if (isChildProcess(argc, argv)) {
+		aura_printf("child process\n");
+		return childProcessMain(argc, argv);
+	}
+
+	return parentProcessMain();
+}
diff --git a/network.c b/network.c
new file mode 100644
index 0000000..263e2cb
--- /dev/null
+++ b/network.c
@@ -0,0 +1,55 @@
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include "network.h"
+
+int
+net_listen4(uint32_t ip, uint16_t port, int backlog)
+{
+	struct sockaddr_in addr_in = { 0 };
+	int sock = 0;
+	int temp = 1;
+
+	if (ip != 0) {
+		return -ENOSYS;
+	}
+
+	if (port == 0) {
+		return -EINVAL;
+	}
+
+	addr_in.sin_port = htons(port);
+	sock = socket(AF_INET, SOCK_STREAM, 0);
+	if (errno != 0) {
+		perror("socket(3)");
+		return -errno;
+	}
+
+	temp = 1;
+	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &temp, sizeof(temp));
+	if (errno != 0) {
+		perror("setsockopt(3)");
+		close(sock);
+		return -errno;
+	}
+
+	bind(sock, (struct sockaddr *)&addr_in, sizeof(addr_in));
+	if (errno != 0) {
+		perror("bind(3)");
+		close(sock);
+		return -errno;
+	}
+
+	listen(sock, backlog);
+	if (errno != 0) {
+		perror("listen(3)");
+		close(sock);
+		return -errno;
+	}
+
+	return sock;
+}
+
diff --git a/network.h b/network.h
new file mode 100644
index 0000000..5db105b
--- /dev/null
+++ b/network.h
@@ -0,0 +1,4 @@
+#include <stdint.h>
+
+int net_listen4(uint32_t, uint16_t, int);
+
diff --git a/parent.c b/parent.c
new file mode 100644
index 0000000..a3cbb4a
--- /dev/null
+++ b/parent.c
@@ -0,0 +1,86 @@
+#include <sys/socket.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "fdwatcher.h"
+#include "logging.h"
+#include "network.h"
+
+char *meowA = "haze";
+char *meowB = "childprocess";
+
+static int
+handleNewConnection(int serverfd)
+{
+	char *childProcessArgv[4] = { meowA, meowB, "", NULL };
+	struct sockaddr address = { 0 };
+	socklen_t addrSize = sizeof(address);
+	char chocolate[11] = { 0 };
+	pid_t kwiat = 0;
+	int sock = 0;
+
+	sock = accept(serverfd, &address, &addrSize);
+	if (errno != 0) {
+		perror("accept(3)");
+		return -1;
+	}
+
+	kwiat = fork();
+	if (kwiat == 0) {
+		snprintf((char *)&chocolate, 10, "%d", sock);
+		childProcessArgv[2] = (char *)&chocolate;
+		close(serverfd);
+		execve("/proc/self/exe", childProcessArgv, NULL);
+		perror("execve(3)");
+		abort();
+	}
+	close(sock);
+
+	return 0;
+}
+
+static int
+meowie(struct FDWatchHandle *handle, enum FDWatch_EventType type, int fd, void *data)
+{
+	switch (type) {
+	case FDWATCH_EVENT_INP:
+		aura_printf("INPUT event in fd:%d\n", fd);
+		handleNewConnection(fd);
+		break;
+	}
+
+	return 1;
+}
+
+int
+parentProcessMain(void)
+{
+	struct FDWatchHandle fdhandle = { 0 };
+	int sock = 0;
+	int ret = 0;
+
+	sock = net_listen4(0, 4096, 0);
+	if (sock < 0) {
+		aura_fprintf(stderr, "net_listen4 failed\n");
+		return 1;
+	}
+
+	ret = fdwatcher_initialise(&fdhandle, 1);
+	if (ret < 0) {
+		aura_fprintf(stderr, "fdwatcher_initialise failed\n");
+		return 1;
+	}
+
+	ret = fdwatcher_add(&fdhandle, sock, NULL);
+	if (ret < 0) {
+		aura_fprintf(stderr, "fdwatcher_add failed\n");
+		return 1;
+	}
+
+	aura_printf("Listening on fd:%d\n", sock);
+
+	fdwatcher_watch(&fdhandle, meowie);
+}
+
diff --git a/parent.h b/parent.h
new file mode 100644
index 0000000..8e6503a
--- /dev/null
+++ b/parent.h
@@ -0,0 +1,2 @@
+int parentProcessMain(void);
+