Я понял секрет!
Как я уже писал в "редактировании" выше, удаленной оболочкой был BusyBox ash
, а не bash
.
Из libbb/lineedit.c:2336-2338
, в источниках BusyBox:
/* Print out the command prompt, optionally ask where cursor is */
parse_and_put_prompt(prompt);
ask_terminal();
Это используется для распечатки командной строки в ash
. Но обратите внимание, как только он выводит подсказку, вызывается другая функция с именем ask_terminal
. Что делает ask_terminal
? Он печатает следующие символы: <ESCAPE>[6n
.
Вы никогда не увидите этих персонажей в своем терминале. На самом деле они представляют собой управляющий код управления терминалом ANSI. <ESC>[6n
- это команда "Query Cursor Position" - она говорит эмулятору терминала отправить обратно другой управляющий код ANSI, который сообщает оболочке, где находится курсор (точка вставки текста) в окне терминала.
Поэтому, как только вы нажмете Enter
, ash
напечатает <ESC>[6n
, и sshd
передает это обратно в ssh
а оттуда в эмулятор терминала. Сразу же, прежде чем вы сможете нажать ~
, ваш эмулятор терминала отправляет что-то вроде <ESC>[47;13R
на стандартный ввод, и ssh
передает это по соединению к sshd
и оттуда к ash
, сообщая ash
где находится ваш курсор.
Теперь клиент SSH на самом деле не знает, что означают эти escape-коды ANSI. Для SSH это все символы, считываемые из стандартного ввода. Вместо того, чтобы видеть <ENTER>~C
, SSH-клиент видит <ENTER><ESC>[47;13R~C
, и поскольку он не видит ~
сразу после Enter
, он не думает, что это escape-код ,
Вопрос в том, что с этим делать. Было бы хорошо, если бы OpenSSH понимал эти экранированные значения ANSI, отправленные терминалом, и все равно принял бы символ выхода ~
после команды управления терминалом ANSI. Я могу прислать ребятам из OpenSSH патч и посмотреть, хотят ли они исправить это ...