/* This is a simple program that forks off a child 
   process and lets the child run for a while. The child 
   then exits after displaying that it is actually running
   and then the parent shows that the child is a zombie 
   before a call to waitpid. After the child has terminated 
   and the call to waitpid, the parent then exits normally.
                               -Kalen          */

#include
#include
#include
#include
#include

main()
{

 pid_t ierr;           /* Variable for return value of fork()             */
 int dummy;          /* Variable to contain return value of waitpid()   */
 int parent_pid;     /* PID of parent process                           */
 int child_pid;      /* PID of child process                            */
 int child_ppid;     /* PID of child's parent                           */

 int *stat;          /* Status of wait function                         */

 printf("\nStart of Programme!\n\n");

/* Find PID of this process and print it to screen along
   with a ps listing to show that it is running           */
 parent_pid = getpid();
 printf("Before fork: Parent PID: %d\n", parent_pid);
 system("ps -efl | grep ass7 | grep -v grep");
 sleep(3);
 printf("\n");

/* Execute the fork and complain on error  */
 if ( (ierr = fork()) < 0 ) {
    printf("Error on calling of fork()\n");
    exit(1); }                                 /* Exit on error and return 1 */
 else {
    printf("Fork succeeded.\n");               /* This will get written twice */
    sleep(3);  }
    
 /* Both processes now examine ierr (parent gets child's PID
    returned and child gets 0 returned from fork function)
    and decide if they are
    the parent or child and will print messages stating 
    what they are and their PIDs. The child will also find
    what is the PID of its parent and print it. 
                                        */
 printf("\n");
 if (ierr != 0) {                      /* I am the parent  */
    child_pid=ierr;
    printf("After fork: Parent: My PID: %d\n", parent_pid);
    printf("After fork: Parent: My Childs PID: %d\n", child_pid);
    /* Wait for the child to terminate */
    do {
        sleep(2);
        printf("\nParent: Is child still there? ChildPID:%d\n", child_pid);
            /* These system calls are a hack that shows my lack of C 
               experience with strings. With a couple of extra lines
               to read, and a breif look in the list, it does clearly
               show the child in a zombie condition before the parent's
               call to waitpid. This satistifies the requirement of 
               the assignment.               */
        system("ps -efl -u 9509 | grep ass7 | grep -v grep"); 
        system("ps -efl -u 9509 | grep defunct | grep -v grep"); 
       } while ((dummy = waitpid(child_pid,stat,WNOHANG)) == 0); 
    printf("\n\nParent is still alive: PID: %d\n", parent_pid); 
    system("ps -efl | grep ass7 | grep -v grep"); /* ps is system dependant */
    printf("Parent is now exiting.\n"); }
 else if ( ierr == 0 ) {                /* I am the child  */
    child_pid = getpid();
    child_ppid = getppid();                    /* Get parent's PID   */
    printf("After fork: Child: My PID: %d\n", child_pid);
    printf("After fork: Child: My PPID: %d\n", child_ppid); 
    system("ps -efl | grep ass7 | grep -v grep"); /* ps is system dependant */
    sleep(9);
    printf("Child process now exiting\n"); }
 else printf("Error after fork succeeded.");   /* Something seriosly wrong */

 exit(0);                                      /* Terminate normally   */
}