Force telnet / ssh to use crtl-H for backspace

20,990

Solution 1

I finally found an answer in Anne Baretta's Linux Keyboard Hall of Shame... it seems that changing key mappings in xterm / rxvt does no good for telnet.

I validated this when I sniffed the telnet connection. First I sniffed the telnet session and saw that Backspace sent 0x7f to the host. Next I intentionally broke Backspace in rxvt using stty erase $ (thus mapping my Backspace to the dollar sign in rxvt). After doing this, I had to hit $ to backspace in rxvt, but telnet still sent 0x7f when I used Backspace on the remote host.

SOLUTION

Create a script called kbdfix (below), and make it executable with 755 permissions; you will need the tclsh and expect packages loaded from your distribution archives.

#!/usr/bin/expect

#Name this file as kbdfix and make it executable in your path
eval spawn -noecho $argv

interact {
 \177        {send "\010"}
 "\033\[3~"  {send "\177"}
}

Now to connect to the broken hosts, I type kbdfix telnet 192.168.12.117 2006, and Backspace works.

Note for anyone confused by 2006 above... that is the TCP port that the Cisco term server uses for the serial connection to the console of the broken device (in this case, a Brocade FCX switch).

If you are merely telnetting to a device that doesn't like Backspace, you would use kbdfix telnet <addr_of_the_broken_device>. I am also using this with ssh when I ssh to a DLink DGS-3200 Ethernet switch that has similar issues; the syntax is kbdfix ssh 172.16.1.26.

Solution 2

Programs are supposed to query the terminal settings to find out what the backspace character is (^h and ^?, i.e. \010 and \177, are the two choices out there). Use stty erase '^h' or stty erase '^?' to declare what your terminal sends.

If you log in remotely (with telnet, rsh or ssh) inside the terminal, note that you must run stty on the application side. stty doesn't tell the terminal to do anything different, it informs the local terminal driver (i.e. the part that interfaces with applications running in the terminal) about the terminal (historically a physical object, now a terminal emulator) settings. Similarly, if you run Screen or similar terminal-in-terminal software, you need to run stty in each screen window (but usually Screen can be configured to do the right thing from its configuration file, if it doesn't work out of the box).

