mybuf - みる会図書館


検索対象: 月刊 C MAGAZINE 1991年3月号
3件見つかりました。

1. 月刊 C MAGAZINE 1991年3月号

List 1 0 : 146 : ー 147 : ー 148 : ー 149 : ー 150 : 151 : 152 : 153 : ー 154 : 155 : ー 156 : ー 157 : ー 158 : ー 159 : 160 : ー 161 : ー 162 : ー 163 : ー 164 : 165 : ー 166 : ー 167 : ー 168 : 169 : ー 170 : : 171 : : 172 : ー 173 : ー 174 : ー 175 : ー 176 : ー 177 : ー 178 : ー 179 : ー 180 : ー 181 : : 182 : ー 183 : ー 184 : ー 185 : ー 186 : ー 187 : ー 188 : : 189 : 190 : ー 191 : : 192 : ー 193 : ー 194 : ー 195 : : 196 : . 197 : ー 198 : ー 199 : ー 200 : ー 201 : 202 : : 203 : ー 204 : 205 : : 206 : 7 : ー 208 : ー 209 : : 210 : ー 211 : ー 212 : ー 213 : ー 214 : ー 215 : : 216 : ー 217 : ー 218 : mybuf. key. chScan / * スキャンコードを毎回クリアする * / / * モニタのバッフアを読む * / DosMonRead( (PBYTE) &inbuf, DCWW_WAIT, (PBYTE)&mybuf, &len) : / * OS / 2 のコマント・・インターフ・リタからの入力だけを処理する * / if ( info->pidForeground = DOS_ 円 D ) { ( (mybuf. kbdDDFlags & KDD_BREAK)&& / * 上矢印または下矢印キーならプレークコードを待っ * / i f i f / * プレークをセットする * / mybuf. kbdDDFlags ト KDD_BREAK; DosMonWrite((PBYTE)&outbuf, (PBYTE)&mybuf, len) : *Str mybuf. key. chChar ー KDD-BREAK : / * プレークをクリアする * / mybuf. kbdDDPlags & = for (;*str; str + + ) { strcpy(cur_cmd, str) : C ニ strlen(str) : str cmd[next_command] : next-command =(next_command==MAXCMDS-1)? 0:next_command 十 1: / * 下矢印なら次のコマンドへ * / e I se = MAXCMDS-I : next_command e 1 S e if ( next_command ) next_command if ( mybuf. key. chScan== 叩 _arrow) / * 上矢印なら前のコマンドを得る DosMonWrite( (PBYTE)&outbuf, (PBYTE)&mybuf,1en) : / * フ・レークをセットする * / mybuf. kbdDDFlags ト KDD_BREAK,• DosMonWrite( (PBYTE)&outbuf, (PBYTE)&mybuf, len) : backspace : mybuf. key. chChar ー mybuf. kbdDDFlags & = -KDD_BREAK; / * プレークをクリアする * / / * バックスペースを送って現在行を消す * / i f (c) { ( (mybuf. key. chScan ー up_arrow) Ⅱ (mybuf. key. chScan==down_arrow) ) / * 矢印キーが押されたら最前のコマンドをモニタのバッフアに挿入する * / cont inue : ( (mybuf. key. chScan==up-arrow) Ⅱ (mybuf. key. chScan==down_arrow) ) DosMonWrite((PBYTE)&outbuf, (PBYTE)&mybuf, len) : switch ( mybuf. key. chChar ) { if ( (mybuf. key. chChar ! = 0 ) & & (mybuf. key. chChar ! = 0xE の ) = cntrl_fl) break if ( mybuf. key. chScan /*c-F 1 が押されたらモニタを脱ける * / if ( ! (mybuf. kbdDDFlags & KDD_BREAK)) continue : / * プレークコードの後でのみキーを調べる * / DosMonWrite( (PBYTE) &outbuf, (PBYTE) &mybuf, len) ; }else{ case case case enter:/* [ RETURN ] キーが押されたのでコマンドをセープする * / : / * パックスペース * / escape : break : break; strcpy (cur_cmd 十 C, cur_cmd 十 c 十 1) : i f (c) { backspace break; cur-cmdC0]=0; if( next_command==MAXCMDS) next_command=0; next_command 十十 : strcpy (cmd [next_command] , cur_cmd) : default ・ if (mybuf. key. fsState & KS_INSERT) { / * 川 S が on なら for (i=strlen(cur_cmd) : ーー ) cur-cmd[i + l]=cur_cmd[i] : cur-cmd[c]=mybuf. key. chChar; stdout へのすべてのライトは , 子の stdout'€ イプへ行くことになります ) 。 親の stdin のハンドルを複製し , この複製 を newstdin と呼びます。親の stdin のハンド ルをクローズします。 si read のハンドルを 元の stdin のハンドルへと複製します ( これ て、 , 親の stdin siread となり , stdin の すべてのリードが子の stdin'f イプから来る ことになります ) 。 子プロセスを非同期て、スタートします。 子プロセスには , 今や , パイプに接続され た stdin と stdout があります。それらを , 親 から継承したからて、す。 ハンドル new stdin と new stdout を stdin と stdout ハンドルの上に複製して , 親の本物 の stdin と stdout をリストアします。こうす ると親は , si write のハンドルにライトし , so read のハンドルからリードすることによ って , 子と通信て、きます。 そして親て、ある CLR のプロセスは無限ル ープに入り , その中て、コマンドを stdin から リードし , それを子に ( si write を介して ) ラ イトします。次に , 応答を ( s 。 read を介して ) 子からリードし , この応答を stdout へ工コー します。これは , CLR のプロセスに , 子の シェルがいっパイプへのライトを終了した かがわかるならば , 万事順調にいきますが , パイプには , 子が終了して次のコマンドを 受け付けられる状態て、あることを親に伝え るための , EOF などのトークンがありませ ん。 CLR はひとつのコマンドを処理する と , パイプリードのステージてハングして しまいます。 この問題を回避する方法はふたつありま すが , どちらも使えません。最初のものは , CLR プログラムが子の stdout パイプ上のコ マンドシェルプロンプトを見て , 子が終了 ことを検出するのて、す。しかし , プロ ンプトは変わることがあるし , 何かの無関 係なコマンドのコンテキストの中て stdout の パイプにエコーされることもありえるから , これはあまりよい解決策てはありません。 Command-Line Retriever f0 「 OS / 2 29

2. 月刊 C MAGAZINE 1991年3月号

題 - ル i 羆①① i ① v ①に f ①に①、 / 2 List 1 もうひとつの方法は , コマンドが送られ るたびにシェルを同期て、走らせる , という ものて、す。この方法て、は , シェルはひとつ のコマンドを処理するたびに終了し , CLR のプロセスはパイプが空になるまて、リード します。しかし , コマンドごとにシェルを 起動していたのて、はレスポンスタイムが劣 化するため , これも使える方法て、はありま せん。 やや見込みのありそうな最後の解決策は , 親の CLR プロセスの中て、ふたつの別々のス レッドをスタートする方法て、す。ひとつは 丘の stdout'€イプを連続的にリードしてそれ を画面にエコーするスレッド , もうひとつ は , キーポードからコマンドをリー それらをの stdinn0 イプにライトするスレ ッドて、す。これなら完全に非同期のインタ フェイスがユーザに提供され , ューザは現 在のコマンドの実行中に新たなコマンドを タイプて、きるて、しよう。 ユーザの入力とコマンドの出力との間の 画面の競合を避けるためには , 画面をふた つのウインドウに分割します。画面下部の コマンド行ウインドウはユーザと対話し , コマンド出力ウインドウが画面の E 部を占 こういった間題以外にも , この戦略は stdin めます。 ラインインタフェイスの扱い方て、す。最初 根本的な問題は , シェルによるコマンド DL 使う方法 舞いに影響がおよぶて、しよう。 シェルのドて、走るアプリケーションの振る ロセスて、あるという実が不透明なため , なりません。この設計て、は , シェルが了・プ それぞれ別の対応をとれるものて、なければ と画面に結びついているか否かに応じて , のステータスを調べて , それがキーボ、一ド なものて、す。アプリケーションはハンドル 般的なプログラミング戦略としても不満足 と stdout のハンドルを置き換えるために ー 219 : 220 : ー 221 : 、 222 : ー 223 : ー 224 : ー 225 : ー 226 : ー 227 : ー 228 : ー 229 : : 230 : ー 231 : ー 232 : ー 233 : : 234 : 、 235 : ー 236 : ー 237 : : 238 : ー 239 : ー 240 : ー 241 : ー 242 : ー 243 : : 244 : ー 245 : ー 246 : ー 247 : ー 248 : : 249 : ー 250 : 、 251 : ー 253 : ー 254 : : 256 : ー 257 : ー 258 : : 259 : ー 260 : ー 261 : 262 : ー 263 : ー 264 : ー 265 : : 266 : 267 : , 268 : } C 十十 : )else{ cur-cmd[c]=mybuf. key. chChar : C 十十 : if ( ! (mybuf. kbdDDFIags & KDD-BREAK)) continue : / * フ・レーク・コート・の後でのみキーを調べる * / DosMonWrite( (PBYTE)&outbuf, (PBYTE)&mybuf, len ) : cmd [c] = 0 : }else{ / * ! DOS- 円 D * / } / * switch * / cur_ if ( DosGetPrty(PRTYS_PROCESS, &wait, DOS_ 円 D ) ) i f ( j== 10 ) { / * しかしこれは 10 キーごとにチェックしてシステムの速度低下を防ぐ * / / * 0S / 2 のコマント・の円 D がもはや存在しなければモニタのインストールを外す * / if ( mybuf. key. chScan = cntrl-fl) break ・ /*C- F 1 が押されたらモニタを脱ける * / break } / * for ルーフ・の終わり * / DosMonCIose(monitor-handIe) ; DosSemCIear( &term-sem) : : 252 : } / * keymon ノオワリ * / USHORT wait ・ for ( wait=0;wait く MAXCMDS;wait + + ) cmd[wait][0]=0; DosSemSet( ( ULONG far * ) &term-sem ) : -beginthread(keymon, (void far * ) stackl, 4096 , t i d / * term ー sem セマフォを待ち続ける * / DosSemWait( (unsigned far*) &term-sem, ー 1 し ) : : 255 : main() (void far * ) の : List 14 : 10 : 9 : 8 : 7 : 6 : 5 : 4 : 3 : 2 : 1 : CLR プログラムの main ( ) 関数の一部 これは C L R プログラムの ma in ( ) のごく一部である . これは D ししをインストールすることによって KBD ルーチンを置換する . 使い方の詳細は本文を見よ . #include く stdio. h> #include く stdlib. h 〉 #include く string. h> #include く process. h> 12 : #define INC し _BASE 13 : #define INC し -DOSPROCESS #include く 0S2. h > 30 C MAGAZINE 1991 3

3. 月刊 C MAGAZINE 1991年3月号

- 影 i ①① iev ① f ①に①、 / 2 List 1 て多くなるのて、す。 CLR プログラムのプロ セスプライオリティを高くすると , OS/2 は それをもっと頻繁にスケジュールするよう になりますが , しかし , そうしたあとて、も , このプログラムは実行速度と機能の両方て、 不満足なものて、した。 ペイプを利用する 最初のバーションに欠けていた機能の , 最大のものが画面アクセスて、す。ューザと ( 画面を介して ) 対話をし , コマンドシェル にもデータを送る , というタイプのフォア グラウンドプロセスも , 動作しなければな りません。私は結果をろくに考えもせずに シェルを子プロセスとしてロードするプロ グラムを書きました。 子の stdin と stdout が , フォアグラウンド プロセスがリード / ライトて、きるパイプにフ ックされます。 CLR70 ログラムはユーザの コマンドて、目覚め , シェルの stdin ストリ ムへとパイプします。それから , シェルの stdout ストリームから応答を読み , それを直 接に画面に表示します ( Fig. 2 ) 。この CLR プ ログラムはシェルを ( 子プロセスとして ) 完 全に隔離するのて、 , すべての機能を実装て、 きます。 唯一の難しい部分は , シェルを子プロセ スとして起動して , その標準ハンドルを CLR のプロセスが所有するパイプに接続した状 態にすることて、す。これを行うために , OS/ 2 はさまざまなパイプ ( 関連の ) 関数と , ハン ドル複製関数を用意しています。 子の stdout を , so read および so write と いう名のハンドルとパイプさせます。子の stdin を , si read および si write という名の ハンドルとパイプさせます。 親の stdout のハンドルを複製し , この複製 を new stdout と呼びます。親の stdout のハ ンドルをクローズします。 so write ハンドル を元の stdout のハンドルへと複製します ( こ れて、 , 親の stdout so write となり , 73 : #define KS_SYSREQ 75 : 76 : U し ONG term-sem ニ 0 し・ 77 : unsigned tid 79 : / * スレッドのスタック * / 80 : char stackl [ 4096 ] 82 : / * コマンドのスタック * / 83 : #define MAXCMDS 10 84 : char cmd[MAXCMDS] [ 80 ] : 86 : 87 : void far keymon() 88 : { 89 : , DOS_ 円 D : USHORT sessionlD 90 : HMONITOR monitor_handle : buffer-type inbuf,outbuf; 92 : kbdpacket-type mybuf : 93 : 94 : USHORT I en 95 : USHORT 96 : SE し gsel, GINPOSEG far * info : 98 : Char * Str : 99 : int next_command, cur-cmd[100] : 100 : Char 101 : int 102 : 103 : 104 : 105 : 106 : 107 : 108 : 109 : 110 : 111 : 112 : 113 : 114 : 115 : 116 : 117 : 118 : 119 : 120 : 121 : 122 : 123 : 124 : 125 : 126 : 127 : 128 : 129 : 130 : 131 : 132 : 133 : 134 : 135 : 136 : 137 : 138 : 139 : 140 : 141 : 142 : 143 : 144 : 145 : 0X8000 1 se 1 next_command=O : cur-cmd[0]=0; / * モニタをオープンする * / if ( DosMon0pen ( "KBD$", (PHMONITOR) &mon itor_handle ) ) { printf(" Cannot open keyboard monitor. Yn") : DosBeep(600, 175 ) : DosSemCIear( (HSEM) &term_sem) : return : = sizeof( buffer_type ) : inbuf. Si ze outbuf. size = sizeof( buffer_type ) : / * 現在のスクリーングループのを取得する * / DosGetInfoSeg( &gsel, & ls 引 ) = MAKEP(gsel, の : infO sessionlD infO- 〉 sgCurrent DOS_ 円 D = info->pidPoreground : / * このスレッドのプライオリイティを上げる * / / * このスレッドだけを変える * / if ( DosSetPrty( PRTYS_THREAD, PRTYC_TIMECRITICA し , / * 最低のプライオリイティに * / 16 , t i d) ) { pr intf ("keymon ( ) スレッドをタイムクリティカルにすることができません . Yn") : DosBeep(600, 175 ) : / * このモニタをチェーンの冒頭に登録する * / if (DosMonReg( monitor_handle, (PBYTE)&inbuf, (PBYTE)&outbuf, 1 , sessionID) ) { p r i ntf ( " キーポードモニタを登録できません . \n " ) : DosBeep ( 600 , 175 ) : DosMonClose(monitor-handIe) : DosSemC lear ( (HSEM) &term-sem) : return : / * これがモニタのメインループ * / for ( : : len ニ sizeof( buffer-type ) : 28 C MAGAZINE 1991 3