Less gets keyboard input from stderr?

前端 未结 4 2106
南方客
南方客 2020-12-11 01:25

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 fr

相关标签:
4条回答
  • 2020-12-11 01:58

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

    0 讨论(0)
  • 2020-12-11 02:04
    $ ls -l /dev/fd/
    lrwx------ 1 me me 64 2009-09-17 16:52 0 -> /dev/pts/4
    lrwx------ 1 me me 64 2009-09-17 16:52 1 -> /dev/pts/4
    lrwx------ 1 me me 64 2009-09-17 16:52 2 -> /dev/pts/4
    

    When logged in at an interative terminal, all three standard file descriptors point to the same thing: your TTY (or pseudo-TTY).

    $ ls -fl /dev/std{in,out,err}
    lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdin -> fd/0
    lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdout -> fd/1
    lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stderr -> fd/2
    

    By convention, we read from 0 and write to 1 and 2. However, nothing prevents us from doing otherwise.

    When your shell runs ls -l * | less, it creates a pipe from ls's file descriptor 1 to less's file descriptor 0. Obviously, less can no longer read the user's keyboard input from file descriptor 0 – it tries to get the TTY back however it can.

    If less has not been detached from the terminal, open("/dev/tty") will give it the TTY.

    However, in case that fails... what can you do? less makes one last attempt at getting the TTY, assuming that file descriptor 2 is attached to the same thing that file descriptor 0 would be attached to, if it weren't redirected.

    This is not failproof:

    $ ls -l * | setsid less 2>/dev/null
    

    Here, less is given its own session (so it is no longer a part of the terminal's active process group, causing open("/dev/tty") to fail), and its file descriptor 2 has been changed – now less exits immediately, because it is outputting to a TTY yet it fails to get any user input.

    0 讨论(0)
  • 2020-12-11 02:16

    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 :)

    0 讨论(0)
  • 2020-12-11 02:21

    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".

    0 讨论(0)
提交回复
热议问题