5

Say that the ping command is running, and I type something on the terminal while ping is still running.

Now when ping terminates and bash gain back control, bash will print on the terminal what I typed while ping was running. This is a screenshot that shows what I mean:

enter image description here

How did bash get this information? I am sure it did not get it from stdin, because when I typed "I typed this while ping was running", I did not press Enter (and so stdin is empty).

paul
  • 475
  • 5
  • 10
  • 2
    Where do you expect the keys strokes you are entering while ping is running are going? If ping is not consuming them, they are queued. When ping is done, they are waiting and in this case bash gets them.... – Stephen Rauch May 21 '17 at 04:46
  • 2
    Although Unix tty drivers conventionally don't deliver input (as opposed to signals) until you type EOL (usually CR/Enter) or EOF (usually control-D), they can be set to 'raw' mode which does not wait, and bash normally does this in order to support command line editing and completion; see the (rather large) section with that title in the bash manual/info. – dave_thompson_085 May 21 '17 at 07:08
  • 1
    @Stephen Rauch In what queue the key strokes are stored? If I am writing a program in C that executes ping, and so when ping terminates, my program gain back control, what function should I call to get what was typed while ping was running (to get data from this queue)? – paul May 21 '17 at 11:54
  • Additional Information. If line editing disabled, then behavior is changing. To turn off line editing: either run the subshell bash --noediting or set +o emacs in the current shell. I have discovered following: typed characters don't appear in the end, but you can remove part of prompt string by quantity typed characters, for example: type 6 characters, while ping is working, then press backspace 6 times ~/Documents/test_dir$ transforming to ~/Documents/tes. – MiniMax May 24 '17 at 13:24

2 Answers2

5

Bash did get your input from its standard input (stdin), which is the terminal.

A terminal can be in one of two modes: raw or cooked (also known as “character mode” and “line mode”, the terms “raw” and “cooked” are mostly used in the Unix world) (the word “cooked” was introduced as a pun to make an opposite to “raw”). In raw mode, the terminal transmits input immediately to the application. In cooked mode, the terminal reads a full line and provides a (very primitive) line edition mechanism, and only transmits the data to the application when the user presses Enter.

Terminals start in cooked mode. Applications that want more control over input, such as bash, set the terminal in raw mode while they're waiting for the user to type a command.

  • 1
    So in my example what happened is that when ping terminates and bash gains back control, bash set the terminal to raw mode, which causes the the tty device line buffer (which contains the string "I typed this while ping was running" to be flushed to bash, and bash will display it on the terminal window? – paul May 22 '17 at 15:28
  • 1
    Also, I don't think that bash sets itself completely to raw mode, but rather it just changes some termios settings like disabling the tty device line buffering and the tty device echoing – paul May 22 '17 at 16:08
  • 1
    @paul Yes, I simplified a bit in my answer. “Raw mode” is one specific terminal setting, there are other settings, which you can set through the stty command. Raw/cooked is one setting, another is echo (either the terminal echoes what you typed to the screen immediately, or it doesn't and it's up to the application to echo stuff if it wants). Raw usually goes with noecho and cooked with echo but applications are free to pick cooked/noecho or raw/echo if they want. – Gilles 'SO- stop being evil' May 22 '17 at 22:50
  • Is my first comment correct? – paul May 22 '17 at 23:11
  • 1
    @paul Yes. While ping runs, the terminal has echo on, and nothing is reading input. Then bash runs, displays a prompt and reads input, and at that point it receives the pre-typed input. Bash handles its own echo so it displays those characters again. By the way, you can check the current terminal modes from another terminal with stty </dev/pts/… — that'll let you know what the terminal modes are at a shell prompt (if you run stty from that terminal, the shell changes modes before running your command). – Gilles 'SO- stop being evil' May 22 '17 at 23:15
  • Unclear, how terminal separates the ping input from the keyboard input. The ping command writes to the terminal, at the same time user presses keys on the keyboard, therefore terminal gets one garbled input, doesn't it? – MiniMax May 24 '17 at 15:10
  • 1
    @MiniMax ping does not read any input from the terminal. ping writes some output to the terminal. If you type something, it is echoed by the terminal, so this is a second source of output to the terminal. What you type and what ping outputs do get mixed. – Gilles 'SO- stop being evil' May 24 '17 at 20:05
  • @Gilles Yes, i am understand it. What I am not understanding is this: how in the end we are getting all typed characters - "I typed this while ping was running". How terminal have could extract this string from mixed ping/keyboard input? All it has, is mixed input from two source, which are writing simultaneously. Or exist something else? – MiniMax May 24 '17 at 21:16
  • 1
    @MiniMax There is no input from ping. Ping writes to the terminal device, that's output, and the terminal displays the output. The terminal device generates input from keyboard events. – Gilles 'SO- stop being evil' May 24 '17 at 21:30
  • I was thought, that terminal also have own input and output conception. If program writes to terminal, it is go to terminal input. And if program reads from terminal, it is go from terminal output. Wrong? :) Because in old, hardware terminals were two states - send and receive. Input and output. I should read more about it. – MiniMax May 24 '17 at 22:07
  • 2
    @MiniMax Think of a terminal device as a pair of pipes. Each pipe carries data in one direction: either from the hardware/emulator to the application (this is called input) or from the application to the hardware/emulator (this is called output). The data from ping goes into the output pipe. It doesn't get mixed with what the user types, that goes through the input pipe and in the opposite direction. – Gilles 'SO- stop being evil' May 24 '17 at 22:14
0

I believe the terminal buffers every line of text received through the keyboard, such that any program which has a file descriptor (i.e. fd0) attached to the terminals device file - won't see any text from the line until the terminal "sends" it - which happens when you press Enter.
(How the line editors of shells get around this - I'm not sure, but they definitely get at the text before you hit Enter)

Also when a shell launches a child process (in this case ping) it goes into in a suspended/waiting state as the child process runs, so even if the terminal wasn't withholding text from it, the shell would ignore it, assuming it was intended for the child process.

So the text you see appearing on the screen, is because the terminal is displaying it, but there is no program capturing it and doing anything with it, until the child exits - and the shell "wakes up' - then the text is sent to the shells line editor. Although I don't think all terminals necessarily do that.

  • 1
    Interactive editors typically switch the terminal driver to "raw" mode. The line-at-a-time behavior you describe is often referred to as "cooked" mode. – tripleee May 21 '17 at 09:10
  • @tripleee thanks that explains how shells can get the individual chars – the_velour_fog May 21 '17 at 09:13