diff options
| -rwxr-xr-x | build.sh | 17 | ||||
| -rw-r--r-- | child.c | 106 | ||||
| -rw-r--r-- | child.h | 2 | ||||
| -rw-r--r-- | fdwatcher.c | 128 | ||||
| -rw-r--r-- | fdwatcher.h | 18 | ||||
| -rw-r--r-- | logging.h | 29 | ||||
| -rw-r--r-- | main.c | 40 | ||||
| -rw-r--r-- | network.c | 55 | ||||
| -rw-r--r-- | network.h | 4 | ||||
| -rw-r--r-- | parent.c | 86 | ||||
| -rw-r--r-- | parent.h | 2 |
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); + |
