// Morgan Elder
// CMPSCI 4760

// Program 3.1
// simplechain.c
// A program that creates a chain of processes, where n is a command-line argument

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>

int main(int argc, char *argv[])
{
  int opt;
  const int MAX_PROCESSES = 100;

  pid_t childpid = 0;
  int i,
      iter,
      nprocs = 4,
      sleeptime = 3,
      niters = 1;

  while ((opt = getopt(argc, argv, ":p:s:i:")) != -1)
  {
    switch (opt)
    {
    case 'p':
      nprocs = atoi(optarg);
      if (nprocs > MAX_PROCESSES)
      {
        fprintf(stderr, "%s: error: Max number of processes (%d) exceeded\n", argv[0], MAX_PROCESSES);
        return 1;
      }
      else if (nprocs < 0)
      {
        fprintf(stderr, "%s: error: The number of forked processes cannot be less than 0", argv[0]);
        return 1;
      }
      break;
    case 's':
      sleeptime = atoi(optarg);
      if (sleeptime < 0)
      {
        fprintf(stderr, "%s: error: The sleep time cannot be less than 0 seconds", argv[0]);
        return 1;
      }
      break;
    case 'i':
      niters = atoi(optarg);
      if (niters < 1)
      {
        fprintf(stderr, "%s: error: niters cannot be less than 1", argv[0]);
        return 1;
      }
      break;
    case '?':
      fprintf(stderr, "%s: error: Uknown option %c\n", argv[0], optopt);
      return 1;
    case ':':
      fprintf(stderr, "%s: error: Missing arg for %c\n", argv[0], optopt);
      return 1;
    default:
      abort();
    }
  }

  if (argc < 2)
  { // check for valid number of command-line arguments
    fprintf(stderr, "Usage: %s processes\n", argv[0]);
    return 1;
  }
  for (i = 1; i < nprocs; i++)
  {
    if (childpid = fork())
    {
      break;
    }
  }
  for (iter = 0; iter < niters; iter++)
  {
    sleep(sleeptime);
    if (wait(NULL) == -1)
    {
      perror(strcat(argv[0], ": error: "));
      return 1;
    }
    fprintf(stderr, "i: %d process ID: %ld parent ID: %ld child ID: %ld\n",
            i, (long)getpid(), (long)getppid(), (long)childpid);
  }

  return 0;
}