/*
 * Mysterious code for assignment  4-10
 */
#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>

#define MAX_SIG 45

void signal_catcher(int);	//The signal catcher function
int generate();			//generates random signals
void leave();			//atexit code
int notify_signal(int);		//print out the signal
int check(int);			//check for SIGSTOP
void notify_dead();		//print out message if other proc dies

/*
 * Implementations are pretty self-explanatory
 */
void signal_catcher(int the_sig)
{
	signal(the_sig, signal_catcher);
}

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

void leave()
{
	printf("\nprocess %d terminating...\n", getpid());
}

int notify_signal(int the_sig)
{
	char temp[50];
	sprintf(temp, "%d sends signal %d\n", getpid(), the_sig);
	write(1, temp, strlen(temp));
	return(the_sig);
}

int check(int the_sig)
{

	if (the_sig==SIGSTOP) //Since we can't catch this
		the_sig=0;
	return(the_sig);
}

void notify_dead()
{
        char temp[50];
	sprintf(temp, "process %d returned that friend is dead therefore exiting...\n", getpid());
	write(1, temp, strlen(temp));
	exit(0);
}

int main()
{

	int p_pid, c_pid, pid;
	int p_sig, c_sig;
	int i, status;
	int identifyp=0, identifyc=0;	
	
	/*
	 * So here begins the fun part. good luck!
	 */
	
	/* 
	 * First I let the parent run 
	 * it will set its identifier for later use
	 * set its atexit function
	 * it sets the seed
	 * blocks all signals
	 * and goes to sleep
	 */
	if((pid=(unsigned) fork()) != 0)
	{
		identifyp=1;
		atexit(leave);
		
		srand((unsigned) getpid());
		
		for (i=1; i<=MAX_SIG; i++)
			signal(i, signal_catcher);
		
		sleep(1);
	}	
	
	/*
	 * This is the child's first run
	 * sets its identifier
	 * sets the exit function
	 * blocks all signals
	 * and goes to sleep
	 */
	else
	{
		identifyc=1;
		atexit(leave);
		
		srand((unsigned) getpid());
		
		for (i=1; i<=MAX_SIG; i++)
			signal(i, signal_catcher);	
		
		sleep(1);
	}

	
	/*
	 * Here are the infinate loops for both child and parent
	 */

	/*
	 * check if parent then go into the loop
	 */
	if(identifyp == 1)
	{
		for( ; ; )
		{ 
			sleep(1);
			/*
			 * This next on is just generating and displaying the 
			 * new signal 
			 */
			p_sig=check(notify_signal(generate()));
			
			/*
			 * send the signal and check if signal was 9 ... 
			 * if yes then parent will HAVE to wait 
			 * because child will become a zombie
			 * and kill(child_pid, 0);
			 * will return 0 always so we'll have to somehow 
			 * figure this out
			 */
			kill(pid, p_sig);  
	       		if(p_sig==9)
			{
				notify_dead();
				wait(&status);			
			}

        	}
	}
	

	/*
	 * If this is the child then go into the loop
	 */
	if(identifyc == 1)
	{
		for( ; ; )
		{
			sleep(1);
			/*
			 * here the kill can be used 
			 */
			if (kill(getppid(), 0) != 0)
				notify_dead();
			c_sig=check(notify_signal(generate()));
			/*
			 * Send the signal
			 */
			kill(getppid(), c_sig);
		}
		
	}		

}
/*
 ###### RUN 1 ######
9007 sends signal 13
9008 sends signal 21
9007 sends signal 15
9008 sends signal 14
9007 sends signal 11
9008 sends signal 5
9007 sends signal 9
process 9007 returned that friend is dead therefore exiting...

process 9007 terminating...

###### RUN 2 ######
9026 sends signal 16
9025 sends signal 7
9026 sends signal 13
9025 sends signal 14
9026 sends signal 24
9025 sends signal 30
9026 sends signal 29
9025 sends signal 10
9026 sends signal 5
9025 sends signal 6
9026 sends signal 14
9025 sends signal 28
9026 sends signal 4
9025 sends signal 1
9026 sends signal 19
9025 sends signal 32
9026 sends signal 18
9025 sends signal 20
9026 sends signal 9
process 9026 returned that friend is dead therefore exiting...

process 9026 terminating...


###### RUN 3 ######
9034 sends signal 20
9035 sends signal 29
9034 sends signal 31
9035 sends signal 29
9034 sends signal 7
9035 sends signal 1
9034 sends signal 11
9035 sends signal 28
9034 sends signal 31
9035 sends signal 31
9034 sends signal 1
9035 sends signal 19
9034 sends signal 24
9035 sends signal 27
9034 sends signal 10
9035 sends signal 30
9034 sends signal 3
9035 sends signal 2
9034 sends signal 3
9035 sends signal 2
9034 sends signal 8
9035 sends signal 33
9034 sends signal 1
9035 sends signal 5
9034 sends signal 30
9035 sends signal 22
9034 sends signal 11
9035 sends signal 3
9034 sends signal 21
9035 sends signal 5
9034 sends signal 22
9035 sends signal 7
9034 sends signal 2
9035 sends signal 17
9034 sends signal 1
9035 sends signal 33
9034 sends signal 25
9035 sends signal 18
9034 sends signal 12
9035 sends signal 31
9034 sends signal 27
9035 sends signal 30
9034 sends signal 22
9035 sends signal 10
9034 sends signal 26
9035 sends signal 30
9034 sends signal 10
9035 sends signal 18
9034 sends signal 24
9035 sends signal 19
9034 sends signal 15
9035 sends signal 17
9034 sends signal 11
9035 sends signal 4
9034 sends signal 21
9035 sends signal 17
9034 sends signal 33
9035 sends signal 27
9034 sends signal 13
9035 sends signal 25
9034 sends signal 10
9035 sends signal 23
9035 sends signal 28
9034 sends signal 4
9035 sends signal 27
9034 sends signal 9
process 9034 returned that friend is dead therefore exiting...

process 9034 terminating...

*/
