#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/signal.h>
#include <strings.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>

/* 
 * Disclaimer:
 * Warning! This code could damage your eyes!
 * It could make them tear untill you get to the end.
 * Hint: Use lots of coffee!
 */

/*
 * Variable to store the maximum number of random numbers 
 * to be generated.
 */
int MAX_INPUT=100;

/*
 * These are for the input and 
 * output files
 */
FILE *file_des_in;
FILE *file_des_out;

/*
 * Filenames used
 */
char *tempfile="tempfile.dat";
char *input_file="input.dat";
char *output_file="output.dat";

//Not quite sure what this one is 
volatile int gen=0;

/*
 * Function definitions
 */
char* file_read();		//to read from the common file
int file_store(char *);		//to output to the common file
int generate();			//generates random numbers
char *notify_number(char *);	//notifies for the number that produces or consumes
int consume_number(char *);	//self-explanatory
int generate_sleep();		//generates random sleep time (different)
void parent_sigset_catcher(int);//self-explanatory
void child_sigset_catcher(int);	//self-explanatory
void generate_store_numbers();	//generates the input file for the parent
char *get_number(FILE *);	//grabs a number from input file 
void leave();			//as a parameter to atexit()


int consume_number(char *the_num)
{
	char temp[50];
	
	/*
	 * This one just displays
	 */
	sprintf(temp, "child %d consumes number %s\n", getpid(), the_num);
	write(1, temp, strlen(temp));
	fflush(stdout);
	return(0);
}					
	
char *notify_number(char *the_num)
{
	char temp[50];

	/*
	 * This one displays but also 
	 * returns the value for the "chain reaction"
	 */
	sprintf(temp, "parent %d generates number %s", getpid(), the_num);
	write(1, temp, strlen(temp));
	return(the_num);
}

int generate()
{
	return((rand()%33)+1);
}

int file_store(char *num)
{
	char temp_var[10];
	int filedes;

	/*
	 * Creates it and puts it in
	 * and closes it
	 */
	filedes=creat(tempfile, 0644);
	filedes=open(tempfile, O_WRONLY, 0644);
	sprintf(temp_var, "%s", num);
	write(filedes, temp_var, sizeof(temp_var));
	close(filedes);
	
	return(filedes);
}

char* file_read()
{
	char temp_char[10];
	int filedes;
	/*
	 * reads value and erases the file
	 */
	filedes=open(tempfile, O_RDONLY);
	read(filedes, temp_char, sizeof(temp_char));
	close(filedes);
	unlink(tempfile);
	
	/* 
	 * This statement does the 
	 * main consuming but since they are
	 * chained then it doesn't matter too much 
	 * where i put it 
	 */
	fprintf(file_des_out,"%s", temp_char);
	return(temp_char);
}	

int generate_sleep()
{
	//Relatively smaller time
	//We don't want to wait too much
	return((rand()%5)+1);
}

void generate_store_numbers()
{
	        char temp_var[10];
		int i, num;
		FILE *filedes;
		
		/*
		 * Creates the input file
		 * generates the random values one 
		 * by one and stores them
		 */
		creat(input_file, 0644);
		filedes=fopen(input_file,"w");
		srand((unsigned) getpid());
		for (i=0; i<MAX_INPUT; ++i)
		{
			num=(unsigned) generate();
			sprintf(temp_var, "%d\n", num);
			fprintf(filedes,"%s", temp_var);
		}
		
		fclose(filedes);
		
}						
	
char *get_number(FILE *file_in)
{
	char temp_char[10];
	
	/*
	 * Grab a line from a file
	 */	
	fgets(temp_char, 10, file_in);
	return(temp_char);
	
}	

void leave()
{
	/*
	 * atexit executes this
	 */
	fclose(file_des_in);
	fclose(file_des_out);
}

