title: How to find the terminal name associated with a process reliably in C?
body: <p>See the following code.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;unistd.h&gt;
  
  int main()
  {
      printf("ttyname(0): %s\n", ttyname(0));
      printf("ttyname(1): %s\n", ttyname(1));
      printf("ttyname(2): %s\n", ttyname(2));
      printf("ctermid(NULL): %s\n", ctermid(NULL));
  
      /* Sleep for sometime so that we can manually run the ps command to
       * see the terminal associated with the process. */
      sleep(10);
  
      return 0;
  }
  </code></pre>
  
  <p>I compile and run this as follows.</p>
  
  <pre><code>$ gcc foo.c
  $ ./a.out 
  ttyname(0): /dev/pts/3
  ttyname(1): /dev/pts/3
  ttyname(2): /dev/pts/3
  ctermid(NULL): /dev/tty
  </code></pre>
  
  <p>In another terminal, I run the <code>ps</code> command to confirm the terminal name.</p>
  
  <pre><code>$ ps -ef | grep a.out | grep -v grep
  coder     1498  1473  0 19:19 pts/3    00:00:00 ./a.out
  </code></pre>
  
  <p>Everything is good so far. My program prints the terminal correctly.</p>
  
  <p>However, my program fails to output the terminal information when stdin, stdout as well as stderr are redirected as follows.</p>
  
  <pre><code>$ ./a.out &lt; /dev/null &gt; foo.txt 2&gt; /dev/null
  </code></pre>
  
  <p>In another terminal, I run <code>ps</code> and I can see that indeed <code>/dev/pts/3</code> is associated witht he process.</p>
  
  <pre><code>$ ps -ef | grep a.out | grep -v grep
  coder     1536  1473  0 19:22 pts/3    00:00:00 ./a.out
  </code></pre>
  
  <p>But after <code>./a.out</code> exits and I check its output in <code>foo.txt</code>, I don't see this information captured.</p>
  
  <pre><code>$  cat foo.txt 
  ttyname(0): (null)
  ttyname(1): (null)
  ttyname(2): (null)
  ctermid(NULL): /dev/tty
  </code></pre>
  
  <p>Since <code>ttyname()</code> fails to provide any meaningful information when stdin, stdout and stderr are redirected and since <a href="http://code.metager.de/source/xref/gnu/glibc/sysdeps/posix/ctermid.c" rel="nofollow noreferrer"><code>ctermid()</code> always returns <code>/dev/tty</code></a>, what can I do to reliably determine the terminal associated with a process? I am ideally looking for a solution that works on any standard Unix or Linux system, but if that is not possible, then Linux specific solutions are also okay.</p>