/* fork.c - A program to fork a child and wait for its demise */
/* Programmed for Physics 673 - Dr. D.M. Gingrich */
/* Author: R.A. Davis  November 12, 1996 */

#include 
#include 
#include 
#include 

main()
{
    register int ParentId,ChildId,MyId,ChildStatus;
    printf("Starting program.\n");

    /* First the main program displays its PID and the PID of the shell */

    MyId = getpid();
    ParentId = getppid();
    printf("PARENT: My process ID is %i\n",MyId);
    printf("PARENT: My parent (the grandparent) is %i\n",ParentId);
    printf("PARENT: Let's see if we're right!\n");

    /* Flush the buffers and run a ps to see what's up */

    fflush(0);
    system("ps -lu $USER");

    /* Fork the child */

    ChildId = fork();

    /* This block is executed if there is a problem with the fork */

    if (ChildId < 0) {
        printf("PARENT: Error in forking child - terminating.");
        exit(1); 
      }

    /* The child executes this block - displays its id and parent id */

    if (ChildId == 0) {
        printf("CHILD: I'm alive - I'M ALIVE!\n");
        MyId = getpid();
        ParentId = getppid();
        printf("CHILD: I think my name is %i\n",MyId);
        printf("CHILD: My parent is %i\n",ParentId);
        printf("CHILD: Now I go to sleep before I die.\n");
        fflush(0);
        sleep(5);       /* Child sleeps to run for a while */
        printf("CHILD: My life is half over!\n");
        fflush(0);
        sleep(5);
        printf("CHILD: Now I die. Look for my Zombie!\n");
        exit(0);
      }

    /* Parent executes this block - ps to see child running */

    if (ChildId > 0) {
        printf("PARENT: I have given birth to a process ID %i\n",ChildId);
        fflush(0);
        system("ps -lu $USER");
        printf("PARENT: Now we wait for baby to die.\n");
        ChildStatus = waitpid(ChildId,0,WNOHANG);/* Use NOHANG to avoid stop */
        while (ChildStatus == 0) {  /* Wait for child to die */
          system("ps -lu $USER | grep ' Z '");  /* look for zombie */
          ChildStatus = waitpid(ChildId,0,WNOHANG);  
        }
        printf("PARENT: Child has terminated. Zombie should be cleaned up.\n");
        fflush(0);
        system("ps -lu $USER");   /* ps to see child is gone */
        sleep(2);
        printf("PARENT: Now we terminate.\n");
      }
    return(0);
  }