title: How to duplicate a child descriptor onto STDOUT_FILENO and STDERR_FILENO
body: <p>I am trying to implement the GNU <code>popen</code> library but having issues with <code>dup2</code>. I want to duplicate the child pipe to both <code>STDOUT_FILENO</code> and <code>STDERR_FILENO</code>.
   I am little confuse here with the dup2, because it says on the man page that dup2 closes the old descriptor, how how can use duplicate pipe onto <code>STDERR_FILENO</code> after doing this <code>dup2(pipe_list[child_fd], child_fd)</code>. Because from what i do understand upon a call to dup2 the <code>oldfp</code> will be closed and this <code>dup2(pipe_list[child_fd], STDERR_FILENO)</code> will not work because <code>pipe_list[child_fd]</code> was already closed. Should i use <code>dup</code> and after that close <code>fd</code> or there is a way to achieve this with <code>dup2</code>?</p>
  
  <pre><code>#define tpsr(a,b) (*type == 'r' ? (b) : (a))
  #define tpsw(a,b) (*type == 'w' ? (b) : (a))
  
  
  static FILE *fp_stream = NULL;
  static pid_t popen_pid = -1;
  static const char * const shell_path = "/bin/sh";
  
  
  FILE *mypopen(const char *command, const char *type) {
  
      int pipe_list[2];
      int parent_fd, child_fd;
  
  
      if (type == NULL || type[1] != 0) {
          errno = EINVAL;
          return NULL;
      }
  
      if (type[0] != 'w' &amp;&amp; type[0] != 'r') {
          errno = EINVAL;
          return NULL;
      }
  
  
      if (pipe(pipe_list) == -1) {
          return NULL;  //errno will be set
      }
  
      child_fd = tpsr(STDIN_FILENO,STDOUT_FILENO);
      parent_fd = tpsw(STDIN_FILENO,STDOUT_FILENO);
      /*The above (tpsr and tpsw) are the same as this
          if type[0] == 'r'
          child_fd = STDOUT_FILENO; //1 child will be doing the writing
          parent_fd = STDIN_FILENO; //0 parent read
  
         if type[0] == 'w'
          child_fd = STDIN_FILENO; //0 child doing the reading
          parent_fd = STDOUT_FILENO;//1 parent do the writing
      }*/
  
  
      if ((popen_pid = fork()) == -1) {
          close(pipe_list[0]);
          close(pipe_list[1]);
          return NULL;
      }
  
      if (popen_pid == 0) {
          // we got a child here
  
          if (pipe_list[child_fd] != child_fd) {
  
              if (dup2(pipe_list[child_fd], child_fd) == -1) {
                  (void) close(pipe_list[child_fd]);
                  _exit(EXIT_FAILURE);
              }
                //is this the right way after the oldfd is closed by dup2
              if (child_fd == STDOUT_FILENO) {
                  if (dup2(pipe_list[child_fd], STDERR_FILENO) == -1){
                      (void) close(pipe_list[child_fd]);
                      _exit(EXIT_FAILURE);
                  }
  
              }
  
              (void) close(pipe_list[child_fd]);
          }
          (void) pipe_list[parent_fd];
  
  
          (void) execl(shell_path, "sh", "-c", command, (char *) NULL);
          _exit(EXIT_FAILURE); //exit(127) required by man page
  
      } else {
  
          (void) close(pipe_list[child_fd]);
          if ((fp_stream = fdopen(pipe_list[parent_fd], type)) == NULL) {
              (void) close(pipe_list[parent_fd]);
              return NULL;
          }
  
  
      }
  
      return fp_stream;
  }
  </code></pre>