#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define SIZE 4096
#define TIMEOUT 30
#define GRACE 2

extern int errno;

int main(int argc, char* argv[]) {
	pid_t child;
	int inpipe[2];
	fd_set set;
	time_t start;
	struct timeval timeout;
	int sel;
	char buf[SIZE];
	int count;

	if(pipe(inpipe) < 0) {
		fprintf(stderr, "Open pipe failed: %s\n", strerror(errno));
		return 128;
	}

	child = fork();
	switch (child) {
		case -1: // error
			fprintf(stderr, "Fork failed: %s\n", strerror(errno));
			return 129;
		case 0: // child
			if(close(inpipe[1]) < 0) {
				fprintf(stderr, "Close read end of pipe failed: %s\n", strerror(errno));
				return 130;
			}
			if(dup2(inpipe[0], 0) < 0) {
				fprintf(stderr, "Attaching write end of pipe to stdin failed: %s\n", strerror(errno));
				return 131;
			}
			if(execvp(argv[1], &(argv[1])) < 0) {
				fprintf(stderr, "Can't run child: %s\n", strerror(errno));
			}
			break;
		default: // parent
			if(close(inpipe[0]) < 0) {
				fprintf(stderr, "Close write end of pipe failed: %s\n", strerror(errno));
				return 132;
			}
			start = time(NULL);
			while((time(NULL) <= start + TIMEOUT) && (waitpid(child, NULL, WNOHANG) != child)) {
				FD_ZERO(&set);
				FD_SET(0, &set);
				timeout.tv_sec = 1;
				timeout.tv_usec = 0;
				sel = select(FD_SETSIZE, &set, NULL, NULL, &timeout);
				switch(sel) {
					case 0: //timeout
						break;
					case 1: // input
						if((count = read(0, buf, SIZE)) < 0) {
							fprintf(stderr, "Read failed: %s \n", strerror(errno));
							return 133;
						}
						if((count = write(inpipe[1], buf, count)) < 0) {
							fprintf(stderr, "Write failed: %s \n", strerror(errno));
							return 134;
						}
						break;
					case -1: //error
					default: //whatever
						fprintf(stderr, "Select returned %d due to: %s\n", sel, strerror(errno));
						return 135;
				}
			}
			close(inpipe[1]);
			sleep(GRACE);
			kill(child, SIGKILL);
	}

	return 0;
}
