*************************************************************
CONTINUING.C
*************************************************************

/* Trevor Nickle  Assignment 3  November 26, 1996           */
/*                                                          */
/* Purpose        To learn how to manipulate strings,       */
/*                Pointers, and primarily signal control.   */
/*                In all, five signals are tested for and   */
/*                Caught.                                   */
/*                                                          */
/* Variables                                                */
/* n,b            These integer variables are used to       */
/*                Generate a hardware signal                */
/* t1 ... t4      Integer value stores flag from forks      */
/* w              Integer value stores flag from waitpid    */
/* i,j            Indices for for loops.                    */
/* stat           Integer pointer used in waitpid           */
/* pid            Process IDentity                          */
/* procid[6]      Integer Array that stores the digits      */
/*                That make up the pid                      */
/* strings[7]     Char array that stores the characters     */
/*                That make up the pid                      */
/* sss1           Char pointer that contains the unix       */
/*                command kill with options                 */
/* sss2           Char string that stores pid in string form*/
/* command        Char string that executes kill command    */
/* k              Stores flag from kill2                    */
/*                                                          */
#include 
#include 

void continuing() {

int w,t4,i,j,k;
int *stat;

t4 = fork();      /* Kill 2 component                       */
if (t4<0) {
   printf("ERROR: NO FORK T4\n");
   fflush(stdout);
   exit(0);
          }
if (t4==0) {  /* If Part 4 Start */
   printf("CHILD4: My purpose in life is to wait for a kill(2) signal.\n");
   fflush(stdout);
   for (j=0;j<60;j++) {  /* Keeps child alive long enough to kill it */
      for (i=0;i<1000000;i++);
                      }
           } /* If Part 4 End */
else {  /* Else Part 4 Start */
   sleep(8);
   printf("PARENT4: Child Process id is %d\n",t4);
   fflush(stdout);
   printf("PARENT4: Checking up on the child before killing it.\n");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
   system("ps -l | grep p673d | grep -v grep");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
   printf("PARENT4: About to use kill(2)\n");
   fflush(stdout);
   k = kill(t4,_SIGQUIT);

   if (k<0) {
     printf("ERROR: KILL2 INCORRECT\n");
     fflush(stdout);
     exit(0);
            }

   sleep(7);
   system("ps -l | grep p673d | grep -v grep");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
   printf("PARENT4: Kill(2) done\n");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
   printf("******************************************** \n");
   fflush(stdout);  /* Keyboard Interrupt Component */
   printf(" \n");
   fflush(stdout);
   w = waitpid(t4,stat,1);
   while (w!=-1) {  /* This While confirms that the child has died */
      w = waitpid(t4,stat,1);
                 }

      printf("PARENT5: Waiting for user to interrupt...\n");
      fflush(stdout);
      sleep(20);       /* Gives User opportunity to interrupt program */
      printf("PARENT5: If Interrrupt hasn't occurred yet ... Too late\n");
      fflush(stdout);
      printf(" \n");
      fflush(stdout);
      printf("******************************************** \n");
      fflush(stdout);
    }  /* Else Part 4 End  */
}

**********************************************************************
MAIN
**********************************************************************

/* Header of Information is on top of Continuing.c                      */

#include       /* Necessary header files for program execution */
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void mistakeA();        /* These Subroutines are called when a given    */
void mistakeB();        /* Signal is generated.                         */
void mistakeC();        /* The last routine contains the last 2 signals */
void mistakeD();        /* That are dealt with.  Program is just too big*/
void mistakeE();        /* To debug effectively                         */
void continuing();   


