> The terminal just happens to invisibly turn \n into \r\n.
No, it was actually done by the Unixen itself, in the part of the kernel that handled ttys: it convert '\n' to '\r\n' on writes to ttys, and '\r' to '\n' on reads from ttys. Linux only recently have moved this functionality out into the user-land layer.
Hmmm, I could swear I have read about moving line discipline out of the kernel in some LWN article but apparently no, it never happened (although it probably should've, there is no much reason to perform mapping of NL to CR-NL in the privilleged mode). Maybe I've confused it with what happened on the Windows side of things? They moved almost all of the console infrastructure out of the kernel recently and into the user space, and that definitely has happened.
I suspect Linux actually can't move it to user space. It would break binary compatibility with all user space code that sets OPOST via the ioctl. They can't hide it in a libc either.
No, it was actually done by the Unixen itself, in the part of the kernel that handled ttys: it convert '\n' to '\r\n' on writes to ttys, and '\r' to '\n' on reads from ttys. Linux only recently have moved this functionality out into the user-land layer.