Skip to main content

First, Bash reads and writes the x, outputting it to the terminal. Then it reads the backspace (character code 0177 in octal or 127 in decimal), and outputs the backspace character (octal 010, decimal 8(*)) which moves the cursor back and outputs the control sequencecontrol sequence for clearing the end of the line, <ESC>[K. The last \4 is the Ctrl-D, which is used by Bash to exit the program.

First, Bash reads and writes the x, outputting it to the terminal. Then it reads the backspace (character code 0177 in octal or 127 in decimal), and outputs the backspace character (octal 010, decimal 8(*)) which moves the cursor back and outputs the control sequence for clearing the end of the line, <ESC>[K. The last \4 is the Ctrl-D, which is used by Bash to exit the program.

First, Bash reads and writes the x, outputting it to the terminal. Then it reads the backspace (character code 0177 in octal or 127 in decimal), and outputs the backspace character (octal 010, decimal 8(*)) which moves the cursor back and outputs the control sequence for clearing the end of the line, <ESC>[K. The last \4 is the Ctrl-D, which is used by Bash to exit the program.

added 1179 characters in body
Source Link
ilkkachu
  • 148.1k
  • 16
  • 268
  • 441

Well, what happens when you type depends on what mode the terminal is in. Roughly, it can be in the usual "cooked" mode where the terminal itself provides elementary line editing (handles backspaces); or in a "raw" mode, where all keypresses go to the application, and it's up to the application to decide what to do with them, and what to output in response. Cooked mode usually goes along with "local echo" where the terminal (local to the user) prints out the characters as they are typed. In raw mode, the application usually takes care of echoing the typed characters, to have full control over what's visible.

See e.g. this question for discussion on the terminal modes: What’s the difference between a “raw” and a “cooked” device driver?

If you run e.g. cat, the terminal will likelybe in cooked mode (the default) and handle the line editing, and hitting. Hitting for example x, <backspace>, Ctrl-DxBackspaceCtrl-D will result in cat just reading the empty input, signalling the end of input . You can check this with strace. But if you run an interactive Bash shell instead, it will handle the backspace by itself, and output what it considers appropriate to do what the user expects, i.e. wipe one character.

 

Run:Here's part of the output for strace -etrace=read,write -obash.trace bash, and enter x<backspace><Ctrl-D>. Nowafter entering the mentioned sequence bash.trace will show these system callsxBackspaceCtrl-D:

First, Bash reads and writes the x, thenoutputting it to the terminal. Then it reads the backspace (character code 0177 in octal or 127 in decimal), and outputs the backspace character (octal 10010, decimal 8(*)) which moves the cursor back and outputs the control sequence for clearing the end of the line, <ESC>[K. The last \4 is the Ctrl-D, which is used by Bash to exit the program.

(* in input, Ctrl-H would have the decimal character code 8. Backspace is either the same or 127 as here, depending again on how the terminal is set up.)

In comparison, the same experiment with cat only shows a single read of zero bytes, the "end of file" condition. End of file can mean either a connected pipe or socket being closed, an actual end of file, or Ctrl-D being received from a terminal in cooked mode:

read(0, "", 131072)                     = 0

In particular, cat doesn't see the x, nor the backspace, nor the actual code for Ctrl-D: they're are handled by the terminal. Which might be the virtual terminal driver in the kernel; an actual physical terminal over a serial connection or such; or a terminal emulator like xterm either running on the same machine or at the remote end of an SSH connection. It doesn't matter for the userspace software.

Well, what happens when you type depends on what mode the terminal is in. Roughly, it can be in the usual mode where the terminal itself provides elementary line editing (handles backspaces); or in a "raw" mode, where all keypresses go to the application, and it's up to the application to decide what to do with them, and what to output in response.

If you run e.g. cat, the terminal will likely handle the line editing, and hitting for example x, <backspace>, Ctrl-D will result in cat just reading the empty input, signalling the end of input . You can check this with strace. But if you run an interactive Bash shell instead, it will handle the backspace by itself, and output what it considers appropriate to do what the user expects, i.e. wipe one character.

Run: strace -etrace=read,write -obash.trace bash, and enter x<backspace><Ctrl-D>. Now bash.trace will show these system calls:

First, Bash reads and writes the x, then it reads the backspace (character code 0177 in octal or 127 in decimal), and outputs the backspace (octal 10, decimal 8) which moves the cursor back and outputs the control sequence for clearing the end of the line, <ESC>[K. The last \4 is the Ctrl-D.

Well, what happens when you type depends on what mode the terminal is in. Roughly, it can be in the usual "cooked" mode where the terminal itself provides elementary line editing (handles backspaces); or in a "raw" mode, where all keypresses go to the application, and it's up to the application to decide what to do with them, and what to output in response. Cooked mode usually goes along with "local echo" where the terminal (local to the user) prints out the characters as they are typed. In raw mode, the application usually takes care of echoing the typed characters, to have full control over what's visible.

See e.g. this question for discussion on the terminal modes: What’s the difference between a “raw” and a “cooked” device driver?

If you run e.g. cat, the terminal will be in cooked mode (the default) and handle the line editing. Hitting for example xBackspaceCtrl-D will result in cat just reading the empty input, signalling the end of input . You can check this with strace. But if you run an interactive Bash shell instead, it will handle the backspace by itself, and output what it considers appropriate to do what the user expects, i.e. wipe one character.

 

Here's part of the output for strace -etrace=read,write -obash.trace bash, after entering the mentioned sequence xBackspaceCtrl-D:

First, Bash reads and writes the x, outputting it to the terminal. Then it reads the backspace (character code 0177 in octal or 127 in decimal), and outputs the backspace character (octal 010, decimal 8(*)) which moves the cursor back and outputs the control sequence for clearing the end of the line, <ESC>[K. The last \4 is the Ctrl-D, which is used by Bash to exit the program.

(* in input, Ctrl-H would have the decimal character code 8. Backspace is either the same or 127 as here, depending again on how the terminal is set up.)

In comparison, the same experiment with cat only shows a single read of zero bytes, the "end of file" condition. End of file can mean either a connected pipe or socket being closed, an actual end of file, or Ctrl-D being received from a terminal in cooked mode:

read(0, "", 131072)                     = 0

In particular, cat doesn't see the x, nor the backspace, nor the actual code for Ctrl-D: they're are handled by the terminal. Which might be the virtual terminal driver in the kernel; an actual physical terminal over a serial connection or such; or a terminal emulator like xterm either running on the same machine or at the remote end of an SSH connection. It doesn't matter for the userspace software.

Source Link
ilkkachu
  • 148.1k
  • 16
  • 268
  • 441

First, the entire thing prints only after the 5 second sleep so from that I deduced the output from the kernel to the terminal is line buffered.

No, the output from your program to the kernel is line-buffered. That's the default behaviour for stdio when stdout is a terminal. Add the call setbuf(stdout, NULL) to turn output buffering off for stdout. See setbuf(3).

  1. Since the \b\b goes back two spaces, to the position of l then similar to how l was replaced by h, the o should have been replaced by \n. Why wasn't it?

Because the newline character just moves the cursor (and scrolls the screen), it doesn't print as a visible character that would take up the place of a glyph on the terminal. If we assume it would take the place of a glyph, what would it look like?

  1. if I input something into the very same program, and press Backspace, it erases the last character, but not for the output. Why?

Well, what happens when you type depends on what mode the terminal is in. Roughly, it can be in the usual mode where the terminal itself provides elementary line editing (handles backspaces); or in a "raw" mode, where all keypresses go to the application, and it's up to the application to decide what to do with them, and what to output in response.

If you run e.g. cat, the terminal will likely handle the line editing, and hitting for example x, <backspace>, Ctrl-D will result in cat just reading the empty input, signalling the end of input . You can check this with strace. But if you run an interactive Bash shell instead, it will handle the backspace by itself, and output what it considers appropriate to do what the user expects, i.e. wipe one character.

Run: strace -etrace=read,write -obash.trace bash, and enter x<backspace><Ctrl-D>. Now bash.trace will show these system calls:

read(0, "x", 1)                         = 1
write(2, "x", 1)                        = 1
read(0, "\177", 1)                      = 1
write(2, "\10\33[K", 4)                 = 4
read(0, "\4", 1)                        = 1

First, Bash reads and writes the x, then it reads the backspace (character code 0177 in octal or 127 in decimal), and outputs the backspace (octal 10, decimal 8) which moves the cursor back and outputs the control sequence for clearing the end of the line, <ESC>[K. The last \4 is the Ctrl-D.