#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "prtastr.h"
#define BUFFSIZE 1024
int parse_args(int argc,  char *argv[ ], int *np, int* n){
  if ( (argc != 3) ||
       ((*np = atoi (argv[1])) <= 0)  || 
       ((*n = atoi (argv[2]))  < 0)
       ) {
    fprintf (stderr, "Usage: %s nprocs delay\n", argv[0]);
    return(-1); };
  return(0); 
}
int make_trivial_ring(){   
  int   fd[2];
  if (pipe (fd) == -1) 
    return(-1); 
  if ((dup2(fd[0], STDIN_FILENO) == -1) ||
      (dup2(fd[1], STDOUT_FILENO) == -1)) 
    return(-2); 
  if ((close(fd[0]) == -1) || (close(fd[1]) == -1))   
    return(-3); 
  return(0); 
}
int add_new_node(int *pid){
  int fd[2];
  if (pipe(fd) == -1) 
    return(-1); 
  if ((*pid = fork()) == -1)
    return(-2); 
  if(*pid > 0 && dup2(fd[1], STDOUT_FILENO) < 0)
    return(-3); 
  if (*pid == 0 && dup2(fd[0], STDIN_FILENO) < 0)
    return(-4); 
  if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) 
    return(-5);
  return(0);
}
int main(int argc,  char *argv[]){
   int   i;             /* number of this process (starting with 1)   */
   int   childpid;      /* indicates process should spawn another     */ 
   int   nprocs;        /* total number of processes in ring          */ 
   int   delay;
   if(parse_args(argc,argv,&nprocs, &delay) < 0) 
     exit(EXIT_FAILURE);
   if(make_trivial_ring() < 0){
     perror("Could not make trivial ring");
     exit(EXIT_FAILURE); 
   }
   for (i = 1; i < nprocs;  i++) {
     if(add_new_node(&childpid) < 0){
       perror("Could not add new node to ring");
       exit(EXIT_FAILURE); 
     }
     if (childpid) break; 
   }

   /* ring process code  */
   {
     char buff[BUFFSIZE];
     int token = 7;
     int bytes;
     sprintf(buff,"I'm process %d with parent %d whose i = %i\n", 
	     getpid(), getppid(), i);

     if(i == 1){
       prtastr(buff, STDERR_FILENO, delay);
       if((bytes = write(STDOUT_FILENO, &token, sizeof(token))) 
	  != sizeof(token)){
	 perror("Write of token failed");
	 exit(EXIT_FAILURE); 
       }
     }
     while(1){
       if((bytes =  read(STDIN_FILENO, &token, sizeof(token))) 
	  != sizeof(token)){
	 perror("Read of token failed");
	 exit(EXIT_FAILURE); 
       }
       prtastr(buff, STDERR_FILENO, delay);
       if((bytes = write(STDOUT_FILENO, &token, sizeof(token))) 
	  != sizeof(token)){
	 perror("Write of token failed");
	 exit(EXIT_FAILURE); 
       }
     }
     exit(EXIT_FAILURE);
   }  /* end of ring process code  */
}     /* end of main program here */