My Weblog
18 10 2004

Mon, 18 Oct 2004

Red Hat Gets Terminal Settings Wrong
Okay, I don't really mind if Red Hat decides to do things differently than Debian, but I do mind if they way they do things breaks the standard, accepted way. In this case, I'm referring to the way that Red Hat configures the terminal backspace character.

Now, Red Hat configures the Backspace key to send Control-H, which is the classic, historical setting for it. However, this interferes with Emacs, which uses Control-H to start the help system. The modern (and IMHO correct) setting is to use ASCII DEL (^?, value 127) for Backspace. Debian follows this method as detailed in the Keyboard Configuration section of the Debian Policy Manual. This allows Backspace, Delete, and Control-H to be interpreted independently of one another.

The fact that Red Hat chooses to use the old configuration bothers me, but I can deal with that. What I can't deal with is that Red Hat puts the following code into /etc/bashrc:


    if [ -x /usr/bin/tput ]; then
      if [ "x`tput kbs`" != "x" ]; then # We can't do this with "dumb" terminal
        stty erase `tput kbs`
      elif [ -x /usr/bin/wc ]; then
        if [ "`tput kbs|wc -c `" -gt 0 ]; then # We can't do this with "dumb" terminal
          stty erase `tput kbs`
        fi
      fi
    fi
This sets the tty erase character to whatever is specified as the backspace code in the terminfo database. Whoever wrote this is trying to work around terminals that send one character with the backspace key, yet whose tty device is set to use the other character. This may work with terminals on the local machine, or with remote logins to machines that use the same erase character, but it breaks backspace on other systems. The erase character is correctly set by telnetd and sshd to match the erase character used on the client, and this code forces it to be whatever character the server uses. The program being run must generate output that is correctly displayed on the user's terminal, which means that the server must use the terminal settings the client wants, not the other way around.

It is also unreasonable to consider this a fix for local terminals whose erase character and Backspace binding don't match up. If this is the case, then there is a configuration problem and it should be corrected by changing the configuration for that specific terminal or emulator (i.e. by changing the backarrowKey, ptyInitialErase, or backarrowKeyIsErase resources for xterm). Writing a shell script to work around the problem doesn't fix it, it just hides the problem.

A possible solution would be to run stty erase ^? explicitly in my shell startup script. This is unacceptable however, since it 1) doesn't change the fact that Red Hat's default setup is broken and 2) some of my accounts are used by several other people who use different distros, and setting the erase character explicitly might break their terminal settings.

To take one step toward solving this problem, remove above code from /etc/bashrc. It's a nasty kludge written solely to cover up the fact that Red Hat can't figure out how to change X resources and terminal emulator settings to match their termcap and terminfo databases.

Update: I have noticed that the delete key is also broken. This isn't that big of a deal, it's just annoying. On some machines the delete key (in bash at least) has the same effect as the backspace key (delete previous character) and on others it prints a tilde (and probably some control characters). As long as it doesn't break things for anyone else, I'm fine with it. I use backspace a lot more than delete anyway :-)

Actually, this appears to only be a problem when running a remote screen session on some redhat boxes. Remote ssh sessions work fine. For some reason, screen on these machines doesn't set the kD termcap capability correctly. It would be awesome if the TERMCAP variable was preserved for remote logins. :-/

Update (2004-10-18): I've discovered another stupid RedHat BS/DEL 'fix'. RedHat provides a global configuration file for GNU screen, which is an application that I depend on everyday. In this /etc/screenrc file, there is the following code:
# This makes screen treat backspaces '^?' as
# deletes. There should be a fix in the code
# for the way termcap inheritance works,
# but I dont know where to put it, and this works.
bindkey -d -k kb stuff "\010"
This forces the backspace key to send ^H, which is WRONG!!! Even if you think that ^H is the correct character for backspace (which it isn't), it is not correct to force screen to send ^H for backspace. If my kb/kbs entry is defined as ^?, this code makes it absolutely impossible to send ^?, since screen will always translate it to ^H. I don't know what the heck this is supposed to fix. If my kb/kbs is defined as ^H to begin with, this does nothing and is therefore useless. If the kb/kbs entry is ^?, now it becomes impossible to send DEL to the application. This will break all apps that use the stty erase character to determine what backspace should be if the erase character isn't ^H. Now another fix is required, like the brain-dead 'stty erase `tput kbs`' hack described above. The only way to solve the problem is as follows:

  1. Remove all hacks from both system-wide and personal config files that change stty erase, the kb/kbs definitions, or the mapping for the backspace key
  2. Choose a system-wide backspace character (either ^H or ^?)
  3. Change terminfo/termcap entries so that kb/kbs is set to that character
  4. Make sure all terminal emulators send this character when the backspace key is pressed. This should be set system-wide
  5. Make sure all terminal emulators set the erase character to this value. This should be set system-wide
  6. Configure applications system-wide to use the stty erase character to determine what the backspace key sends
  7. If that is not possible, configure the application to accept both ^H and ^? for backspace
  8. If that is not possible, make sure the apps use termcap/terminfo to determine the backspace character
  9. If that is not possible, then the app is broken and must be fixed.


If you do these steps, backspace will only be broken under the following conditions:


In short, the stty erase character should be treated as correct at all times, and termcap/terminfo should match it. The backspace key should also match it. Any other configuration will have more problems than this one. If someone tells you otherwise, they're stupid. Ignore them.

posted at: 11:46 | path: /computers/linux/redhat | permanent link to this entry