#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <time.h>
//--------------------------------------------------------------------------------------------
#include "Process_r.h"

Process_r task;  //задача
char* coup_de_grace=NULL; //команда добивания.

void hdl_abort_by_user(int sig)
{
   if ((coup_de_grace!=NULL)&&strlen(coup_de_grace)!=0)
        system(coup_de_grace);
   FILE * killed = fopen("INTERRUPT","w");
   fprintf(killed,"task was interrupted\n");
   fclose(killed);
   killpg(0, SIGKILL);
   exit(0);
}

void set_handlers(){

	struct sigaction act;

	memset(&act, 0, sizeof(act)); //обнуление полей структуры
	act.sa_handler = hdl_abort_by_user; //установка обработчика в поле стурктуры

	sigset_t   set;  //маска сигналов, которые буудт блокироваться во время выполнения обработчика
	sigemptyset(&set);         //предваритальеное обнуление всех сигналов
	sigaddset(&set, SIGINT);
	act.sa_mask = set;

	sigaction(SIGINT, &act, 0); //установка обработчика

}

int main(int argc, char ** argv){
	int i;
	time_t time1;
	time_t time2;
	char ** args = new char* [argc];
	int maxtime = atoi(argv[0]);
	coup_de_grace =argv[1];

	for ( i=2; i<argc; ++i)
		args [i-2] = argv[i];
	args[argc-2] = NULL;
	args[argc-1] = NULL;
    //------------
	int pid = getpid();
	task.Start();
	//потомок	- задача
	if (task.pid ==0 )
		execvp (argv[2],args);
	time1 = time((time_t *)0);
	int s;
	double total_time = 0.;
	int timer_pid = fork();
	if (timer_pid ==0){
		sleep(maxtime);
		FILE * killed = fopen("TIMEOUT","w");
        fprintf(killed,"task was killed by timer\n");
        fclose(killed);
		kill(pid,SIGINT);
        exit(0);
	}
	set_handlers();
	waitpid(task.pid,&s,WUNTRACED);
	kill(timer_pid,SIGKILL);

	time2 = time((time_t *)0);
	total_time = difftime(time2, time1);

	FILE * tt = fopen("total_time","w");
	fprintf(tt,"%.5lf",total_time);
	fclose(tt);

	FILE * done  = fopen("DONE","w");
	fprintf(done,"task finished correctly");
	fclose(done);

//Добивание. не факт что и сам тест будет корректно написан. от греха.
    if ((coup_de_grace!=NULL)&&strlen(coup_de_grace)!=0)
        system(coup_de_grace);
    killpg(0, SIGKILL);
	return 0;
}


