13

Perhaps there are already answers out there that indirectly answer my question, but I've read many of them and haven't yet found a satisfactory answer to this discrepancy.

The original meaning of carriage return comes from old teleprinters: it meant to move the print head to the left in the current line. If you kept writing in the current line, you would be overwriting what was already written. Nowadays, we can specify this behaviour with the text symbol \r, which is typed explicitly within a string. For example, in Python you can do print('hello\rgoodbye'), and in the terminal you can do echo $'hello\rgoodbye', and in both cases you will only see goodbye.

In contrast, a pseudo-carriage return can also be inserted interactively with the ASCII control character ^M (typed with Ctrl-M or with Enter). I call it pseudo-carriage return because even though it is widely called carriage return, surprisingly it doesn't insert \r, but rather it inserts \n, which is the symbol for a new line.

So interactively typing hello, then Ctrl-M, then goodbye, surprisingly doesn't achieve the equivalent of hello\rgoodbye, but rather the equivalent of hello\ngoodbye.

Isn't this very inconsistent? What is the rationale behind this?

2
  • 1
    By chance this fresh answer of mine can advance your research, I believe. May 10, 2021 at 12:58
  • 1
    I've used Model 33, Model 35, and Model 35ASR TeleTypes. Control-M, "\r", Carriage Return returned the print head to the left margin. Control-J, "\n", Linefeed advanced the paper 1 line. Unix/Linux decided on Control-J for End-of-line. Some programs convert \r for you.
    – waltinator
    May 10, 2021 at 22:51

1 Answer 1

20

This is the result of the terminal’s input handling: by default, the terminal device driver (software in the kernel of your operating system to handle input from the terminal, not the terminal itself) converts CtrlM to CtrlJ. You can see this by running

od -t x1

and then entering both characters:

$ od -t x1
^M
^J
^D
0000000 0a 0a
0000002

(You won’t see ^M etc. on screen.)

Thus when you type CtrlM, whatever program is processing your input doesn’t see a carriage return, it sees a line feed instead.

This can be configured with stty icrnl. See Understanding Return, Enter, and stty icrlf for a similar question.

3
  • Hi, thanks a lot for your answer. If I understood correctly, there was some divergence such that many Unix programs and the C language started to use line feed ^J or \n, whereas terminals went their own way and started to interpret Enter as carriage return ^M or \r. At some point, Unix and C became very widespread, so terminals had to somehow revert back to be more compatible with Unix and C. The easiest way to do this was to add the layer of interpretation of stty icrnl, and convert ^M to ^J. Is this a roughly correct account of the historical development?
    – mgarort
    May 10, 2021 at 13:17
  • 3
    I’m not sure when icrnl was added to termio or termios, but Unix always had a separation between its internal expectations and how terminals worked (inherited from Multics); I’m not sure things diverged as such, terminals were already varied when Unix was created. This related answer I wrote on Retro.SE goes into some of the history and provides pointers to more detailed explanations. May 10, 2021 at 15:52
  • This is an interesting answer, because it seems about the opposite of the way things work on Windows. There the Enter key is converted to \r\n, and the C runtime library will convert that back to \n if you open a file in "text" mode. May 11, 2021 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.