main() {

int n,b,t1,t2,t3,t4,w,i,j;
int *stat;                /*All Variables are described in Continuing.c.*/
int pid;
int procid[6];
char strings[7];
char *sss1 = "kill -s SIGTERM ";
char *sss2;
char *command;


signal(SIGTERM,mistakeD);  /* These are the signals that will be caught.*/
signal(SIGABRT,mistakeC);
signal(SIGFPE,mistakeA);
signal(SIGINT,mistakeB);
signal(_SIGQUIT,mistakeE);

printf("******************************************** \n");
fflush(stdout);  /* Hardware Signal Component                           */
printf(" \n");
fflush(stdout);
t1 = fork();

if (t1==-1) {    /* Error Check                                         */
   printf("ERROR: NO FORK T1\n");
   fflush(stdout);
   exit(0);
            }

if (t1==0) {     /* Child #1 Execution                                  */
   printf("CHILD1: My purpose in life is to wait until a division by zero.\n");
   fflush(stdout);
   n=0;
   b=8;
   b=b/n;     
           }

else {           /* Parent #1 Execution                                 */
   w = waitpid(t1,stat,1);
   while (w!=-1) {  /* This While confirms that the child has died */
      w = waitpid(t1,stat,1);
                 }
   printf("PARENT1: We just passed a division by zero error\n");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
     }

printf("******************************************** \n");
fflush(stdout);  /* Software Signal Component                           */
printf(" \n");
fflush(stdout);
t2 = fork();

if (t2==-1) {    /* Error Checking                                      */
   printf("ERROR: NO FORK T2\n");
   fflush(stdout);
   exit(0);
            }

if (t2==0) {     /* Child #2 Executions                                 */
   printf("CHILD2: My purpose in life is to wait for a sortware abort.\n");
   fflush(stdout);
   abort();
           }

else {           /* Parent #2 Executions                                */
   w = waitpid(t2,stat,1);
   while (w!=-1) {  /* This While confirms that the child has died */
      w = waitpid(t2,stat,1);
                 }
   printf("PARENT2: We just passed an abort signal\n");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
     }

printf("******************************************** \n");
fflush(stdout); /* Kill 1 Component                                    */   
printf(" \n");
fflush(stdout);
t3 = fork();

if (t3==-1) {
   printf("ERROR: NO FORK T3\n");
   fflush(stdout);
   exit(0);
            }

if (t3==0) {
   printf("CHILD3: My purpose in life is to wait for a kill(1) signal.\n");
   fflush(stdout);
   for (i=40;i>0;i--) {          /* Keep Child alive long enough to kill it*/
      for (j=0;j<1000000;j++);
                      }
           }


else { /* prob */
   if (pid>99999) {
      printf("ERROR: PID TO LARGE ERROR\n");
      fflush(stdout);
      exit(0);
                  }
   sleep(4);                                  /* This section of code     */
   pid = t3;                                  /* retrieves one digit at a */
   procid[0] = (int)(pid/10000);              /* time from the pid and    */
   pid = pid - (int)((int)(pid/10000)*10000); /* converts it to a         */
   procid[1] = (int)(pid/1000);               /* character.               */
   pid = pid - (int)((int)(pid/1000)*1000);
   procid[2] = (int)(pid/100);
   pid = pid - (int)((int)(pid/100)*100);
   procid[3] = (int)(pid/10);
   pid = pid - (int)((int)(pid/10)*10);
   procid[4] = (pid/1);

   for (i=0;i<5;i++) {
      if (procid[i]==1) strings[i]='1';
      if (procid[i]==2) strings[i]='2';
      if (procid[i]==3) strings[i]='3';
      if (procid[i]==4) strings[i]='4';
      if (procid[i]==5) strings[i]='5';
      if (procid[i]==6) strings[i]='6';
      if (procid[i]==7) strings[i]='7';
      if (procid[i]==8) strings[i]='8';
      if (procid[i]==9) strings[i]='9';
      if (procid[i]==0) strings[i]='0';
                     }
     
   printf("PARENT3: Child Process id is %d\n",t3);
   fflush(stdout);
   printf("PARENT3: Individual Numbers are %d %d %d %d %d \n",procid[0],procid[1],procid[2],procid[3],procid[4]);
   fflush(stdout);
   printf("PARENT3: Characters are %c %c %c %c %c\n",strings[0],strings[1],strings[2],strings[3],strings[4]);
   fflush(stdout);
   strings[5]='\0';
   sss2 = strings;
   printf("PARENT3: String is %s\n",sss2); 
   fflush(stdout);
   command = strcat(sss1,sss2);
   printf("PARENT3: Command is %s\n",command);
   fflush(stdout);
   printf("PARENT3: Checking up on the child before killing it.\n");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
   system("ps -l | grep p673d | grep -v grep"); /* Checks child's existance*/
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
   printf("PARENT3: About to use kill(1)\n");
   fflush(stdout);
   system(command);                             /* Sends kill command      */
   sleep(7);
   system("ps -l | grep p673d | grep -v grep");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
   printf("PARENT3: Kill(1) done\n");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
   printf("******************************************** \n");
   fflush(stdout);
   printf(" \n");
   fflush(stdout);
   w = waitpid(t3,stat,1);
   while (w!=-1) {  /* This While confirms that the child has died */
      w = waitpid(t3,stat,1);
                 }
   continuing();   /* Other two signals are in here */
 }

}

********************************************************************
ALL SIGNAL HANDLING ROUTINES
********************************************************************

#include 

void mistakeA() {

printf("MISTAKE A: We just had a division by zero error\n");
fflush(stdout);
return; 
}


#include 

void mistakeB() {

printf("MISTAKE B: We just got stopped from the keyboard\n");
fflush(stdout);
return; 
}



#include 

void mistakeC() {

printf("MISTAKE C: We just received an abort signal\n");
fflush(stdout);
return; 
}



#include 

void mistakeD() {

sleep(1);
printf("MISTAKE D: We just received a kill signal\n");
fflush(stdout);
printf(" \n");
fflush(stdout);
return; 
}



