summary refs log tree commit diff
path: root/fdwatcher.c
diff options
context:
space:
mode:
Diffstat (limited to 'fdwatcher.c')
-rw-r--r--fdwatcher.c128
1 files changed, 128 insertions, 0 deletions
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();
+}