#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>

#define ADMIN_EMAIL "your@address"
#define LOGFILE "/var/log/kern.log"

int main(void)
{
	int fd;
	int ret;
	int pid;
	int fds[2];
	struct stat st;
	unsigned long size = 0;
	char *data;
	char *p, *p2, *p3;
	char tmp;

	fd = open(LOGFILE, O_RDONLY);
	if (fd < 0) {
		printf("Unable to open %s.\n", LOGFILE);
		exit(1);
	}

	ret = fstat(fd, &st);
	if (ret < 0)
		exit(1);

	size = st.st_size;

	while (!sleep(1)) {
		ret = fstat(fd, &st);
		if (ret < 0)
			exit(1);

		if (st.st_size > size) {
read:
			lseek(fd, size, SEEK_SET);
			data = calloc(st.st_size - size + 1, sizeof(char));
			if (data == NULL) {
				printf("Out of memory.\n");
				exit(1);
			}
			read(fd, data, st.st_size - size);
			p = data;
			while ((p2 = strstr(p, "grsec: "))) {
				p2 += 7;
				p3 = strchr(p2, '\n');
				if (p3 == NULL)
					break;
				tmp = *(p3 + 1);
				*(p3 + 1) = '\0';

				if (pipe(fds))
					goto skip;

				write(fds[1], p2, strlen(p2));
				write(fds[1], "\n", 1);
				close(fds[1]);

				pid = fork();
				if (pid == 0) {
					if (dup2(fds[0], 0))
						exit(1);
					execl("/usr/bin/mail", "/usr/bin/mail", "-s", "grsecurity alert", ADMIN_EMAIL, NULL);
				} else if (pid > 0) {
					wait(NULL);
					close(fds[0]);
				}

skip:
				*(p3 + 1) = tmp;
				p = p3 + 1;
			}
		} else if (st.st_size < size) {
			size = 0;
			goto read;
		}

		size = st.st_size;
	}

	close(fd);
	return 0;
}
