Hacker News
The TTY Demystified (2008)
20after4
|next
[-]
teddyh
|next
|previous
[-]
JdeBP
|root
|parent
[-]
It's an interesting question for CIS URLs whether a url-path with an empty final component, that duplicates a url-path with an actual 'index' component (of some kind), is to be taken as the primary or the secondary form. When a site has 'index.php', 'index.html', 'index.gopher', 'index.gemini', and others, the question is whether the container is the same as the index file.
Joker_vD
|previous
[-]
And of course, the concerns of the serial line driver are thrown into the mix too, for the added entertainment.
jonnyasmar
|root
|parent
[-]
- SIGWINCH doesn't always fire on initial spawn — the TUI starts up thinking it has 0 columns and emits garbage until the first real resize. Fix: synthesize an ioctl(TIOCSWINSZ) before the first read, and re-send on focus events. - xterm.js negotiates dimensions with the PTY backend over a non-obvious dance; off-by-one in the cell math wraps long prompts in the wrong place every time. - Tools that detect "am I in a TTY" via isatty() behave differently from tools that stat() stdin; a few agents fall through to non-TUI mode if the PTY's mode bits aren't quite right.
None of that is reflected in the abstract "PTY is a virtual terminal" mental model. The kernel/terminal/application split is a leaky abstraction in practice — you only find out by hosting one inside the other.
Joker_vD
|root
|parent
[-]
Wait, how do you even use fstat's output to find out if the file is a tty?
Although in my experience the "funniest" part is deciding whether to use isatty() on stdin or on stdout. I mean, there is no much point enabling line editing/tab completion if stdin is a pipe/regular file, right?
jonnyasmar
|root
|parent
[-]
The stdin-vs-stdout split is where I see the most actual "is this a TTY" mistakes though. Tools that emit JSON-on-stdout-when-piped and TUI-when-not work fine until something stuffs them into a PTY with piped stdin — then they're in TUI mode but can't actually read the user input format they expect.
mpyne
|root
|parent
[-]
Stuff like this is why a build script I used to maintain would redirect stdin from /dev/null when running commands that were intended to be non-interactive. You only need one script to hang forever waiting for a user to type in a password to decide that you'll force the issue going forward.
jonnyasmar
|root
|parent
[-]
The really fun version is when a command writes the prompt to stderr (so it shows up in the build log!) and then reads from a stdin you didn't realize was still open. Took embarrassingly long to track down.