Image

Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

How do programs like less receive keyboard input as well as from a pipe?

+4
−0

(Inspired by: https://discuss.python.org/t/_/107345)

It was brought to my attention that it actually works to do something like:

$ spam=$(printf '%1000s')
$ spam=${spam// /abcdefg}
$ echo $spam | less

(There are other TUI programs I use where this doesn't work; whatever is received from the pipe is interpreted as if it were typed by the user, and then the program hangs if it hasn't yet received a "quit" command in the input.)

We have multiple pages of text fed to the standard input of less, which is then able to show the first page and wait for the usual sort of commands from the user.

But how? I thought that the program is reading those commands from standard input, but that was already redirected via a pipe. In other programs I've created myself, once standard input was attached somewhere, it would be impossible to "feed" it from somewhere else (e.g. if I have foo | bar already running, I can find no way for baz to write to bar's input).

And even if the key presses were being translated into input fed to less's stdin, how would it be able to distinguish which input comes from the keyboard vs. the pipe? (It clearly can't do this by inspecting the actual byte values, since less accepts commands that are ordinary text, such as q, rather than purely relying on things that would start with a control character.)

History

0 comment threads

1 answer

+4
−0

As you've observed, programs like less don't rely on STDIN for interactive input. Instead, they look for their controlling terminal and open a new file descriptor reading from that. On most systems, that's achieved by opening /dev/tty for reading. Much as with STDIN/STDOUT/STDERR, a Unix process usually inherits its controlling terminal from its parent, in this case the shell. See also tty(4) and credentials(7).

Another program that does this is sudo, which is why you can type things like:

echo foo | sudo tee /root/bar

and it'll work even if sudo wants a password. What's more, it uses the controlling terminal for printing the password prompt too, so you could even do:

cut -d: -f1 /etc/passwd | sudo xargs getent shadow | less

and it still works.

History

2 comment threads

There is more complexity (1 comment)
Insight (1 comment)

Sign up to answer this question »