/* sample solution for comp2310 lab 7, 2007 */
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

int main(int argc, char *argv[]){
  int id, n, *buf1, i, len;
  int fd_l[2], fd_r[2], fd_lp[2];
  int status;
  int nbytes;
  pipe(fd_l);
  pipe(fd_r);
  fd_lp[0] = fd_l[0]; // save for child n-1
  fd_lp[1] = fd_l[1];

  if (argc != 2){
    printf("Error no input argument\n");
    exit(-1);
  } else {
    // convert the character string argument to an integer
    n = atoi(argv[1]);
  }
  len = sizeof(int)*n;
  buf1 = (int*) malloc(len);

  id = 0; 
  while (id < n-1 && fork()==0) { // child
    id++;  	 // id'th level child; note: next child will see this update 
    printf("child %d created\n", id);
    fd_l[0] = fd_r[0]; // inherit left pipe of child from right pipe of parent
    fd_l[1] = fd_r[1];
    if (id < n-1) {
      pipe(fd_r); // redefine for next child
    } else // get this from the original parent
      fd_r[0] = fd_lp[0], fd_r[1] = fd_lp[1];
  }
  
  close(fd_r[0]); /* close read from right */
  close(fd_l[1]); /* close write from left */

  for (i=0; i < n; i++)
    buf1[i] = -2;
  
  if (id == 0) {
    for (i=0; i < n; i++)
      buf1[i] = -1;
    buf1[id] = id;
    nbytes = write(fd_r[1], buf1, (id+1)*sizeof(int));
    printf("p%d: write %d bytes\n", id, nbytes);
    nbytes = read(fd_l[0], buf1,  n*sizeof(int));
    printf("p%d: read %d bytes\n", id, nbytes);
    for (i=0; i < n; i++)
      printf("%d ", buf1[i]);
    printf("\n");
  } else {
    nbytes = read(fd_l[0], buf1, id*sizeof(int));
    printf("p%d: read %d bytes\n", id, nbytes);
    buf1[id] = id;
    nbytes = write(fd_r[1], buf1, (id+1)*sizeof(int));
    printf("p%d: write %d bytes\n", id, nbytes);
  }

  return 0;
}
