I recently acquired an old Heathkit dumb terminal, and I would like to get it working with the colemak keyboard layout. Because the terminal sends ascii codes directly over serial, I don't believe anything like loadkeys will work. (If there is a simple solution to changing the layout, I'd love to know.)

My current plan is to filter every byte that is received or transmitted in a simple piece of software. There are also a few command line programs that still use incompatible escape codes (despite TERM being set correctly) which I would like to manually filter out as well.

Essentially I'd like to create a program that sits between agetty and the terminal and allows me to filter bytes manually as they are sent or received.

The filtering of bytes is simple enough, but I'm unsure how to create an interface to agetty that can do this. Will I need to create my own device using mknod?

(I've also considered using a microcontroller or raspberry pi sitting between the terminal and linux machine to read bytes in and write the new bytes out. This solution would be clunky and I'd like to avoid it if possible.)

Any advice on where to look/read would be extremely helpful.

1 Answer 1


Some "dumb" terminals have a built-in setup menu, sort of like "BIOS settings" for a terminal. Those settings will usually include a selection of keyboard layouts. But a Heathkit terminal (which model?) may be too old-school for that. Even if the terminal has a mechanism for switching keyboard layouts, it is unlikely to offer a Colemak layout, as that layout was developed in 2006 or so.

agetty - or any getty process - is started by init (or whatever is PID #1) to initialize the TTY device and send the appropriate reset codes to the terminal, display a login prompt and receive the username. Once getty has done that, it will exec() a login process to get a password from the user.

But note: that is just exec(), not a fork()+exec(). So once its job in starting the session is done, the getty process will be gone, replaced by login and eventually by the user's shell. Once the user's session ends, init will detect that there is no longer any process on that TTY device, and will start another instance of getty to start the process over.

So, if you want to keep filtering any characters coming in from the terminal, you'll need something that stays in place for the entire session. Once the user's session ends, you may want your process to die away, so you can have init start a fresh instance for the next login session.

You'll also need to duplicate the TTY device interface, as the real serial port TTY device will be occupied by your program while it's doing its job. Trying to have two separate programs reading the same serial port simultaneously will only lead to grief. Fortunately, you don't have to do it from scratch: duplicating the TTY interface is exactly what the pseudo-TTYs are for. See man 3 openpty.

You would need to do the initialization of the device settings and sending the appropriate reset codes to the terminal just like agetty does, but then your program would present the login prompt and initialize its character filtering loop. Once it has received a response to the username prompt, it should request a pseudo-TTY, fork()+exec() a login program connected to the "slave" side of that pseudo-TTY, and start passing filtered characters from the real terminal into the master side of that pseudo-TTY and unfiltered output from the pseudo-TTY back to the real terminal.

Your program should not waste CPU cycles by actively waiting for data from the TTY devices, but instead use the select(2) or poll(2) system calls to efficiently wait for data to process.

Reading the source code of the ttysnoop package might be useful, as it needs to do something similar to record the TTY session.

  • It's an H19. It's old enough that it doesn't have any settings other than some dip switches. These all look like great places to start. Thanks a bunch.
    – runrin
    Jun 13, 2022 at 6:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .