title: Understanding dup2 and closing file descriptors
body: <p>I'm posting my code simply for context of my question. I'm not explicitly looking for you to help fix it, I'm more so looking to understand the dup2 system call that I'm just not picking up from the man page and the numerous other stackoverflow questions.</p>
  
  <pre><code>    pid = fork();
  
      if(pid == 0) {
          if(strcmp("STDOUT", outfile)) {
              if (command-&gt;getOutputFD() == REDIRECT) {
                  if ((outfd = open(outfile, O_CREAT | O_WRONLY | O_TRUNC)) == -1)
                      return false;
                  command-&gt;setOutputFD(outfd);
                  if (dup2(command-&gt;getOutputFD(), STDOUT_FILENO) == -1)
                      return false;
                  pipeIndex++;
              }
              else if (command-&gt;getOutputFD() == REDIRECTAPPEND) {
                  if ((outfd = open(outfile, O_CREAT | O_WRONLY | O_APPEND)) == -1)
                      return false;
                  command-&gt;setOutputFD(outfd);
                  if (dup2(command-&gt;getOutputFD(), STDOUT_FILENO) == -1)
                      return false;
                  pipeIndex++;
              }
              else {
                  if (dup2(pipefd[++pipeIndex], STDOUT_FILENO) == -1)
                      return false;
                  command-&gt;setOutputFD(pipefd[pipeIndex]);
              }
          }
  
          if(strcmp("STDIN", infile)) {
              if(dup2(pipefd[pipeIndex - 1], STDIN_FILENO) == -1)
                  return false;
              command-&gt;setOutputFD(pipefd[pipeIndex - 1]);
              pipeIndex++;
          }
  
  
          if (execvp(arguments[0], arguments) == -1) {
              std::cerr &lt;&lt; "Error!" &lt;&lt; std::endl;
              _Exit(0);
          }
  
      }
  
      else if(pid == -1) {
          return false;
      }
  </code></pre>
  
  <p>For context to you, that code represents the execution step of a basic linux shell. The command object contains the commands arguments, IO "name", and IO descriptors (I think I might get rid of the file descriptors as fields).</p>
  
  <p>What I'm having the most difficultly understanding is when and which file descriptors to close. I guess I'll just ask some questions to try and improve my understanding of the concept.</p>
  
  <p>1) With my array of file descriptors used for handling pipes, the parent has a copy of all those descriptors. When are the descriptors held by the parent closed? And even more so, which descriptors? Is it all of them? All of the ones left unused by the executing commands?</p>
  
  <p>2) When handling pipes within the children, which descriptors are left open by which processes? Say if I execute the command: ls -l | grep 
  "[username]", Which descriptors should be left open for the ls process? Just the write end of the pipe? And if so when? The same question applies to the grep command.</p>
  
  <p>3) When I handle redirection of IO to a file, a new file must be opened and duped to STDOUT (I do not support input redirection). When does this descriptor get closed? I've seen in examples that it gets closed immediately after the call to dup2, but then how does anything get written to the file if the file has been closed?</p>
  
  <p>Thanks ahead of time. I've been stuck on this problem for days and I'd really like to be done with this project.</p>
  
  <hr>
  
  <p><strong>EDIT</strong> I've updated this with modified code and sample output for anyone interested in offering specific help to my issue. First I have the entire for loop that handles execution. It has been updated with my calls to close on various file descriptors.</p>
  
  <pre><code>while(currCommand != NULL) {
  
      command = currCommand-&gt;getData();
  
      infile = command-&gt;getInFileName();
      outfile = command-&gt;getOutFileName();
      arguments = command-&gt;getArgList();
  
      pid = fork();
  
      if(pid == 0) {
          if(strcmp("STDOUT", outfile)) {
              if (command-&gt;getOutputFD() == REDIRECT) {
                  if ((outfd = open(outfile, O_CREAT | O_WRONLY | O_TRUNC)) == -1)
                      return false;
                  if (dup2(outfd, STDOUT_FILENO) == -1)
                      return false;
                  close(STDOUT_FILENO);
              }
              else if (command-&gt;getOutputFD() == REDIRECTAPPEND) {
                  if ((outfd = open(outfile, O_CREAT | O_WRONLY | O_APPEND)) == -1)
                      return false;
                  if (dup2(outfd, STDOUT_FILENO) == -1)
                      return false;
                  close(STDOUT_FILENO);
              }
              else {
                  if (dup2(pipefd[pipeIndex + 1], STDOUT_FILENO) == -1)
                      return false;
                  close(pipefd[pipeIndex]);
              }
          }
          pipeIndex++;
  
          if(strcmp("STDIN", infile)) {
              if(dup2(pipefd[pipeIndex - 1], STDIN_FILENO) == -1)
                  return false;
              close(pipefd[pipeIndex]);
              pipeIndex++;
          }
  
          if (execvp(arguments[0], arguments) == -1) {
              std::cerr &lt;&lt; "Error!" &lt;&lt; std::endl;
              _Exit(0);
          }
      }
  
      else if(pid == -1) {
          return false;
      }
  
      currCommand = currCommand-&gt;getNext();
  
  }
  
  for(int i = 0; i &lt; numPipes * 2; i++)
      close(pipefd[i]);
  
  for(int i = 0; i &lt; commands-&gt;size();i++) {
      if(wait(status) == -1)
          return false;
  }
  </code></pre>
  
  <p>When executing this code I receive the following output </p>
  
  <pre><code>ᕕ( ᐛ )ᕗ ls -l
  total 68
  -rwxrwxrwx 1 cook cook   242 May 31 18:31 CMakeLists.txt
  -rwxrwxrwx 1 cook cook   617 Jun  1 22:40 Command.cpp
  -rwxrwxrwx 1 cook cook  9430 Jun  8 18:02 ExecuteExternalCommand.cpp
  -rwxrwxrwx 1 cook cook   682 May 31 18:35 ExecuteInternalCommand.cpp
  drwxrwxrwx 2 cook cook  4096 Jun  8 17:16 headers
  drwxrwxrwx 2 cook cook  4096 May 31 18:32 implementation files
  -rwxr-xr-x 1 cook cook 25772 Jun  8 18:12 LeShell
  -rwxrwxrwx 1 cook cook   243 Jun  5 13:02 Makefile
  -rwxrwxrwx 1 cook cook   831 Jun  3 12:10 Shell.cpp
  ᕕ( ᐛ )ᕗ ls -l &gt; output.txt
  ls: write error: Bad file descriptor
  ᕕ( ᐛ )ᕗ ls -l | grep "cook"
  ᕕ( ᐛ )ᕗ 
  </code></pre>
  
  <p>The output of <code>ls -l &gt; output.txt</code> implies that I'm closing the wrong descriptor, but closing the other related descriptor, while rendering no error, provides no output to the file. As demonstrated by <code>ls -l</code>, <code>grep "cook"</code>, should generate output to the console.</p>