title: pipes causing infinite output
body: <p>When I simply pipe ls -l | sort with this, the program just spits out the results from ls -l infinitely.  Can anyone see what's wrong?
  Assume that you only have to look at the main function.  This will compile, though.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;sys/wait.h&gt;
  
  
  #define COMMAND_LINE_LENGTH 256
  #define HISTORY_LENGTH 10
  #define TOKEN_MAX 50
  #define DIRECTORY_LENGTH 5
  #define DIRECTORY_PREFIX "/bin/"
  
  struct prog_def
  {
      //Binary location
      char *bin;
  
      //Is this program expecting a pipe?
      int expecting_pipe;
  
      //Arguments
      char *args[TOKEN_MAX + 1];
  
      pid_t pid;
  
  } prog_def;
  
  int get_prog_defs(const char* buf, struct prog_def prog_defs[])
  {
      char *line = malloc(strlen(buf) + 1);
  
      int prog_count = 0;
      char* token;
  
      strcpy(line, buf);
      line[strlen(buf)] = 0;
  
      while(1)
      {
          int arg_count = 0;
  
          //The first time through we have to pass the line
          token = strtok(line, " ");
  
          //Each subsequent call we have to pass NULL
          //http://www.cplusplus.com/reference/cstring/strtok/
          line = NULL;
  
          //Start building the binary location string
          prog_defs[prog_count].bin = (char*)malloc(strlen(token) + DIRECTORY_LENGTH + 1);
  
          //Concatenate the directory prefix and command name
          strcat(prog_defs[prog_count].bin, DIRECTORY_PREFIX);
          strcat(prog_defs[prog_count].bin, token);
  
          //The first argument execvp will expect is the binary location itself
          //Redundant but if I wasn't too lazy to read the doc then I'd know why
          prog_defs[prog_count].args[arg_count++] = prog_defs[prog_count].bin;
  
          while(1)
          {
              prog_defs[prog_count].expecting_pipe = 0;
  
              //Check next token for end, pipe, IO redirection, or argument
              token = strtok(NULL, " ");
  
              //If we've consumed all tokens
              if (token == NULL)
                  break;
  
              //Pipe
              if (strcmp(token, "|") == 0)
              {
                  prog_defs[prog_count - 1].expecting_pipe = 1;
                  break;
              }
  
              //Regular argument
              prog_defs[prog_count].args[arg_count++] = token;
          }
  
          ++prog_count;
  
          if (token == NULL) break;
      }
  
      return prog_count;
  }
  
  
  int main(int argc, char** argv)
  {
  
      char command[COMMAND_LINE_LENGTH] = {0};
  
      //Generic loop counter
      int x = 0;
  
      while(1)
      {
          printf("&gt;");
  
          //Get the command
          gets(command);
  
          struct prog_def prog_defs[TOKEN_MAX];
          int prog_count = get_prog_defs(command, prog_defs);
  
          //Keep the previous out fd for the in of the subsequent process
          int prev_out_fd = open("/dev/null", O_RDONLY);
  
          for (x = 0; x &lt; prog_count; ++x)
          {
              //Create a pipe for both processes to share
              int pipefd[2];
  
              if (x != prog_count -1)
              {
                  pipe(pipefd);
              }
  
              prog_defs[x].pid = fork();
  
              if(prog_defs[x].pid == 0)
              {
                  dup2(prev_out_fd, STDIN_FILENO);
                  close(pipefd[1]);
  
                  if(x != prog_count - 1)
                  {
                      dup2(pipefd[1], STDOUT_FILENO);
                      close(pipefd[0]);
                      close(pipefd[1]);
                  }
  
  
                  execvp(prog_defs[x].bin, prog_defs[x].args);
              prev_out_fd = pipefd[0];
              close(pipefd[1]);
              }
  
          close(prev_out_fd);
  
              prev_out_fd = pipefd[0];
              close(pipefd[1]);
  
          }
  
          printf("\n");
  
          for (x = 0; x &lt; prog_count; ++x)
          {
              waitpid(prog_defs[x].pid, NULL, 0);
          }
  
      }
  }
  </code></pre>