#!/bin/sh

modulename=taskmonitor
if modprobe $modulename target="-1" 2> /dev/null; then
	echo "Should throw an error with an invalid pid"
	exit 1
fi

pid=$$

if ! modprobe $modulename target="$pid"; then
	echo "Could not load module $modulename.ko!"
	exit 1
fi

major=$(grep $modulename /proc/devices | cut -d ' ' -f1)
if [ -z "$major" ]; then
	echo "no major number found!"
	exit 1
fi

device=/dev/supertakmonitor

if ! mknod "$device" c "$major" 0; then
	echo "could not create device!"
	exit 1
fi

printf '%s' '
#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include "taskmonitor.h"

int main(int argc, char **argv)
{
	int fd;
	pid_t pid = -1, pid2;

	if (argc < 3)
		return -1;

	pid2 = atoi(argv[2]);

	if ((fd = open(argv[1], O_RDWR)) < 0) {
		perror("open");
		return -1;
	}

	/* get the monitored PID */
	if (ioctl(fd, TM_PID, &pid) < 0) {
		perror("ioctl pid");
		return -1;
	}

	if (pid != pid2) {
		fprintf(stderr, "TM_PID returned wrong pid\n");
		return 1;
	}

	/* stop the kthread, sleep 3s, and start it again*/
	if (ioctl(fd, TM_STOP) < 0) {
		perror("ioctl stop");
		return -1;
	}

	sleep(3);

	if (ioctl(fd, TM_START) < 0) {
		perror("ioctl start");
		return -1;
	}

	pid = getpid();
	if (ioctl(fd, TM_PID, &pid)) {
		perror("ioctl pid");
		return -1;
	}

	/* get the monitored PID */
	pid = -1;
	if (ioctl(fd, TM_PID, &pid) < 0) {
		perror("ioctl pid");
		return -1;
	}

	if (pid != getpid()) {
		fprintf(stderr, "TM_PID returned wrong pid\n");
		return 1;
	}



	return 0;
}' > userioctl.c

find /linux* -type f -name "taskmonitor.h" -print0 | xargs -0 -I {} cp {} .

if ! [ -f taskmonitor.h ]; then
	echo "taskmonitor.h file not found!"
	echo "please include this file to your submission"
	exit 1
fi

if ! gcc userioctl.c ; then
	echo "can't compile user program to test ioctl!"
	echo "fix your header file!"
	exit 1
fi

if ! out=$(./a.out "$device" "$pid"); then
	echo "error while running usespace program"
	echo "$out"
	exit 1
fi

echo "$out"

if ! rmmod $modulename; then
	echo "Fail while unloading module"
	exit 1
fi

if pgrep monitor; then
	echo "Monitor thread still running!"
	exit 1
fi