int main()
{
	char *test_var;
	
	int pid, c, p;		//c,p - counters
	int c_pid, p_pid;	//parent and child pid storage
	int ident_p=0, ident_c=0;//bool identifiers
	
	/*
	 * Clean-up old files
	 */
	unlink(input_file);	
	unlink(output_file);
	
	/*
	 * Make new output file 
	 * and generate and store the input numbers
	 * in the input file
	 */
	creat(output_file, 0644);
	generate_store_numbers();

	/*
	 * open both files
	 * child will inherit this
	 */
	file_des_in=fopen(input_file, "r");
	file_des_out=fopen(output_file, "w");
	
	/*
	 * The following 2 "if" statements
	 * set the default behaviour if they receive a signal
	 * set the pid values for c_pid and p_pid
	 * and set the identity values for the boolean
	 * variables
	 */
	if ((pid=(unsigned) fork())!=0)
	{
		srand((unsigned) getpid());
		sigset(SIGUSR1, parent_sigset_catcher);	
		c_pid=pid;
		ident_p=1;
	}
	else
	{
		srand((unsigned) getpid());
		sigset(SIGUSR2, child_sigset_catcher);
		p_pid=getppid();
		ident_c=1;
	}

	/*
	 * PARENT PROCESS CODE
	 */
	if (ident_p == 1)
	{
		atexit(leave);	//make sure files clased after exit
	
		unlink(tempfile); //clean from previous run should put in atexit()

		//generate the first number->display it->put it in common file
		file_store(notify_number(get_number(file_des_in)));
		
		/*
		 * and do it till the maximum requested by the 
		 * user is reached
		 */
		
		for(p=0; p<MAX_INPUT-1;++p)
		{
			sleep(generate_sleep());
			kill(c_pid, SIGUSR2);
			sigpause(SIGUSR1);
		}
		/*
		 * done. send a completion signal
		 * and exit
		 */
		kill(c_pid, SIGHUP);
		sleep(1);
		exit(0);
	}	

	/*
	 * CHILD CODE
	 */
	if (ident_c == 1)
	{
		atexit(leave);	//as above
		
		//Get immune for a completion signal
		sigset(SIGHUP, child_sigset_catcher);

		//wait till parent is done with gen the first number
		sigpause(SIGUSR2);
		//sleep(1);
		//sleep then signal parent.. like above
		for(c=0;c<MAX_INPUT;++c)
		{
			sleep(generate_sleep());
			kill(p_pid, SIGUSR1);
			sigpause(SIGUSR2);
		}
		exit(0);
	}
	
	return(0);
}


void parent_sigset_catcher(int the_sig)
{
	sleep(generate_sleep());
	//do all notification and storing as
	//specs require
	file_store(notify_number(get_number(file_des_in)));
}

void child_sigset_catcher(int the_sig)
{
	sleep(generate_sleep());
	if(the_sig==SIGHUP)
	{
		consume_number(file_read());
		exit(0);
	}
	consume_number(file_read());
	   
}

