views:

204

answers:

4

Hello!

I'm taking a look at the code to the 'less' utility, specifically how it gets keyboard input. Interestingly, on line 80 of ttyin.c, it sets the file descriptor to read from:

     /*
      * Try /dev/tty.
      * If that doesn't work, use file descriptor 2,
      * which in Unix is usually attached to the screen,
      * but also usually lets you read from the keyboard.
      */
  #if OS2
      /* The __open() system call translates "/dev/tty" to "con". */
      tty = __open("/dev/tty", OPEN_READ);
  #else
      tty = open("/dev/tty", OPEN_READ);
  #endif
      if (tty < 0)
          tty = 2;

Isn't file descriptor 2 stderr? If so, WTH?! I thought keyboard input was sent through stdin.

Interestingly, even if you do ls -l * | less, after the file finishes loading, you can still use the keyboard to scroll up and down, but if you do ls -l * | vi, then vi will yell at you because it doesn't read from stdin. What's the big idea? How did I end up in this strange new land where stderr is both a way to report errors to the screen and read from the keyboard? I don't think I'm in Kansas anymore...

+2  A: 

Well... first off, you seem to missing the open() call which opens '/dev/tty'. It only uses file descriptor 2 if the call to open() fails. On a standard Linux system, and probably many Unices, '/dev/tty' exists and is unlikely to cause a fail.

Secondly, the comment at the top provides a limited amount of explanation as to why they fall back to file descriptor 2. My guess is that stdin, stdout, and stderr are pretty much connected to '/dev/tty/' anyway, unless redirected. And since the most common redirections for for stdin and/ or stdout (via piping or < / >), but less often for stderr, odds on are that using stderr would be most likely to still be connect to the "keyboard".

Jason Musgrove
The reason for using stderr is that stdin/stdout are more likely to be pipes created by the spawning shell. Piping into or out of less is a noop, but does work. But redirecting stderr of a less command specifically has little value and isn't likely to be done. So betting that stderr is "really" the terminal device is a reasonable guess.
Andy Ross
+1  A: 

The same question with an answer ultimately from the person who asked it is on linuxquestions although they quote slightly different source from less. And no, I don't understand most of it so I can't help beyond that :)

Troubadour
A: 

It appears to be Linux specific functionality that sends keyboard input to FD 2.

DVK
Blatantly false. Try this on any other UNIX.
ephemient
+10  A: 
ephemient
+1, very complete.
sheepsimulator
Oh, I see it now. Because stderr is nothing more than juts a file descriptor that's actually connected to the terminal, it can read or write from it as it pleases. THAT'S COOL! Thank you, ephemient.
Michael