/* timer.c
 *
 * i'm sure there are a billion unix programs to this
 * i just couldn't think of the name of any.
 * 
 * input a integer time n in seconds and a program to run, and the 
 * program will be killed after n seconds
 *
 */

#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>

/* an ominous sounding SIGALRM handler */
void kill_child();

/* child */
pid_t   cpid;

/* command line */
char  **command;

int main(int argc, char *argv[])
{
	char * ptr;
	int i=0, p[2];

	if ( argc != 3 ) {
		fprintf(stderr, "Usage: timer timeout \"command\"\n");
		exit(0);
	}

	/* setup command for exec */
	command    = (char**)malloc(sizeof(char**));
	ptr        = strtok( argv[2] , " ");
	command[0] = (char *)malloc(strlen(ptr));
	strcpy( command[0] , ptr) ;

	/* take options */
	for ( i = 1 ; (ptr = strtok( NULL , " ")) != (char *)NULL; i++ ) {
		command[i] = (char *)malloc(strlen(ptr));
		strcpy( command[i] , ptr) ;
	}

	/* null terminate */
	command[i] = (char *)malloc(sizeof(char*));
	command[i] = '\0';

	signal(SIGALRM, kill_child); 	/* setup signal handler */

	switch ( cpid=fork() ) {

		case -1 :
			perror("fork failed!");
			break;

		/* child */
		case 0  :

			execvp( command[0] , command );      /* exec program */
			perror("timer");

		default :

			alarm(atoi(argv[1]));		/* set alarm */

			/* wait on child but don't block */
			while ( !waitpid( cpid , NULL , WNOHANG ) );
	}

}

/* death becomes you */
void kill_child() {
	kill ( cpid , SIGKILL );
}
