web-dev-qa-db-ja.com

C-cでedを終了できないのはなぜですか?

最小限のテキストエディターであるプログラムedは、使用して割り込みを送信しても終了できません Ctrl-C、代わりにエラーメッセージ「?」を出力しますコンソールに。なぜ割り込みを受け取ったときにedが終了しないのですか?確かに、ここに存在するだけでなく、不可解なエラーメッセージの方が役立つ理由はありません。この動作により、多くの新規ユーザーは次のようなやり取りにつながります。

$ ed
hello
?
help
?
exit
?
quit
?
^C
?
^C
?
?
?
^D
$ su
# rm -f /bin/ed

そのような悲劇的な無駄— edが単に中断されることに同意した場合、簡単に回避できます。

同様の動作を示す別の頑固なプログラムはlessでもあり、これも無視する理由があまりないようですC-c。なぜこれらのプログラムは単にヒントをとらないのですか?

20
Lily Chung

Ctrl+C 送信 [〜#〜] sigint [〜#〜] 。 SIGINTの従来のアクションは、プログラムの最上位ループに戻り、現在のコマンドをキャンセルして、プログラムが次のコマンドを待つモードに入ります。非対話型プログラムのみがSIGINTで終了することになっています。

だから当然です Ctrl+C edを強制終了しませんが、最上位のループに戻ります。 Ctrl+C 現在の入力行を中止し、edプロンプトに戻ります。

同じことがより少なくなります: Ctrl+C 現在のコマンドを中断し、コマンドプロンプトに戻ります。

歴史的な理由により、edは [〜#〜] sigquit [〜#〜]Ctrl+\)。通常のアプリケーションはこの信号をキャッチせず、有効になっている場合はコアダンプを使用して自身を終了させる必要があります。

nix V7 ed(1)ソースコード は、少数のコメントのみを含むプリミティブな1,762行のCプログラムであり、そのうちの1つはこの非常にわかりやすいヘッダーコメントです。

_/*
 * Editor
 */
_

ソースコード自体には根拠がないため、プログラムの作成者から入手するだけです。

edは元々は PDP-11アセンブリのKen Thompsonによって と書かれていましたが、実際にはCに移植した人と話す必要があります。それはおそらく Dennis Ritchie 、彼はUnix用にCを作成し、Cを使用してUnixを非PDPマシンに移植できるようにする多くの人の1人だったためしかし、リッチー博士はそのような質問に答えるのにもはやいません。

コードを読んだところ、編集されたドキュメントの in-core コピーの内容を保存しようとしたことが示唆されました。他のテキストエディターも死なないことに気づくでしょう Ctrl-C

edの機能は次のとおりです Ctrl-C

_onintr()
{
    signal(SIGINT, onintr);
    putchr('\n');
    lastc = '\n';
    error(Q);
}
_

(はい、 K&R C 。戻り値の型指定子やパラメータ宣言は必要ありません。)

英語に翻訳、ed

  1. シグナルハンドラを再登録します。

    (Unixは自動リセット信号を取得しませんでした 4.3BSDまで 、1980年代中頃。)

  2. グローバル変数lastcを介して、新しい行を書き出し、そのことを記憶します。

    (_ed.c_には約sixtyグローバル変数があります。)

  3. ユーザーの観点からは、error()関数を呼び出します。これは 有名な が、印刷_?_を実行するだけです。

つまり、「そうするつもりはなかったのですか」。

18
Warren Young

edは、他のインタラクティブプログラムと同様に、 Ctrl+C プログラム自体のタスクを中断します。
これは、シェルで実行されているタスク(コマンド)を中断する通常の場合と非常に似ています。

ユーザーの観点からは、両方のバリアントは非常によく似ています。シグナルの処理は異なります。通常の場合、シグナルSIGINTは実行中のコマンドであるフォアグラウンドプロセスに送信され、コマンドは終了することで処理します。
edの場合、シグナルはフォアグラウンドプロセスのedインスタンスに送信されます。 edで実行中のタスクがある場合、そのタスクは中断され、プロンプトが表示されます。実行中のタスクがない場合、何も変更されません。

シェルも終了しないことに注意してください Ctrl+Cedと同じように。そしてそれが終了すること Ctrl+D。繰り返しますが、edのように

7
Volker Siegel

edが気にする3つのシグナルがあります。

  1. INT
  2. HUP
  3. QUIT

ed のPOSIX仕様では、これらについて次のように述べています。

SIGINT

edユーティリティは現在のアクティビティを中断し、文字列?\nを標準出力に書き込み、コマンドモードに戻ります(詳細説明のセクションを参照)。

SIGHUP

バッファが空ではなく、最後の書き込み以降に変更されている場合、edユーティリティはバッファのコピーをファイルに書き込もうとします。まず、現在のディレクトリにあるed.hupという名前のファイルを使用します。それが失敗した場合、HOME環境変数で指定されたディレクトリにあるed.hupという名前のファイルが使用されます。いずれの場合でも、edユーティリティは、現在記憶されているパス名にファイルを書き込まずに、コマンドモードに戻らずに終了します。

SIGQUIT

edユーティリティはこのイベントを無視します。

したがって、使用しているedの実装は、INT信号に関するPOSIX仕様に準拠しています(これは Ctrl+C 送信)。

この点で、エディターはインタラクティブシェルのように動作し、INT信号を受信して​​も終了しません。 vinanoなどの他のエディターも同じことを行います。

3
Kusalananda