The difference in behavior that you observe from netcat vs. telnet is due to the way the terminal is used: * In netcat, the terminal is in line-by-line mode (also called “cooked mode”). You edit a line (using the local terminal's built-in edition feature, and so in particular the local stty settings), then send it in its final state to the remote host. * In telnet, the (local) terminal is in character-by-character mode (also called “raw mode”). Every keystroke goes directly to telnet which relays it immediately to the remote system. You are dependent on the remote system's line edition features.

There are broken programs out there that don't care about the terminal settings. Looks like you've encountered one of them. Your best bet is to change your terminal's configuration. The same goes if you need to communicate with a device over a remote protocol such as telnet or SSH and the device is not configurable.

With xterm, it's easy: there's a setting to toggle the character sent by the BackSpace key at run-time. From the left button menu, toggle “Delete is DEL”. Programmatically, send the escape sequence \e[?67h to have BackSpace send ^h, or \e[?67l to have BackSpace send ^?. The corresponding resource is XTerm.backarrowKeyIsErase. Other terminal emulators may or may not have a similar interface feature or support the escape sequence.

Many terminal emulators send one of ^h or ^? when you press BackSpace, and the other character when you press Ctrl+BackSpace. This can be useful in a pinch.

Note that showkeys and friends are only relevant on the Linux console, not within X.

Solution 3

Backspace and Control-H were designed to be the same thing but nowadays, especially on Linux, you often have backspace sending delete and delete sending some odd escape sequence.

In any case and as far as I know, telnet or the TERM variable shouldn't change what backspace sends, this is usually a terminal emulator configuration feature.

Share:
20,990

Related videos on Youtube

Mike Pennington
Author by

Mike Pennington

Updated on September 18, 2022

Comments

  • Mike Pennington
    Mike Pennington over 1 year

    I have some devices connected to a Cisco serial term server; many work fine when I telnet directly to the port on the Cisco. However, I have a few stubborn devices that will not use Backspace as it is mapped in telnet by default.

    In case it matters, I telnet from rxvt under Debian squeeze (in an X Window). TERM is set to rxvt, but it doesn't matter whether I use vt100, vt101, or xterm... changing TERM has no effect. I started down the road of changing TERM based on what I saw in an old Kermit FAQ. FWIW, stty erase ^h and stty erase ^? don't work either.

    I have noticed that Backspace works correctly on these devices if I use a raw TCP socket from netcat... i.e. nc 192.168.12.117 2006; however, then I run into other issues with passwords not hidden or terminal paging.

    How can I selectively force telnet and ssh to map Backspace to CtrlH for these devices? Also, what criteria should I use to evaluate whether this is a bug in the device?

    EDIT

    In case it matters, this is the output from showkey -a for the keys in question... ^? corresponds to Backspace and ^H is CtrlH. It seems like I should be getting close when I look at The Linux Keyboard and Console Howto, but I can't seem to decipher what I can do to change this. I have tried various incantations with loadkeys to no effect.

    [mpenning@hotcoffee docs]$ sudo showkey -a
    
    Press any keys - Ctrl-D will terminate this program
    
    ^?      127 0177 0x7f
    ^H        8 0010 0x08
    

    I am also including relevant output from dumpkeys as well... this is the current mapping in my system (which doesn't work on some devices in question). If I could figure out how to get Backspace to do the same thing as CtrlH, I would have a solution.

    [mpenning@hotcoffee docs]$ sudo dumpkeys | grep -Ei "backspace|127"
    keycode   8 = BackSpace        ampersand        braceleft       
    keycode  14 = BackSpace        Delete          
            control keycode  14 = BackSpace       
    keycode 127 =
    [mpenning@hotcoffee docs]$
    
    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' about 13 years
      Have you tried ssty erase '^?'? If the devices insist on a C-h, it's not telnet's call, it's the terminal (emulator)'s.
    • Mike Pennington
      Mike Pennington about 13 years
      @Gilles your comment is actually not correct, see my answer below
  • jlliagre
    jlliagre about 13 years
    Your question is based on the assumption telnet is doing specific processing of the backspace key which I believe is wrong. I should have put that as a comment instead of an answer indeed.
  • Mike Pennington
    Mike Pennington about 13 years
    AFAICT, telnet pays no attention to local terminal mappings of the keyboard. Anne Barreta's notes about the keyboard and telnet
  • jlliagre
    jlliagre about 13 years
    I'm afraid you are misunderstanding what stty does.
  • jlliagre
    jlliagre about 13 years
    stty erase $ doesn't map the "backspace" key to "$", it tells the tty driver that in order to erase a character, the "$" key need to be used. When you run telnet, you are in raw mode so this setting is ignored. A simple solution would be to configure your terminal emulator to send ^H for backspace, as god intended, another one is using your hack which translates these character on the fly using expect.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 13 years
    @Mike: I think you're still confused about something (which I admit neither jlliagre nor I mentioned explicitly; I've updated my answer). stty needs to run on the application side. I highly doubt telnet is translating input characters or that you need to use script; just running stty on the remote machine will probably do the trick.
  • Mike Pennington
    Mike Pennington about 13 years
    @Gilles, the remote machine is a network device, it does not have stty.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 13 years
    @Mike: Oh, I see. Then your issue isn't with telnet (it's just the messenger), it's with the remote device. (Your blaming telnet is what was confusing me, and I think jlliagre.) Then using some intermediate software that performs the translation, such as expect or screen, is a reasonable approach.
  • Mike Pennington
    Mike Pennington about 13 years
    @Gilles, the reason I was trying to modify telnet's behavior is because it seemed like telnet was causing a difference in this particular case. netcat was not having an issue with backspace (which is something I will track down when I have some spare moments). I need to figure out whether the device (a Brocade switch) has a bug, or this is simply a nasty "feature"
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 13 years
    @Mike: When you use netcat, your terminal is in cooked mode: you write a line, editing it locally, and Enter sends it. When you use telnet, your terminal is in raw mode: each character is sent immediately to the application. See e.g. the beginning of this page, or this Wikipedia article.