title: SHELL with PIPE communication BETWEEN 2 child processes with the same parent process
body: <p>I want to create a UNIX based <code>shell</code> that supports commands with 1 pipe.
  For example, the command <code>ls | wc</code></p>
  
  <p>I have wrote the following code but when I try an input like the one above, the program actes weird and can't figure out where the fault is. </p>
  
  <p>To be more specific, it appears to <code>fork()</code> properly, then <code>exec()</code> with the proper parameters but only the command before the pipe (ls) exits properly. The command after the pipe (wc) never exits actually and as a result there is no output from the program.</p>
  
  <p>I 've put some <code>printf</code> to help me figure out where is the fault in the code.
  Functions <code>fetch_input</code> and <code>string_tokenizer</code> are tested and work fine.</p>
  
  <p>The fault must be somewhere below the point pointed in the code.
  Any suggestion to help me find what is the fault would be appreciated.</p>
  
  <p>Thanks in advance.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;unistd.h&gt;
  
  #define ANSI_COLOR_GREEN "\x1b[32m"
  #define ANSI_COLOR_CYAN "\x1b[36m"
  #define ANSI_COLOR_RESET "\x1b[0m"
  
  char * fetch_input(char * buffer);
  char * trim(char * string);
  char ** string_tokenizer(char * string, char c);
  
  int main(int arc, char * argv[]){
  
  char *input, *init_input, **commands, **com1, **com2;
  pid_t fork_pid_1, fork_pid_2, ret_pid;
  int stat,i, fd[2];
  
  init_input = (char *)malloc(sizeof(char)*256);
  
  input = init_input;
  input = fetch_input(input);
  
  while(strcmp(input,"exit")!=0){
  
      commands = string_tokenizer(input,'|');
      com1 = string_tokenizer(commands[0],' ');
  
      if(commands[1]==0){
          fork_pid_1 = fork();
          if(fork_pid_1&lt;0){
              printf("Fork Error!\n");
              _exit(1);
          }
          else if(fork_pid_1==0){
              execvp(com1[0],com1);
              printf("Exec Error!\n");
              _exit(1);
          }
          else{
              ret_pid=wait(&amp;stat);
  
          }
      }
      else{                 //the fault is probably somewhere below that point
          if(pipe(fd)&lt;0){ _exit(1);}
  
          fork_pid_1 = fork();
  
          if(fork_pid_1&lt;0){
              printf("Fork Error!\n");
              _exit(1);
          }
          else if(fork_pid_1==0){
  
              printf("First command, ready to exec...(pid:%d)\n",getpid());       
  
              close(fd[0]);
              dup2(fd[1],1);
              close(fd[1]);
  
              execvp(com1[0],com1);
              printf("Exec Error!\n");
              _exit(1);
  
          }
          else{
              com2 = string_tokenizer(commands[1],' ');
  
              fork_pid_2=fork();
              if(fork_pid_2&lt;0){
                  printf("Fork Error!\n");
                  _exit(1);
              }
              else if(fork_pid_2==0){
  
                  printf("Second command, ready to exec...(pid:%d)\n",getpid());
  
                  close(fd[1]);
                  dup2(fd[0],0);
                  close(fd[0]);
  
                  execvp(com2[0],com2);
                  printf("Exec Error!\n");
                  _exit(1);
  
  
              }
              else{   
                  printf("Now we 're in the parent process...(p_pid:%d)\n",getpid());
                  while( (ret_pid=waitpid(-1,&amp;stat,0)) &gt;0 ){
                      printf("Child process (%d) exited with status:%d\n",ret_pid,stat);
                  }
  
              }
  
          }
  
  
      }
      input = init_input;
      input = fetch_input(input);
  }
  
  return 0;
  }
  
  char * fetch_input(char * buffer){
  
  int i, sum;
  
  do{
      printf(ANSI_COLOR_CYAN "$" ANSI_COLOR_RESET);
      fflush(stdin);
      fgets(buffer,256,stdin);
      if(buffer[strlen(buffer)-1]=='\n'){
          buffer[strlen(buffer)-1]='\0';
      }
      sum=0;
      for(i=0;i&lt;strlen(buffer);i++){
          if(buffer[i]==' '){sum++;}
      }
  }while(strlen(buffer)==sum);
  
  buffer = trim(buffer);
  
  return buffer;
  
  }
  
  char * trim(char * string){
  
      int i;
  
      i=strlen(string);
      while(string[i-1]==' '){
          i--;
      }
      *(string+i)='\0';
      while(isspace(*string)){string++;}
  
      return string;
  }
  
  char ** string_tokenizer(char * string, char c){
  
       int j=0,k,i,done,found,first,last;
       char ** ret, *str;
  
       str=string;
       if( (str==0) || (strlen(str)==0) ) return NULL;
       ret = (char **)malloc(sizeof(char*));
       do{
          done=0;
          found=0;
          i=0;
          first=-1;
          last=-1;
  
          while( (str[i]!='\0') &amp;&amp; (done==0) ){
  
                 if( (str[i]==c) &amp;&amp; (found==0) ){
                      i++;
                 }
                 else if( (str[i]!=c) &amp;&amp; (found==0) ){
                      found=1;
                      first=i;
                      i++;
                 }
                 else if( (str[i]!=c) &amp;&amp; (found!=0) ){
                      i++;
                 }
                 else if( (str[i]==c) &amp;&amp; (found!=0) ){
                      done=1;
                      last=i;
                 }
  
           }
  
  
           if(done!=0){
  
  
               *(ret+j) = (char *)malloc(sizeof(char)*(last-first+1));
  
               for(k=first;k&lt;last;k++){
                   *(*(ret+j)+(k-first)) = str[k];
               }
               *(*(ret+j)+(k-first)) = '\0';
               *(ret+j) = trim(*(ret+j));
               j++;
               str=str+last;
           }
  
  
       }while(done!=0);
  
       if( (done==0) &amp;&amp; (found==0) ){
           *(ret+j)=NULL;
       }
       else if( (done==0) &amp;&amp; (found!=0) ){
            *(ret+j) = (char *)malloc(sizeof(char)*(i-first+1));
            for(k=first;k&lt;i;k++){
                *(*(ret+j)+(k-first)) = str[k];
            }
            *(*(ret+j)+(k-first)) = '\0';
        *(ret+j)=trim(*(ret+j));
            *(ret+j+1) = NULL;
       }
  
       return ret;
  }
  </code></pre>