0

According to POSIX General Terminal Interface about carriage return processing:

CR

Special character on input, which is recognized if the ICANON flag is set; it is the carriage-return character. When ICANON and ICRNL are set and IGNCR is not set, this character shall be translated into an NL, and shall have the same effect as an NL character.

However, it appears that in linux, the CR is converted to a LF, even when in non canonical mode.

This can be seen by running this code and typing in a, enter, b, enter.

#include <unistd.h>
#include <termios.h>

int main() {
    struct termios t;
    tcgetattr(STDIN_FILENO, &t);
    // t.c_iflag &= ~(ICRNL); // Turn off ICRNL
    t.c_lflag &= ~(ECHO | ICANON); // Turn off ECHO and ICANON
    tcsetattr(STDIN_FILENO, TCSANOW, &t);

    char c;
    while (read(STDIN_FILENO, &c, 1)) write(STDOUT_FILENO, &c, 1);
}

The output is

a
b

When ICRNL is turned off by uncommenting the line of code, pressing enter after typing in a changes the column to zero and keeps the row the same, so that when b is pressed, the b overwrites the a. This is the expected behavior since the CR isn't converted to a LF by unsetting ICRNL. However I would also expect this if ICRNL is set and ICANON is unset.

freewill
  • 93
  • 4

1 Answers1

1

According to POSIX General Terminal Interface about carriage return processing:
...
However, it appears that in [linux][2], the CR is converted to a LF, even when in non canonical mode.

Correct (for input processing), and that is clearly stated in the Linux man page for termios, where there's a different and simpler specification from POSIX for the ICRNL attribute:

       ICRNL  Translate carriage return to newline on input (unless  IGNCR  is
          set).

This can be seen by running this code and typing in a, enter, b, enter.

Linux does not adhere to POSIX regarding this ICRNL attribute, and it is clearly documented. So you have not discovered a bug.

When ICRNL is turned off by uncommenting the line of code, pressing enter after typing in a changes the column to zero and keeps the row the same, so that when b is pressed, the b overwrites the a. This is the expected behavior since the CR isn't converted to a LF by unsetting ICRNL.

Correct (assuming that OCRNL is disabled, which is typical).

However I would also expect this if ICRNL is set and ICANON is unset.

No, your expectation is incorrect. When ICRNL is enabled and ICANON is disabled, the Enter generates a \r input character, but termios will translate the \r (carriage return) to \n (newline). The \n is the character that will be in the user's buffer on return from a read() syscall.


Note that your methodology is flawed in trying to demonstrate this noncompliance (i.e. your program does not really do what you think it should do).
Rather than read and write (where both syscalls utilize termios), a more revealing test would capture the received characters to a log file.
OR, at the very least, disable the OPOST attribute, so that all termios output processing is disabled (i.e. you need to inhibit the conversion of "NL to CR-NL on output").
Also, you need to restore all of the termios attributes to the same state for each test to assure consistent results.

sawdust
  • 16,103
  • 3
  • 40
  • 50
  • Thanks for your answer. I indeed incorrectly expected linux to be POSIX compliant. The thing I forgot to mention, is that macOS behaves in the same way, even though it is POSIX compliant. This led me to believe I had somehow misinterpreted the POSIX docs. As for flawed methodology, I was running `reset` in between tests; which I perhaps should have mentioned. – freewill Aug 14 '22 at 09:54