title: How to properly read a process's file descriptors?
body: <p>I am writing a small program to list the file descriptors of a specific process, and I am having a hard time understanding the results. The process I'm inspecting looks like this:</p>
  <pre class="lang-c prettyprint-override"><code>int main() {
      int fds1[2];
      int fds2[2];
      pipe(fds1);
      pipe(fds2);
      pid_t pid = fork();
      if (pid == 0) {
          dup2(fds1[0], STDIN_FILENO);
          dup2(fds2[1], STDOUT_FILENO);
          close(fds1[0]);
          close(fds1[1]);
          close(fds2[0]);
          close(fds2[1]);
          sleep(2);
          return 0;
      }
      close(fds1[0]);
      close(fds2[1]);
      waitpid(pid, NULL, 0);
      return 0;
  }
  </code></pre>
  <p>The fd inspection program code looks like:</p>
  <pre class="lang-rust prettyprint-override"><code>let path_str = format!(&quot;/proc/{}/fd&quot;, self.pid);
  let dir = Path::new(&amp;path_str);
  
  let mut fds = Vec::new();
  for entry in fs::read_dir(dir).ok()? {
      let path = entry.ok()?.path();
      let filename = path.file_name()?;
      let fd = fname.to_str()?.to_string().parse::&lt;usize&gt;().ok()?
      fds.push(fd);
  }
  </code></pre>
  <p>The results of <code>ls -l /proc/{pid}/fd</code> while running the above programs together give me this list:</p>
  <pre><code>0 -&gt; /dev/pts/6
  1 -&gt; /dev/pts/6
  2 -&gt; /dev/pts/6
  22 -&gt; /dev/pts/1
  30 -&gt; /dev/pts/4
  
  4 -&gt; /home/{user}/.spectrwm.conf
  5 -&gt; 'pipe:[168640]'
  6 -&gt; 'pipe:[168641]'
  </code></pre>
  <p>I'm confused as to why there are 5 symlinks to <code>/dev/pts/x</code> and why the bottom 3 fds are included in this process's file descriptors, especially my WM's config file. I have a basic understanding of how <code>pipe</code> and <code>fork</code> work, but I can't seem to understand what's going on here.</p>
  <p>Any help or insight would be appreciated, thanks!</p>