#define _GNU_SOURCE

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <limits.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/eventfd.h>

#define MAX_EFD 100

struct event {
	char *path;
	char *args;
};

int main(int argc, char **argv)
{
	struct event events[MAX_EFD];
	struct pollfd pollfds[MAX_EFD];
	int n = 0;
	char line[PATH_MAX];
	int ret;

	while (fgets(line, PATH_MAX, stdin)) {
		int event_control, cfd;
		char *args = strchrnul(line, ' ');

		if (n >= MAX_EFD) {
			fprintf(stderr, "Too many events registered\n");
		}

		if (*args)
			*args++ = '\0';

		events[n].path = malloc(strlen(line) + 1);
		assert(events[n].path);
		strcpy(events[n].path, line);

		args[strlen(args) - 1] = '\0';
		events[n].args = malloc(strlen(args) + 1);
		assert(events[n].args);
		strcpy(events[n].args, args);

		cfd = open(events[n].path, O_RDONLY);
		if (cfd < 0) {
			fprintf(stderr, "Cannot open %s: %s\n", events[n].path,
					strerror(errno));
			return 1;
		}

		pollfds[n].events = POLLIN;
		pollfds[n].fd = eventfd(0, 0);

		dirname(line);
		strcat(line, "/cgroup.event_control");

		event_control = open(line, O_WRONLY);
		if (event_control < 0) {
			fprintf(stderr, "Cannot open %s: %s\n", line,
					strerror(errno));
			return 1;
		}

		snprintf(line, PATH_MAX, "%d %d %s\n", pollfds[n].fd, cfd,
				events[n].args);

		if (write(event_control, line, strlen(line)) < 0) {
			fprintf(stderr, "Cannot write to cgroup.event_control: %s\n",
					strerror(errno));
			return 1;
		}

		close(event_control);
		close(cfd);

		n++;
	}

	while((ret = poll(pollfds, n, -1)) != 0) {
		int i;

		if (ret < 0) {
			perror("poll()");
			return 1;
		}

		for(i=0; (i < n) && ret; i++) {
			if (pollfds[i].revents & POLLIN) {
				printf("%s %s\n", events[i].path,
						events[i].args);
				if (read(pollfds[i].fd, line, 8) < 0) {
					perror("read()");
					return 1;
				}
				ret--;
			}

			if (pollfds[i].revents & ~(POLLIN)) {
				printf("%s(%s): unexpected event: %08x\n",
						events[i].path,
						events[i].args,
						pollfds[i].revents);
				return 1;
			}
		}
	}

	return 0;
}
