/*
 * PJ Waskiewicz
 * 2/08/2000
 * pipe.c
 * Function to handle pipes in pnsh
 */

#include "pnsh.h"

void pipeme(char **args, int numoftokens) {
  int p[2];
  int fd;
  int numofpipes = 0;
  int i, j, process_num = 0;
  int out_bool, redirect_pos;
  int pipepos[MAX_PIPES];
  out_bool = 0;
  for(i = 0, j = 0; i < numoftokens; i++) {
    if(strcmp(args[i], "|") == 0) {
      pipepos[j] = i;
      j++;
      numofpipes++;
    }
    /* Check if we are redirecting output */
    else if(strcmp(args[i], ">") == 0) {
      out_bool = 1;
      redirect_pos = i;
      /* Sanity check */
      if(args[redirect_pos + 1] == NULL) {
        fprintf(stderr, "Malformed redirect\n");
        exit(1);
      }
      else
        /* Get ready for the redirect */
        args[redirect_pos] = NULL;
    }
  }
  /* Start forking */
  if(fork() == 0) {
    pipe(p);
    dup2(p[0], 0);
    close(p[0]);
    for(i = 1; i < numofpipes + 1; i++) {
      if(fork() == 0) {
        dup2(p[0], 0);
        close(p[0]);
        close(p[1]);
        pipe(p);
        process_num = i;
      }
      else {
        dup2(p[1], 1);
        close(p[1]);
        close(p[0]);
        break;
      }
    }
    if(process_num == numofpipes) {
      /* I'm last */
      /* Find the pipe, in order to set up for exec.
       * We also need to check for output redirection
       */
      for(j = pipepos[numofpipes - 1]; j < numoftokens; j++) {
        if(strcmp(args[j], "|") == 0) {
          args[j] = NULL;
          if(out_bool == 1) {
            /* Time to open the file */
            if((fd = open(args[redirect_pos + 1], O_RDWR |
                          O_CREAT | O_TRUNC, 0666)) < 0)
              fprintf(stderr, "%s: open() in child\n", strerror(errno));
            /* Purge the file */
            if((fd = dup2(fd, 1)) < 0)
              fprintf(stderr, "%s: dup2() in child\n", strerror(errno));
          }
          if(execvp(args[pipepos[numofpipes - 1] + 1], args +
                    pipepos[numofpipes - 1] + 1) < 0) {
            fprintf(stderr, "%s: %s\n", args[pipepos[numofpipes - 1] + 1],
                    strerror(errno));
            exit(1);
          }
        }
      }
    }
    else if(process_num > 0) {
      /* I'm everyone else */
      for(j = pipepos[process_num]; j < numoftokens; j++) {
        if(strcmp(args[j], "|") == 0) {
          args[j] = NULL;
          if(execvp(args[pipepos[process_num - 1] + 1],
                    args + pipepos[process_num - 1] + 1) < 0) {
            fprintf(stderr, "%s: %s\n", args[pipepos[process_num - 1] + 1],
                    strerror(errno));
            exit(1);
          }
        }
      }
    }
    else {
      dup2(p[1], 1);
      close(p[0]);
      close(p[1]);
      /* I'm first */
      for(j = 0; j < numoftokens; j++) {
        if(strcmp(args[j], "|") == 0) {
          args[j] = NULL;
          if(execvp(args[0], args) < 0) {
            fprintf(stderr, "%s: %s\n", args[0], strerror(errno));
            exit(1);
          }
        }
      }
    }
  }
  else
    /* Wait for children to die */
    for(i = 0; i < numofpipes + 1; i++)
      wait(NULL);
}