#include 

void mistakeE() {

printf("MISTAKE E: We just had a quit signal\n");
fflush(stdout);
printf(" \n");
fflush(stdout);
return; 
}


****************************************************************
MAKEFILE
****************************************************************

# 
SHELL   = /bin/sh
CC      = cc
LDFLAGS = -g -lm
FLAGS   = -Aa
MAIN    = /users/tnickle

p673d : p673d.o $(MAIN)/mistakeA.o $(MAIN)/mistakeB.o \
                $(MAIN)/mistakeC.o $(MAIN)/mistakeD.o \
                $(MAIN)/mistakeE.o $(MAIN)/continuing.o
	$(CC) -o $@ p673d.o $(MAIN)/mistakeA.o \
                            $(MAIN)/mistakeB.o \
                            $(MAIN)/mistakeC.o \
                            $(MAIN)/mistakeD.o \
                            $(MAIN)/mistakeE.o \
			    $(MAIN)/continuing.o $(LDFLAGS)

p673d.o : p673d.c
	$(CC) $(FLAGS) -o p673d.o -c p673d.c 

$(MAIN)/mistakeA.o : $(MAIN)/mistakeA.c 
	$(CC) $(FLAGS) -o $(MAIN)/mistakeA.o -c $(MAIN)/mistakeA.c 

$(MAIN)/mistakeB.o : $(MAIN)/mistakeB.c
	$(CC) $(FLAGS) -o $(MAIN)/mistakeB.o -c $(MAIN)/mistakeB.c

$(MAIN)/mistakeC.o : $(MAIN)/mistakeC.c
	$(CC) $(FLAGS) -o $(MAIN)/mistakeC.o -c $(MAIN)/mistakeC.c

$(MAIN)/mistakeD.o : $(MAIN)/mistakeD.c
	$(CC) $(FLAGS) -o $(MAIN)/mistakeD.o -c $(MAIN)/mistakeD.c

$(MAIN)/mistakeE.o : $(MAIN)/mistakeE.c
	$(CC) $(FLAGS) -o $(MAIN)/mistakeE.o -c $(MAIN)/mistakeE.c

$(MAIN)/continuing.o : $(MAIN)/continuing.c
	$(CC) $(FLAGS) -o $(MAIN)/continuing.o -c $(MAIN)/continuing.c



*********************************************************************
OUTPUT
*********************************************************************

******************************************** 
 
CHILD1: My purpose in life is to wait until a division by zero.
MISTAKE A: We just had a division by zero error
PARENT1: We just passed a division by zero error
 
******************************************** 
 
CHILD2: My purpose in life is to wait for a sortware abort.
MISTAKE C: We just received an abort signal
PARENT2: We just passed an abort signal
 
******************************************** 
 
CHILD3: My purpose in life is to wait for a kill(1) signal.
PARENT3: Child Process id is 3795
PARENT3: Individual Numbers are 0 3 7 9 5 
PARENT3: Characters are 0 3 7 9 5
PARENT3: String is 03795
PARENT3: Command is kill -s SIGTERM 03795
PARENT3: Checking up on the child before killing it.
 
  1 R  9508  3795  3792 93 209 24  4356740    9          ttyq2    0:04 p673d
  1 S  9508  3792 20603  6 158 24  4338a00    9   3fa0c8 ttyq2    0:02 p673d
 
PARENT3: About to use kill(1)
MISTAKE D: We just received a kill signal
 
  1 Z  9508  3795  3792 -117 220 24  4356740    0          ttyq2    0:06 p673d
  1 S  9508  3792 20603  6 158 24  4338a00    9   3fa0c8 ttyq2    0:02 p673d
 
PARENT3: Kill(1) done
 
******************************************** 
 
CHILD4: My purpose in life is to wait for a kill(2) signal.
PARENT4: Child Process id is 3805
PARENT4: Checking up on the child before killing it.
 
  1 R  9508  3805  3792 -95 226 24  4356740    9          ttyq2    0:08 p673d
  1 S  9508  3792 20603  6 158 24  4338a00    9   3fa0c8 ttyq2    0:02 p673d
 
PARENT4: About to use kill(2)
MISTAKE E: We just had a quit signal
 
  1 Z  9508  3805  3792 95 209 24  4356740    0          ttyq2    0:10 p673d
  1 S  9508  3792 20603  6 158 24  4338a00    9   3fa0c8 ttyq2    0:02 p673d
 
PARENT4: Kill(2) done
 
******************************************** 
 
PARENT5: Waiting for user to interrupt...
MISTAKE B: We just got stopped from the keyboard
PARENT5: If Interrrupt hasn't occurred yet ... Too late
 
******************************************** 

***************************************************************
THIS IS ASSIGNMENT #3
***************************************************************