4

I understand that backspace might now work in an ssh session if TERM is set incorrectly. But strangely, I have a server where TERM is set correctly, but backspace does not work until I manually set TERM=xterm in the shell (which should be redundant). See here:

~ ] ssh [email protected]
root 192.168.10.40 / # echo $0
-bash
root 192.168.10.40 / # echo $TERM
xterm-256color
root 192.168.10.40 / #     # backspace does not work :(
root 192.168.10.40 / # 
root 192.168.10.40 / # TERM=xterm-256color
root 192.168.10.40 / # # now backspace works!!
root 192.168.10.40 / # logout

I would say about 90% of the time, backspace does not work until I run TERM=xterm, and 10% of the time, I don't need to run the TERM= command because backspace is already working. I've compared the output of env for each case, and they are identical (aside from SSH_CLIENT and SSH_CONNECTION where only the client side port has changed)

Any idea what may cause this behavior, or what a workaround might be?


Response to comments

I am using OpenSSH_6.8p1, BoringSSL from https://android.googlesource.com/platform/external/openssh, and I am running GNU bash, version 4.3.42(1)-release (arm-android-eabi) from https://github.com/CyanogenMod/android_external_bash.git

stty -a shows no different before and after setting XTERM. Output is:

speed 38400 baud; rows 102; columns 319; line = 2;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

bind -p|egrep 'delete|rubout|kill' also shows no different before and after setting XTERM. Output is:

"\C-h": backward-delete-char
"\C-?": backward-delete-char
"\C-x\C-?": backward-kill-line
"\e\C-h": backward-kill-word
"\e\C-?": backward-kill-word
# copy-region-as-kill (not bound)
"\C-d": delete-char
"\e[3~": delete-char
# delete-char-or-list (not bound)
"\e\\": delete-horizontal-space
# forward-backward-delete-char (not bound)
"\C-k": kill-line
# kill-region (not bound)
# kill-whole-line (not bound)
"\ed": kill-word
# shell-backward-kill-word (not bound)
# shell-kill-word (not bound)
# unix-filename-rubout (not bound)
"\C-w": unix-word-rubout
# vi-delete (not bound)
# vi-delete-to (not bound)
# vi-overstrike-delete (not bound)
# vi-rubout (not bound)

Interestingly, if I source my bashrc, my backspace starts working again. I know the bashrc is being sourced on login though because that is the only place where I set my Ps1 value

6
  • what's the server? SSH server name and version?
    – Jakuje
    Sep 29, 2016 at 19:34
  • your shell may run a script to update the prompt, and in that script the TERM value might be used to update the terminal settings. Sep 29, 2016 at 20:42
  • Could you do "stty -a" before and after the assignment, and see if there is any difference? Just a try to debug. Sep 29, 2016 at 21:08
  • One other thing that will help people: The outputs of bind -p|egrep 'delete|rubout|kill' run before and afterwards.
    – JdeBP
    Sep 30, 2016 at 9:43
  • An application could be initializing the terminal, sending \033[?67h (or 033[?67l) aka DECBKM. If you check what is actually sent (use cat -v to make the key readable, using ^V to help), does that change? Sep 30, 2016 at 17:48

1 Answer 1

1

Seems like readline/terminal interaction, start by checking your .inputrc, /etc/inputrc, /etc/default/login, INPUTRC environment variable during the login process, and then readline bindings (via bind -q backward-delete-char).

No harm double checking what's in the client (ssh_config) SendEnv and server (sshd_config AcceptEnv) directives too, if anything (though TERM is not sent from client to server this way in OpenSSH, the client always includes the TERM value in the session setup, and the server set TERM from that). The occasional presence of TERMINFO or TERMCAP in the environment is the only thing I can think of to explain the intermittent nature of this.

Readline applies "rubout" to whatever the terminal declares its "erase" is, and rubout is what readline invokes via backward-delete-char.

TERM is one of the special variables that bash monitors, when it's set (independent of whether it changes) bash resets the terminal:

/* What to do just after one of the TERMxxx variables has changed.
   If we are an interactive shell, then try to reset the terminal
   information in readline. */
void
sv_terminal (name)
     char *name;
{
  if (interactive_shell && no_line_editing == 0)
    rl_reset_terminal (get_string_value ("TERM"));
}

(where "TERMxxx" means TERM, TERMCAP and TERMINFO) so this explains why simply setting TERM to its current value actually performs an action.

If you cannot track it down, adding "TERM=${TERM}" at the end of your .profile/.bashrc might be a work-around.

As a last resort you could also try some forensic measures, as detailed in my answer here: Monitor and alert user when stty settings change?

You must log in to answer this question.

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