shellでパスワードプロンプトの入力を間違えたらControl-uする理由

追記(2022/03/20)

Linux限定だし概要レベルだけど包括的なドキュメントがあった。

2. Keyboard generalities

キー入力したときに起きていることを説明している。

  • キーボードコントローラはキーボードドライバにスキャンコードを送信する
  • (スキャンコードモードの)キーボードドライバはアプリケーションプログラムにスキャンコードを送信する
  • (キーコードモードの)キーボードドライバはキー押下、キー離上それぞれのスキャンコードをキーコードに変換し、アプリケーションプログラムに送信する
  • (それ以外の)キーボードドライバはキーコードでキーマップを辞書引きして、発見した文字列(エスケープシーケンスの場合もある)をアプリケーションプログラムに送信する

「アプリケーションプログラムに送信する」は、実際には「端末ドライバに送信する」に相当する。

(端末ドライバ=sttyなのかな)

4. Resetting your terminal

エスケープシーケンスを含む文字列を受信した stty  は~/.inputrc を読んで?エスケープシーケンスに対応するコマンドを見つけると、それをTERMに設定された端末エミュレータへ指示する。

Control-Lを入力すると(押さえて離すと)、最終的にclearコマンドになる、といった具合。

だから 'echo −e \033c' でキーコードを送信すると、エスケープシーケンス ESC c へ変換され、それか reset コマンドとして解釈される。

ということを踏まえてsttyを調べていくとよさそう。

 

 

stty

Special Control Character Assignments

(いろいろあって)sttyの初期値ではCtrl-Uがkillに割り当てられている。


f:id:yujiorama:20220320101826j:image

General Terminal Interface

KILL

    Special character on input, which is recognized if the ICANON flag is set. Deletes the entire line, as delimited by an NL, EOF, or EOL character. If ICANON is set, the KILL character shall be discarded when processed.

ICANONフラグはよくわからないけど、文字列に改行文字や行末文字やファイル終端文字が含まれている場合にセットされるらしい。

結果として、今のカーソル位置(が含まれる文字列)の行を全て削除する、という振る舞いになりそうだ。

追記

コメントで「それはttyの機能だ」とか「そんなやばいところにreadline使うわけ無いだろ」という教えを頂いているので、ちゃんと実装を調べてこようと思っています。

試しにsudoを眺めて、readlineを使ってないのは確認してきました。

安易な答えに飛びついてはいけないなと反省してます。

 

端末エミュレータがCtrl+uをハンドリングしている、という指摘を頼りに、tty、stty、termiosまでたどり着いた。

termios(3) - Linux manual page

VKILL

(025, NAK, Ctrl-U, or Ctrl-X, or also @) Kill character (KILL). This erases the input since the last EOF or beginning-of-line. Recognized when ICANON is set, and then not passed as input.

とてもそれっぽい。これならreadline関係なく、cliコマンドの振る舞いを制御できそう。

もう少し裏取りできたらタイトル直そう。

 

元の記述

そういうものだと思考停止してたけど、考えたら(調べたら)すぐに分かった。Readlineにそういう機能があるからだった。

1.4.4 Killing And Yanking

unix-line-discard (C-u)

Kill backward from the cursor to the beginning of the current line.

inputrcでキーバインディングを変更してると違う操作になりそう。カスタマイズしてないから使えてたんだな( emacs bindingになっているので)。

カーソル位置から行頭までの文字を全て削除する、だからパスワード入力の途中でControl-uすると、入力をやり直すことができるのだった。

疑問

逆にReadlineを使ってないソフトウェアではそういうこと(Control-uで途中まで入力したパスワード文字列を捨ててやり直す)ができない気がする。どうすれば見分けられるんだろう。

身近なソフトウェアでReadline使ってそうなやつ

全然思いつかなかった。