1

I have this program which uses

ioctl(file_descriptor_of_stdout, TIOCGWINSZ, &w);

to get the terminal width (used in printing arrays). This works fine if I run my program directly on a terminal; however, I often pipe output through less, for paging and searching. For the sake of discussion assume stderr is also piped, so I can't "cheat" by expecting that to actually go to the terminal.

Now, less itself does take account of the terminal's width - for breaking lines or chopping them off. Does it not communicate this information further somehow to whatever is being piped through it?

xhienne
  • 5,738
  • 1
  • 15
  • 34
einpoklum
  • 118,144
  • 57
  • 340
  • 684

2 Answers2

2

You have more than one choice:

  • there are three streams (stdin, stdout and stderr), which your program can check using isatty(fileno(stdin)), etc. Redirecting output for an interactive program is more often done than redirecting input, so it is worth checking that.
  • if none of the streams is a terminal, you can open the tty which is associated with every interactive process. That is not necessarily /dev/tty, as shown in a quick check from a shell running in xterm:
    $ ls -l /dev/tty;tty;ls -l `tty`
    crw-rw-rw- 1 root root 5, 0 Mar 10 15:46 /dev/tty
    /dev/pts/1
    crw--w---- 1 tom tty 136, 1 Mar 10 16:09 /dev/pts/1
  • POSIX documents the tty program which might seem a good place to start. However your program would have to read the pathname from a pipe (a little more complicated than isatty applied to the standard streams). The documentation also says

    While no input is read from standard input, standard input shall be examined to determine whether or not it is a terminal, and, if so, to determine the name of the terminal.

    That is, if your program's standard input is redirected (not a terminal), tty is of no help finding the real terminal.
    Comment by @einpoklum reminded me that POSIX also documents the library call ttyname. By the way, usually when a program is implemented by a particular function call, POSIX documents the program, saying that it behaves "as if" if it used that call. But it did not mention this for tty.

  • if none of the standard streams is a terminal, you could try opening /dev/tty. If your program is not interactive, that could fail, e.g., running in cron or in the background. Lest that seem an odd criticism, there are occasional requests to open an X application from cron. Again, POSIX documents that (in 10.1 Directory Structure and Files
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • POSIX tty is not a good place to start, it just makes the `ttyname()` library call and prints the result (I checked the sources). But trying all 3 file descriptors is not a bad idea. – einpoklum Mar 10 '16 at 23:23
1

There are suggestions to try /dev/stderr , /dev/stdout, and /dev/stdin to see which one works, falling back on /dev/tty if none of them point to a terminal.

This is pointless. They will fail if they are redirected or piped, but otherwise will direct to /dev/tty

It's basically saying "check these until one points to /dev/tty, if not, try another, if all tried, resort to trying /dev/tty

If you want the size of the terminal, use /dev/tty directly.

The only reason to check the others first would be if you want to test whether they are going to screen.

P.S. I'm not allowed to leave a comment, but can leave a reply. Weird.

  • Yes, it is a bit strange that new users have to answer in order to leave comments. I see your point though. – einpoklum Mar 31 '23 at 20:20