title: I/O redirection, printing to the wrong file descriptor
body: <p>I'm working with piping along with other file descriptors, and I ran into a pickle.</p>
  
  <h2>Some Context</h2>
  
  <p>For some clairty, the function below makes repeated execvp calls using file descriptors based on context. This is so (Ideally) the calls can be easily strung together for i/o redirection. </p>
  
  <p>For example, one possible input might look like:</p>
  
  <pre><code>cat &lt; input.txt | tr a-z A-Z
  </code></pre>
  
  <p>Which a parser outside of this function turns into:</p>
  
  <pre><code>argvv.at(0).first = "cat", NULL
  argvv.at(0).second.at(0) = "1" //this lets us easily see what fd this 'chunk' is using. In my code, 1 stands for "&lt;"
  argvv.at(0).second.at(1) = "input.txt" // the file to be read from
  
  argvv.at(1).first = "tr", "a-z", "A-Z", NULL;
  argvv.at(1).second.at(0) = "4" // in my code, 4 stands for |
  </code></pre>
  
  <p>In a way, it's kind of like this:</p>
  
  <pre><code>(cat &lt; input.txt) (| tr a-z A-Z)
    argvv[0] ^         argvv[1] ^
  </code></pre>
  
  <p>This is all fed to fcall() to execute.</p>
  
  <p>The way the parser works isn't set in stone. It may not be the best way of doing things, but I'd prefer to solve the problem at hand for now. </p>
  
  <h2>The issue</h2>
  
  <p>For results where calls print to standard out, the calls print to standard in. This remains true for cases that don't involve piping either. <strong>This should not be the case, something must be wrong but I can't figure out what.</strong></p>
  
  <p>I'm still new to i/o, and I'm failing to see what file descriptor I miss-handled.</p>
  
  <p>Or perhaps it isn't that, and there's an even bigger misunderstanding. Really, I'm just hoping it turns not not to be a typo so I can learn something new.</p>
  
  <p><strong>What changes to the code need to be made in order to function as intended, and why?</strong></p>
  
  <h2>The code</h2>
  
  <pre><code>int fcall(std::vector &lt; std::pair&lt;char**, std::vector &lt;std::string&gt; &gt; &gt; argvv ){
  
   const int pipew = 1;
   const int piper = 0;
   //gotta say, fully understanding pipe I really appriciate how much sense this saves me.
  
  
   int status;
   if (strlen(argvv.at(0).first[0]) == 0){
  
       return -1;
   }
   if (!strcmp(argvv.at(0).first[0], "exit")){
  
       return 1;
   }
  
   //counter of weights
  
  
   unsigned int waitcount = 0;
  
   int n = 0;
  
   std::vector&lt;int*&gt; fdv;
  
   for (unsigned int k = 0; k &lt; argvv.size(); k++){
       if (!argvv.at(k).second.at(0).compare("4") ){ //figures out how many pipes we'll need
           int fd[2];
           if(pipe(fd) == -1)
               perror("pipe");
           fdv.push_back(fd);
       }
       else
       {
           fdv.push_back(NULL);
       }
  
       if(argvv.at(k).second.at(0).compare("2") &amp;&amp; argvv.at(k).second.at(0).compare("3")){ //determines how long we should be waiting
           waitcount++;
       }
  
   }
  
  
   int stdins;
   int stdouts;
  
   if (-1 == (stdins = dup(0)))
       perror("dup");
   if (-1 == (stdouts = dup(1)))
       perror("dup");
  
   for (unsigned int i = 0; i &lt; argvv.size(); i++ ){
  
       int pid = fork();
       if(pid == -1)//fork’s return value for an error is -1
  {
          //perror("There was an error with fork(). ");
          perror("fork"); //although you certainly can use the above, it is good
                          //practice not to write more information than necessary
          exit(1);//there was an error with fork so exit the program and go back and fix it
       }
  
       else if(pid == 0)//when pid is 0 you are in the child process
       {
           int fdx;
           int fdy;
  
           //(I) ==============
           int y = ((int)argvv.at(i).second.at(0).at(0)-48);
  
           std::cerr &lt;&lt; y &lt;&lt; std::endl;
           switch (y){
               case 0:
               break;
  
               case 1:
                   if (-1 == (fdy = open(argvv.at(i).second.at(1).c_str(), O_RDONLY))){
                       perror("open");
                   }
                   if (-1 == dup2(fdy, 0)){
                       perror("dup");
                   }
               break;
  
               case 2:
               break;
  
               case 3:
               break;
  
               case 4:
               if(-1 == dup2(fdv.at(i)[piper],0 ))
                   perror("dup");
               break;
  
               }
  
           //(I +1) ==============
           if (i+1 &lt; argvv.size()){
              int z = ((int)argvv.at(i+1).second.at(0).at(0)-48);
           std::cerr &lt;&lt; std::endl;
               switch (z){
                   case 0:
                   break;
  
                   case 1:
                   break;
  
                   case 2:
                   if (-1 == (fdx = open(argvv.at(i+1).second.at(1).c_str(), O_RDWR | O_CREAT,S_IRWXU ))){
                       perror("open");
                   }
                   if (-1 ==  dup2(fdx,1 ))
                       perror("dup");
                   break;
  
                   case 3:
                   if (-1 == (fdx = open(argvv.at(i+1).second.at(1).c_str(), (O_RDWR | O_APPEND) | O_CREAT,S_IRWXU ))){
                       perror("open");
                   }
                   if (-1 ==  dup2(fdx,1 ))
                       perror("dup");
                   break;
  
                   case 4:
                       if(-1 == dup2(fdv.at(i+1)[pipew],1 ))
                           perror("dup");
                   break;
                }
           }
           for(unsigned int kg; kg &lt; fdv.size(); kg++){
               if (fdv.at(kg) != NULL){
                   if (-1 == close(fdv.at(kg)[0]))
                       perror("close");
                   if (-1 == close(fdv.at(kg)[1]))
                       perror("close");
               }
           }
  
           if (y != 2 &amp;&amp; y!= 3){
               if (0 &lt; execvp(argvv.at(i).first[0],argvv.at(i).first )){
                   n = -1;
                   perror("execvp");
               }
           }
  
           exit(1);  //when the child process finishes doing what we want it to, cout,
                     //we want to kill the child process so it doesn’t go on in the program so we exit
  
       }
  
   }
  
   for (unsigned int f = 0; f &lt; waitcount; f++){
       if (-1 == wait(&amp;status))
           perror("wait");
   }
  
   if (-1 == dup2(stdins, 0))
       perror("dup");
   if (-1 == dup2(stdouts, 1))
       perror("dup");
  
  
   if (-1 == close(stdins))
       perror("close");
   if (-1 == close(stdouts))
       perror("close");
  
   return n;
  }
  </code></pre>
  
  <p>Thanks a whole bunch!</p>