/*

   [adimitro@localhost adimitro]$ ./a.out
   parent 17250 generates number 22
   child 17251 consumes number 22

   parent 17250 generates number 26
   child 17251 consumes number 26

   parent 17250 generates number 17
   child 17251 consumes number 17

   parent 17250 generates number 11
   child 17251 consumes number 11

   parent 17250 generates number 27
   child 17251 consumes number 27

   parent 17250 generates number 19
   child 17251 consumes number 19

   parent 17250 generates number 12
   child 17251 consumes number 12

   parent 17250 generates number 21
   child 17251 consumes number 21

   parent 17250 generates number 4
   child 17251 consumes number 4

   parent 17250 generates number 6
   child 17251 consumes number 6

   parent 17250 generates number 13
   child 17251 consumes number 13

   parent 17250 generates number 8
   child 17251 consumes number 8

   parent 17250 generates number 33
   child 17251 consumes number 33

   parent 17250 generates number 4
   child 17251 consumes number 4

   parent 17250 generates number 1
   child 17251 consumes number 1

   parent 17250 generates number 31
   child 17251 consumes number 31

   parent 17250 generates number 32
   child 17251 consumes number 32

   parent 17250 generates number 9
   child 17251 consumes number 9

   parent 17250 generates number 17
   child 17251 consumes number 17

   parent 17250 generates number 7
   child 17251 consumes number 7

   parent 17250 generates number 14
   child 17251 consumes number 14

   parent 17250 generates number 27
   child 17251 consumes number 27

   parent 17250 generates number 22
   child 17251 consumes number 22

parent 17250 generates number 14
child 17251 consumes number 14

parent 17250 generates number 21
child 17251 consumes number 21

parent 17250 generates number 6
child 17251 consumes number 6

parent 17250 generates number 6
child 17251 consumes number 6

parent 17250 generates number 20
child 17251 consumes number 20

parent 17250 generates number 16
child 17251 consumes number 16

parent 17250 generates number 2
child 17251 consumes number 2

parent 17250 generates number 4
child 17251 consumes number 4

parent 17250 generates number 3
child 17251 consumes number 3

parent 17250 generates number 27
child 17251 consumes number 27

parent 17250 generates number 20
child 17251 consumes number 20

parent 17250 generates number 13
child 17251 consumes number 13

parent 17250 generates number 19
child 17251 consumes number 19

parent 17250 generates number 5
child 17251 consumes number 5

parent 17250 generates number 22
child 17251 consumes number 22

parent 17250 generates number 6
child 17251 consumes number 6

parent 17250 generates number 6
child 17251 consumes number 6

parent 17250 generates number 27
child 17251 consumes number 27

parent 17250 generates number 18
child 17251 consumes number 18

parent 17250 generates number 11
child 17251 consumes number 11

parent 17250 generates number 27
child 17251 consumes number 27

parent 17250 generates number 19
child 17251 consumes number 19

parent 17250 generates number 10
child 17251 consumes number 10

parent 17250 generates number 22
child 17251 consumes number 22

parent 17250 generates number 17
child 17251 consumes number 17

parent 17250 generates number 18
child 17251 consumes number 18

parent 17250 generates number 5
child 17251 consumes number 5

parent 17250 generates number 23
child 17251 consumes number 23

parent 17250 generates number 31
child 17251 consumes number 31

parent 17250 generates number 32
child 17251 consumes number 32

parent 17250 generates number 12
child 17251 consumes number 12

parent 17250 generates number 9
child 17251 consumes number 9

parent 17250 generates number 19
child 17251 consumes number 19

parent 17250 generates number 15
child 17251 consumes number 15

parent 17250 generates number 14
child 17251 consumes number 14

parent 17250 generates number 5
child 17251 consumes number 5

parent 17250 generates number 30
child 17251 consumes number 30

parent 17250 generates number 13
child 17251 consumes number 13

parent 17250 generates number 6
child 17251 consumes number 6

parent 17250 generates number 30
child 17251 consumes number 30

parent 17250 generates number 6
child 17251 consumes number 6

parent 17250 generates number 25
child 17251 consumes number 25

parent 17250 generates number 7
child 17251 consumes number 7

parent 17250 generates number 24
child 17251 consumes number 24

parent 17250 generates number 27
child 17251 consumes number 27

parent 17250 generates number 29
child 17251 consumes number 29

parent 17250 generates number 29
child 17251 consumes number 29

parent 17250 generates number 31
child 17251 consumes number 31

parent 17250 generates number 22
child 17251 consumes number 22

parent 17250 generates number 11
child 17251 consumes number 11

parent 17250 generates number 8
child 17251 consumes number 8

parent 17250 generates number 13
child 17251 consumes number 13

parent 17250 generates number 30
child 17251 consumes number 30

parent 17250 generates number 17
child 17251 consumes number 17

parent 17250 generates number 2
child 17251 consumes number 2

parent 17250 generates number 13
child 17251 consumes number 13

parent 17250 generates number 1
child 17251 consumes number 1

parent 17250 generates number 4
child 17251 consumes number 4

parent 17250 generates number 1
child 17251 consumes number 1

parent 17250 generates number 29
child 17251 consumes number 29

parent 17250 generates number 2
child 17251 consumes number 2

parent 17250 generates number 10
child 17251 consumes number 10

parent 17250 generates number 4
child 17251 consumes number 4

parent 17250 generates number 18
child 17251 consumes number 18

parent 17250 generates number 24
child 17251 consumes number 24

parent 17250 generates number 15
child 17251 consumes number 15

parent 17250 generates number 21
child 17251 consumes number 21

parent 17250 generates number 18
child 17251 consumes number 18

parent 17250 generates number 27
child 17251 consumes number 27

parent 17250 generates number 26
child 17251 consumes number 26

parent 17250 generates number 15
child 17251 consumes number 15

parent 17250 generates number 33
child 17251 consumes number 33

parent 17250 generates number 16
child 17251 consumes number 16

parent 17250 generates number 21
child 17251 consumes number 21

parent 17250 generates number 21
child 17251 consumes number 21

parent 17250 generates number 7
child 17251 consumes number 7

parent 17250 generates number 16
[adimitro@localhost adimitro]$ child 17251 consumes number 16


[adimitro@localhost adimitro]$ diff input.dat output.dat
[adimitro@localhost adimitro]$ cat input.dat
22
26
17
11
27
19
12
21
4
6
13
8
33
4
1
31
32
9
17
7
14
27
22
14
21
6
6
20
16
2
4
3
27
20
13
19
5
22
6
6
27
18
11
27
19
10
22
17
18
5
23
31
32
12
9
19
15
14
5
30
13
6
30
6
25
7
24
27
29
29
31
22
11
8
13
30
17
2
13
1
4
1
29
2
10
4
18
24
15
21
18
27
26
15
33
16
21
21
7
16
[adimitro@localhost adimitro]$ cat output.dat
22
26
17
11
27
19
12
21
4
6
13
8
33
4
1
31
32
9
17
7
14
27
22
14
21
6
6
20
16
2
4
3
27
20
13
19
5
22
6
6
27
18
11
27
19
10
22
17
18
5
23
31
32
12
9
19
15
14
5
30
13
6
30
6
25
7
24
27
29
29
31
22
11
8
13
30
17
2
13
[adimitro@localhost adimitro]$

*/

