前の投稿でエラーやタイプミスを(あまり成功していませんが)読んだ
時点で 、
ボブリーはコンソールでストーリーを作成する方法について議論することを提案しました(Shift-PgUp)。
端末に関連する何かをする明白な方法は、他の人がどのようにそれをしたかを見て、同じことをすることです。 これを研究する過程で、興味深い機能に注目しました。いくつかのプログラムは、コンテンツを表示し、アプリケーションを起動する前に画面を復元します(mc、vim、nano、lessなど)。 さらに、起動すると、スクロールバーが消えます(xterm / gnome-terminal内)。
方法を学習するために、最も古い(ncursesに依存しない)アプリケーションとしてMCを使用することにしました。
以下は、mcがどのようにtoggle_panel()をソースコードからの多くの引用とともに行うかについてのロマティックストーリーです。
同時に、読者は「ソースを見る」プロセスがどのように見えるかを見ることができます。
したがって、ソースコードはMCです。 画面の「戻る」はCtrl-Oで見ることができることが知られています。 ボタンの組み合わせは古いノートンコマンダーに登場し、その後のすべてのNCコンソールクローン(Dos Navigator、Volkov Commander、Far Navigatorなど)から借用されました。
原料(apt-get source mc)をダウンロードし、内部を見ました。
すぐに、keybind.cファイルが見つかりました。そこでは、Ctrl文字の組み合わせが「CL」(この場合は「Co」)としてエンコードされていることが簡単にわかりました。 列挙型の単純な配列(または定義ですか?重要ではありません)、必要な行:
{XCTRL( 'o')、CK_ShowCommandLine、 "Co"}、
さらに(MCのアーキテクチャがわからないため、あまり知りたくありません)、
grepユーティリティを使用してこの関数の場所を見つけるだけです:
grep CK_ShowCommandLine -A3 -B3 -r *
検索されたファイル-main.c
main.c:ケースCK_ShowCommandLine:
main.c- view_other_cmd();
main.c- break;
そしてその隣:
ビューアー/ actions_cmd.c:ケースCK_ShowCommandLine:
ビューア/ actions_cmd.c- view_other_cmd();
ビューア/ actions_cmd.c- break;
そして視聴者。 mc自体は同じ関数view_other_cmdを使用します。 同様のgrepは、目的の機能を備えたcmd.cファイルです。
ボイド
view_other_cmd(void)
{
static int message_flag = TRUE;
if(!xterm_flag &&!console_flag &&!use_subshell &&!output_starts_shell){
if(message_flag)
メッセージ(D_ERROR、MSG_ERROR、
_(「xtermまたはLinuxコンソールではありません。\ n」
「パネルを切り替えることはできません。」));
message_flag = FALSE;
} else {
toggle_panels();
}
}
目は古いスタイルのテキスト書式をわずかにカットしますが、...
だから
- 求められている関数toggle_pannels()。 実際、私たちはすぐにそれを見て急いでいますが、今ではより一貫性があり、エラーケースを注意深く読みます(Cのクロージャーのエレガントなエミュレーションに注意してください-操作時間全体でエラーメッセージを1回だけ表示するために静的変数を使用しますプログラム)。
- エラーが出力されるのは、xtermがなく、コンソールがない場合です。 サブシェル関連の部分は興味がありませんが、別個のxtermチェックに関しては、チェックを入れます。
toggle_pannels()を探しています。 execute.cファイル。 関数が大きいので、興味深い場所を引用します。
tty_reset_screen();
do_exit_ca_mode();
tty_raw_mode();
if(console_flag)
handle_console(CONSOLE_RESTORE);
- tty_reset_screen-みましょう
- do_exit_ca_mode-ああ、面白い
- tty_raw_modeは単に文字入力モードを切り替えています
- 興味深いことに、コンソールがあれば、handle_consoleは完了です...
ca_modeとは何ですか? 小さなヒッチ(ファイルはsrcではなくlibにあります)、tty /win.c。 その横にあるのは逆do_enter_ca_modeです:
ボイド
do_enter_ca_mode(void)
{
if(xterm_flag){
fprintf(stdout、/ * ESC_STR ")0" * / ESC_STR "7" ESC_STR "[?47h");
フラッシュ(stdout);
}
}
ボイド
do_exit_ca_mode(void)
{
if(xterm_flag){
fprintf(stdout、ESC_STR "[?47l" ESC_STR "8" ESC_STR "[m");
フラッシュ(stdout);
}
}
合計-未知のモードの切り替え。 xtermに関連付けられています。 クイックGoogleは、これが「代替画面バッファーを使用する」ことを提案しています。
Xtermは2つの画面バッファーを維持します。 通常の画面バッファーを使用すると、saveLinesリソースで設定された最大値まで、保存された出力行を表示するためにスクロールバックできます。 代替画面バッファはディスプレイとまったく同じ大きさで、追加の保存行は含まれません。 代替画面バッファがアクティブな場合、保存された行を表示するためにスクロールバックすることはできません。 Xtermは、2つを切り替えるための制御シーケンスとメニューエントリを提供します。
わかった なるほど。 Xtermには特別なescコードがあります。
Linuxはどうですか? Linuxコンソール(実際、Ctrl-Alt-F1)に移動し、vimを試してください。終了すると、画面に前の内容が表示されます。 少ない...参照してください。 ナノ...参照してください。 つまり、linux(console_codesによる)はこれをサポートしていません。 ええ、明らかに。 mcはどうですか? そして、mcが動作します。 どうやって? なんで? ソースコードmcに戻り、見てください...そして、handle_consoleは何をしますか?
私たちは探しています...(cons.handler.c):
ボイド
handle_console(unsigned charアクション)
{
(void)アクション;
if(look_for_rxvt_extensions())
帰る
#ifdef __linux__
handle_console_linux(アクション);
#elif定義(__FreeBSD__)
handle_console_freebsd(アクション);
#endif
うーん... LinuxとFreeBSDでは、これは異なる方法で処理されることがわかりました。 (しかし、ソラリスについてはどうですか?オラクルはあなたのソラリスにすぎないので、Oracleはフェルトブーツをコンソールに投げました。)
console_saveを通して、handle_console_linuxを調べます。 何が見えますか? MCは、ioctlを実行するcons.saverと呼ばれる別のプロセスをフォークし、奇妙なデバイス/ dev / vcsa *への読み取りと書き込みを行います。 どんなデバイス?
ああ、新しい不思議な世界
Linuxには、テキストモードのCGA(VGA)アダプターのメモリに対応する擬似デバイスがあり、データは配列として格納されていることがわかります
struct {
char char;
char Attrib;
}
はい、はい、ビデオメモリに直接アクセスできる、昔から忘れられていたDOS。 チェック-確かに、hexdumpファイルは画面の内容を完全に表示します。 デバイスにアクセスするには、この権限が必要であることに注意してください。 通常、これは次のように行われます。デバイスのファイルにグループを配置し、このグループに含まれるファイルの所有者をファイルに公開し、sgidビットを設定します。
Debianでは、cons.saverにはttyグループ(疑似端末にアクセスするための共通グループ)用のsgidビットがあり、特別なvcsaグループ用のcentosがあります。 原則として、RHEL / CentOSのアプローチに同意します。より安全です。
だから、特別なファイル...つまり、MCはなハックの助けを借りて画面の内容を読み取り、必要に応じて書き戻します...
しかし、仮想マシンのコンソールはVGAアダプター上にありません! これは純粋なシリアルポートです。 また、単純なチェックは疑わしいものです-すべての仮想マシンで、VGAアダプターがないため、vcsaは初期状態です。 つまり、ビデオカード。
どうする まあ、まずは、mcがシリアルポートの状況で何をするかを確認してください。 知っているように、UNIX98擬似端末とシリアルポートの間に違いはありません。 実際のLinux(コンソール)に戻り、sshを介して任意のサーバーにログインし、mcを起動します。
したがって、コンソールをシリアルポートで作成している間は、原則としてvcsaの類似物を提供することはできません。また、mcでctrl-oをハックすることはできません。 原則として。
しかし、xtermはどうですか?
xtermのESCコードの実装は簡単です。 しかし... ...仮想マシンのコンテンツにアクセスすることはできません。ユーザーの環境を変更することはできません。つまり、デフォルトでは、linuxはシリアルポートにlinux端末タイプ(TERM = linux)を持ち、xterm / xrvt関数を実装しません意味-とにかく使用されません。
念のため、mcがxterm拡張の存在について学習する方法を確認します...
const char * termvalue;
termvalue = getenv( "TERM");
悲しいかな-環境変数(そしてクエリ文字列を期待していた)。 まあ、間違いなく。 ああ。
ところで、FreeBSDでもまったく同じハック(ただし、アーキテクチャ機能に合わせて調整)が使用されています。 ああ。
道徳?
素晴らしいLinuxコンソールでは、Ctrl-Oは完全に機能しません。 悲しいかな、決して。 そして残りは面白かった。
...ところで、ライブサーバーがあり、それが生きている場合、コンソールで何が起こっているかをリモートで確認できます-cat / dev / vcsa *。 また、特別なファンは、コンソールで他のユーザーがどのように機能するかを見ることができます。