べます。すべての可能を調べてもよさそうですが、 tel- netd では次のように、バッフアの空き状態などから調べ るべきファイル・ディスクリプタを決定しています。 if (nfrontp ー nbackp Ⅱ pcc > 0 ) { FD_SET(f , &obits) ; } else { FD_SET(), &ibits) ; nfrontp ー nbackp が 0 以、タ ) 値になる場合は、クラ イアント側に送出するためのキューか空ではないことを意 味します。また、 pcc が 0 より大きな値となる場合は、仮 想端末側から読み込んだバッフアにデータか残っているこ とを意味します。このようなときには、ネットワーク側に 送出できるかどうかだけを調べます。これらの条件カ城り 立たない、つまりクライアント側に送出するためのキュー が空で、イ反想端末側から読み込んだバッフアにもデータが 残っていない場合には、イ反想端末側から言囚みか可能かど うかを調べます。 さらに、クライアント側とイ反想端末側を逆にした検査も 必要です。 if (pfrontp ー pbackp Ⅱ ncc > 0 ) { FD_SET(), &obits) ; FD_SET(f , &ibits) ; } else { このコードでは、イ反想端末側に送出するためのキューに データか残っていたり、ネットワークから読み込んだバッ フアにデータカ戯っている場合には、イ反想端末に書き込め るかどうかを調べます。これらの牛カ艚たされないとき は、ネットワーク側に読み込むべきデータがあるかどうか を調べます。 telnet コマンドでは、このさまざまな場所からの入力 をうまく処理するために、リングバッフアを使って制御 していました。これに対し、 telnetd ではリングバッファ などのネ隹なデータ構造は利用していません。データ構造 といえそうなのは、ネットワークとイ廨端末に対する出力 をイ尉寺するキューだけです。しかし、実際にはどちらも同 しような処理が可能です。これは、 select システムコール に与える FD-SET の違いによるものです。 telnetd では、 すでにデータがある場所には言囚みをおこなわないという ガ去をとっています。そのため、一度データを読み込んで 82 も、次に同し場戸励、ら読み込むときにはかならずデータは 空になっているはすです。したがって、データを読み込む 際には石呆した領域の : 麪頁から読み込むことが可能になっ ています。これが、プログラムか簡単になっている大きな 理由です。 データを入力バッフアに読み込んだ場合、ます端末の設 定変更が必要かどうかを調べます。設定の変更が必要で、 かっ telnet とのあいだて端末の設定をクライアント側で おこなうという合意がとれている場合には、その情報をク ライアント側に渡さなければなりません。このような場合 には必要な 1 辭長をまとめ、クライアント側に送出するキュ ーに登録します。特殊な処理カ坏要なデータの場合にも、 ノヾイナリモードでの転送が可能かなどを調べながら、イ反想 端末側の入力バッフアからクライアント側への出力キュ に移動していきます。 なお、このループは無限ループとなっていますが、クラ イアント側や反想端末側からの言囚みにおいて EOF を読 み込んだ場合にはループを終了し、 telnetd プログラムも 終了します。 ☆ 今回は、 telnetd プログラムにおいて、これまでに紹介 してきた telnet コマンドでの処理に対応する部分がどの ように実現されているかという点に注目して、 telnetd の ソースコードを解説しました。 telnet ではリングバッフアを利用していた部分も、 tel- netd では 1 つ刎反定をおくことで簡単なコードとなって います。 プログラミングの際には、すべてのケースをカバーする のではなく、このように妥当なイ反定を 1 つ設定するだけで プログラムを簡ヒできることがよくあります。その点を 理解していただけたでしようか。 ( たしみ・ひさかす ) UNIX MAGAZINE 2002.6
連載 / シェルの魔術ー⑨ 表 2 chmod の記号形式 ( 十で、、誰の・・が省略された場合 ) 許可を与えるもの (wx) 許可の頁 所有者 言翹えり 書込み 実行 / 捜索 言 ( り 書込み 実行 / 捜索 翹り 書込み 実行 / 捜索 十 ー ( 禁止 ) ーは、十とほば逆の働きをします。つまり、 SetUID/SetGID ビット 、誰の " て指定されたユーザーに対して、、何を " で指定され t スティッキー・ビット た操作を禁止します。十と同しように、そのほかの部分に もとのファイルでの、所有者部分のパーミ、、 : u ノ / ーヨン 関しては変更されません。 もとのファイルでの、所有グルーフ分のパーミッシ g 次の例では、その他のユーザーから書込みと実行 / 捜索 その他のユーサー部分のパーミ の権限を剥奪しています。 o もとのファイルでの、 ツン・ヨン $ chmod o—wx sample 、、操作 " の部分は、 + 、 = の 3 種類の記号から選び 、、誰の " か省略された場合は、すこし注意が必要です。 ます。それぞれについて、例を挙げながらみていきましょ の場合、、、何を " で指定された操作のうち、 umask て許可 う。なお、説明のなかに出てくる umask は、分かりやす されているものだけを禁止します。たとえは、 umask が くするため、実際の場面ではあまり設定しない値も使いま 022 のとき、パーミッションが 777 のディレクトリに対 した。また、、、何を " の部分では、 s や t 、 X などはとり して次のコマンドを実行すると、 577 という変なパーミッ あげません (s 、 t については次回以降で説明します ) 。 ションになってしまいます俵 3 ) 。 十 ( 許可 ) 十は、、、誰の " て指定されたユーサーに対し $ chmod —w sampledir て、、何を " て指定された操作を許可します。そのほかの部 $ ロ 分に関しては変更されません。 次の例では、所有者と所有グループに対して書込みと実 ノート 3 なせこのような動作をするのか、不思議に思うかもしれま 行 / 捜索の許可が与えられます。 せん。私も調べたわけではないので正確には分かりませんが、 umask には、 ( 新規作両を含めて ) パーミッションの変更箇 $ chmod ug + wx sample 所を明示的に指定していない場合に、対象となる箇所を表すも の " という意味があるのかもしれません。 、、誰の " が省略された場合は、、、何を " で指定された操作 、、何を " が省略された場合は、十のときと同じように、何 のうち、 umask て滸可されているものだけを許可します。 もしません。 この場合も同しく、対象となる部分以外は変更されませ = は、絶対形式と似たような作用をします。 = ( 設定 ) ん。たとえば、 umask が 022 のとき、以下のコマンドは 隹の ' てオ日疋されたユーサーのパーご、、 : 所有者の書込みと、所有者、所有グループ、その他のユー つまり、 、ノノ・ヨン / を、、何を " て指定されたものと同しにします。 サーの実行 / 捜索を許可します俵 2 ) 。 次の例では、所有グループとその他のユーザーに言翹てり $ chmod + wx sample と実行 / 捜索だけを許可します ( もとの状態で書込みカ滸 可されていても、彖されます ) 。 また、、、何を " カ略された場合は、何もしません。 実際に許可されるもの umask 直 ( 022 ) 〇〇〇〇 x 〇〇 x 〇 十 十 十十十十十十 所有グループ 十 その他のユーザー 1 一二ロ 一三ロ 107 UNIX MAGAZINE 2002.6
2 し inux のプートプロセス 図 17 ハンドラを呼び出すときのスタック吏用法 (a) レベルか物ラしない場合のスタック 割り込まれたプロセスとハンドラは同じスタックを使用する ハンドラを呼び出す 工ラーコード・← 直前のスタックポインタ EIP CS EFLAGS スタックが伸びる方向 割込み / 例外が発生する 前のスタックポインタ (b) 特権レベルがラする場合のスタック 割り込まれたプロセスのスタック ハンドラを呼び出す 直前のスタックポインタ ハンドラのスタック →・エラーコード EIP CS EFLAGS ESP スタックが伸びる方向 割込み / 例外が発生する 前のスタックポインタ SS のみ DPL が 3 に設定され、ユーサーがソフトウェア割 込みを発生できるようになっています。その他の DPL はすべて 0 です。 ( 本物の ) 割込み / 例外が発生した場合は、このチェッ クはおこなわれません。つまり、 CPL の値に関係なく ハンドラが実行されます。 7. 現在の EFLAGS 、 CS 、 EIP レジスタの内容をスタッ クにブッシュします。ただし、 CPL とハンドラのコー ドセグメントの DPL によって、スタックの場戸励ゞ異 なります。 雀レベルの秘丁が発生しない場合 CPL とハンドラの DPL が同じときは、現行のス タックをそのまま使います ( 図 17- a ) 。 雀レベルの移行が発生する場合 CPL とハンドラの DPL が異なる場合はスタックの 切替えか起こります。 前回は、ページンク冓がリニアアドレスを物理アドレ CPU は、 TSS レジスタからプロセスの状態を表す スに変換する仕組みについて説明し、今回はページングに データ構造体にアクセスし、そのなかからセグメン よる手機能について説明しました。 ト・セレクタと、スタックポインタを読み取ります。 次に、現在の SS と ESP 、 EFLAGS 、 CS 、 EIP レ 前号で述べたように リニアアドレスは仮想的なアドレ ジスタの内容を TSS から得たスタックにオ褓内し、さ ス空間で、現実に 4GB ものメモリか載っていない言算機 らに SS と ESP レジスタの内容を史新して、スタッ クを切り替えます ( 図 17 ー b ) 。 8. 例外にエラーコードがともなう場合は、それをスタック にフッシュします。 9. ゲート・デスクリプタからセグメント・セレクタとオフ セットを読み取り、それぞれ CS と EIP レジスタに ロードします。 以上の処理により、 CPU はハンドラの実行を始めま す。そして、、、決まりごと " として、ハンドラルーチンの 燧こはかならず IRET 命令を実行します。この命令は、 上記の処理で切り替えた制御ポインタ ( スタックを切り替 えた場合はスタックポインタ ) をもとに戻し、割込み多に 前の実行位置に復帰する処理をおこないます。 おまけ 48 UNIX MAGAZINE 2002.6
連載 / シェルの魔術ー⑨ 表 3 chmod の記号形式 ( ーで、、誰の " が省略された場合 ) 許可を剥奪するもの (w) 許可の 所有者 言嗣てり 書込み 実行 / 捜索 実行 / 捜索 言翹 ( り その他のユーザー 実行 / 捜索 表 4 chmod の記号形式 ( = で、、誰の・・が省略された場合 ) umask 直 ( 025 ) 言聢するハーミッション (rw) 許可の頁 所有者 言翹 ( り 実行 / 捜索 実行 / 捜索 その他のユーサー 実行 / 捜索 umask 直 ( 022 ) に剥奪されるもの 〇〇〇〇 >< 〇〇 >< 〇 所有グループ 実際に言聢されるもの 〇 〇 〇 〇 〇 〇 〇 〇 〇 こノンヨンと同じにしたのち、書込別雀限を泉簿し $ chmod go=rx sampledir ています。順番カ芍色だと、、 - w " が無効になってしまうこと に注意してください。 、、何を " て指定されている 、、誰の " が省略された場合は、 また、記号形式の基本型は , ( カンマ ) で区切って、 もののうち、 umask で許可されているものだけを許可し 複委対旨定できます。 ます。それ以外のものに関してはすべて禁止になります。 umask が 025 のとき、以下のコマンドは所有者 / 所有グ $ chmod u=rwx , 0 = sample $ ■ ループの言翹てり、所有者 / その他のユーサーの書込みを許 可します俵 4 ) 。 この例では、所有者に対してはすべての操作を許可し、 その他のユーサーについては言翹り、書込み、実行 / 捜索 $ chmod =rw sample のすべてを禁止しています。 、、何を " が省略された場合は、、、誰の " からすべての権限 ユーサープライベート・クループ を剥奪します。両方が省略された場合は、所有者 / 所有グ ループ / その他のユーサーのすべてに対して、すべての操 最後にすこし脱線して、ユーサープライベート・グルー 作を禁止することになります。 プについて説明しましよう。 企業や大学などでは、あるまとまった仕事ごとにプロ 以上で説明した、、どうする " の部分は、続けていくつも ジェクトを作り、そのプロジェクトで複数の人が協調し 指定することができます。この場合、前から順番に実行さ て・作業する、ということがあると思います。また、それほ れていきます。 ど大掛かりなものではなくとも、何人かのグルーフ。で一緒 に乍業することは、日常的によくあるでしよう。 $ chmod g=u—w sample この作業を UNIX 上でおこなう場合、各人が自分のホ この例では、所有グループのパーミッションを所有者 ーム・ディレクトリで作業すると、関係するファイルがバ 〇〇 x 〇〇 x 〇〇 >< 所有グループ UNIX MAGAZINE 2002.6 108
連載シェルの魔術ー⑨ 一言翹り可能 ー書込み可能 ー % テ / 捜索可能 ・その他のユーザーの 一言翹えり可能 ー書込み可能 ー実行 / 捜索可能 の順に並べます。 UID/SetGID/ スティッキー・ビットは考えないものと ョンが以下のようになっているとします。また、 Set- 例を挙げてみましよう。あるファイルのパー いのて簡単ですね。 3 桁すつに区切って、それそれの固まりごとに考えればい ( 2 ) で作った 2 進数を 8 進数に変換します。 2 進数を ( 3 ) 8 進数に奐 として、 12 桁または、 9 桁の 2 進数を作ります。 属性を有効にしたい場合は 1 、そうでない場合は 0 ) 」 UID/SetGID/ スティッキー・ビットについては、その 「操作を許可する場合は 1 、そうでない場合は 0 (Set- ッションを、 ( 1 ) て並べたパ ( 2 ) 2 進数に奐 果は、次回以降に説明します。 これらの属性をディレクトリやファイルに適用した場合の効 ミッションのことをモードと呼ぶことがあります。 ションと一緒に扱われます。そのため、この属性も含めてバー を決めるものではありませんが、数値化するときにはバーミッ 殊な属生を加えるものです。これらの属性は操作の許可 / 禁止 は見慣れないかもしれませんが、ファイルやディレクトリに特 これら 3 つ (SetUID/SetGID/ スティッキー・ピット ) きます。その場合は、 ls ー 1 カ咄力する順番と同しですね。 これらのうち、最初の 3 つはまとめて省略することがで ます、許可する場合を 1 、そうでない場合を 0 としま す。所有者の部分は言翹 ( り / 書込みの操作か許可されてい るので、 110 になります。また、所有グループとその他の ューザーの部分は、言翹えりだけか許可されているので 100 になります。このようにして、このパーミッション本を 2 進数で 110 100 100 と表すことができました。これを さらに 8 進数に変換すると、 644 になります。皆さんも、 実際に紙に書いて引算してみてください。 これで数値表現することができましたが、何かあるごと にこのような手順を踏むのはちょっと面倒です。でも、大 丈光もうすこし簡単に言 1 算するガ去があります。 手順の ( 2 ) の操作をよく考えてみると、所有者の言 り可能は 100000000 、所有者の書込み可能は 10000000 、その他のユーザーの実行 / 捜索可能は 1 として、単 純な足し算をしているだけです 1 。また、基数の変換は足 し算より先でも同じですから、けっきよく、次の一覧から 必喫なものを抜き出して足せはいいことになります。 400 200 100 40 20 10 4 2 1 所有者か翹印可能 所有者か書込み可能 所有者か実行 / 捜索可能 所有グルーフ。か第翹えり可能 所有グルーフ。か書込み可能 所有グルーフ。が実行 / 捜索可能 その他のユーザーか第翹り可能 その他のユーサーか書込み可能 その他のユーサーが実行 / 捜索可能 します。 所有者 所有グループ その他のユーザー 104 言翹り / 書込み可能 言翹可能 言翹り可能 さきほどの例では、 400 十 200 十 40 十 4 = 644 となり ます。すこしだけ簡単になったでしよう ? 新規ファイルの / ヾーミッション UNIX MAGAZINE 2002.6 考えてもかまいません。 1 もちろん、本当は論理和をとっているのてすが、重複かないので足し算と ションは、適当に決まっているわけではなく、次の 2 つ のような、作りたてのファイルやディレクトリのパーミッ んらかのパ ッションが設定されているはすです。 したばかりのファイルや、作りたてのディレクトリにもな 内にありますから、当然、リダイレクションなどで作成 ーミッションという属性はすべてのファイル ( の実
連載 / シェルの魔術ー⑨ 、ノノョン 許可の瑟頁 言り 書込み 実行 / 捜索 言翹り 実行 / 捜索 書込み 実行 / 捜索 の要素から言 1 算されます。 $ umask 0022 プロセスカ甘日疋したノヾーミ、、 プロセスのもっマスク値 ノート 2 前者は、プロセスがシステムにファイルやディレクトリ umask コマンドを引数なしで実行したとき、 4 桁の数値が の作成を要求するとき、「このパーミッションで作ってく 表示されたことに気がつきましたか ? このことからも分かるよ うに、 umask は SetUID/SetGID/ スティッキー・ピット ださい」とお願いするものです。たとえは、ディレクトリ に対しても、設定したくなし寸篥作 " を指定できるのです。 を作成する mkdir コマンドは、「このディレクトリを 777 一方、プロセスカ畴斤規にファイルを作成する場合も、 Set- で作ってください」とお願いします。また、シェルがリダ UID/SetGID/ スティッキー・ビットまで含めて要求するこ イレクションでファイルを作成する際には、「このファイ とかできます。 ルを 666 で作りたいんだけど」と要求します。 さて、プロセスがファイルの作成を要求したとき、シス 後者のマスク値は umask と呼はれるもので、許可し ノンヨンを、 テムはそのファイルのパーミ、、、 たくなし鰾作を新直で指定します。直の言 1 算ガ去はパー 1. プロセスカ甘日疋したパーミッションから ミッションの数値表現の場合とはは 1 司しですが、さきほど 2. umask によって指定されたものを除く の手順の ( 2 ) で、 「操作を許可したくない場合は 1 、そうでない場合は 0 」 という操作によって決定します。 たとえば、シェルの um k が 027 だったとしましょ とします。たとえば、所有グループとその他のユーザーの う。このとき、コマンドの実行結果をあるファイルにリ 書込みを許可したくない場合の umask は 022 になりま ダイレクションしたとします。リダイレクションは 666 す。 でファイルを作成するように要求しますから、作成された ところで、 umask の値は、連載の第 7 回 ( 2002 年 1 ミッションは 640 になります俵 1 ) 。 ファイルのノヾ 月号 ) でとりあげた、、プロセスの清報 " の 1 つです。また、 また、 mkdir コマンドを実行した場合、その umask は プロセスか複製される際には、親プロセスの箱から子プロ シェルの umask がそのまま引き継がれるので、 027 にな セスの箱へコピーされるものです。 ります。 mkdir コマンドは 777 でディレクトリを作成 シェルの umask の値は、 umask コマンドて変更する するように要求しますから、新しくできたディレクトリの ことかできます。引数には、指定したい umask を指定し ミッションは 750 になります。 ます。 $ umask 022 また、引数を省略すると現在の umask が表示されま 結果 ( 640 ) umask 直 ( 027 ) プロセス求 ( 666 ) 〇〇〇〇 x 〇 >< x >< 〇〇 x 〇 x >< x >< x 〇〇 x 〇〇 >< 〇〇 x ノ / - ョン chmod コマンド 則回も説明したように、ファイルのパーミッションを変 更できるのは、そのファイルの所有者だけです。そのファ す。 105 UNIX MAGAZINE 2002.6
2 し inux のプートプロセス 図 3 セグメントデスクリプタ ~ 63 32 40 39 48 47 46 45 44 43 S タイプ A べース ( 23 … 16 ) P DPL 56 55 54 53 52 51 G D ( .. 16 ) べース ( 15...0 ) べース ( 31 ... 24 ) リミット ( 15.. 0 ) 0 16 15 31 表 2 セグメントのタイプ メントの範囲を超えるアドレスにアクセスしないように 意味 命令を実行する前に論理アドレスのオフセット値をチェ ツ 0 読出し専用データセグメント クします。プログラムカ危囲タ ) アドレスにアクセスしよ 1 読み書き可能データセグメント 2 言売出し専用スタック・セグメント うとすると、 CPU はその命令の実行を中断して OS に制 3 読み書き可能スタック・セグメント 御を移します ( 図 2 ) 。 4 実行専用コードセグメント セグメントの大きさは、セグメントデスクリプタの G 5 実行と読出し可能コードセグメント フラグとリミット・フィールドで定義されます ( 図 3 ) 。 G 6 実行専用コンフォーミングコード・セグメント 7 実行と読出し可能コンフォーミングコード フラグがクリア ( 0 ) されている場合、リミット・フィー セグメント ルドの値はセグメントの大きさをバイト数で表し、反対に G フラグがセット ( 1 ) されている場合は、セグメントの 徴があります。そこで、スタックポインタがリミットを超 大きさを 4KB 単位て表します。 えた ( 領域が足りなくなった ) 場合にリミット値を小さ つまり、オフセットとリミットの聞系は次のようになり く再設定すれは領域拡張に対応しやすいからではないかと ます。 田います。 ノじ、 ただし、 Linux では前回説明したように、基本フラット G=O : 0 オフセットリミ モデル 2 を用いているため、リミット境界に反するアクセ ス違反は発生しません。 たとえは、 タイプチェック G=O, リミット =7FFFH 表 2 に示したセグメントのタイプは、データセグメン ト ( 0 ~ 3 ) とコードセグメント ( 4 ~ 7 ) に大別できます。 の場合、セグメントの大きさは 32KB で、有効なオフ CPU はこれらの違いを識別し、セグメント・レジスタに セット値は 0 から 7FFFH までとなります。このとき、 セレクタをロードするときに以下のタイプチェックをおこ 8000H 以降のアドレスにアクセスしようとすると、一矍 ない、誤ったアクセスガ去を防ぎます。同時に、セレクタ 機能によってアクセスが中断されます。 のインデックス値がデスクリプタ・テープルの大きさを超 一方、スタックタイプのセグメントの場合俵 2 ) は、 えていないかどうかも石忍します ( 図 4 ) 。 アクセス可能な観肋になります ( 図 2 ) 。 ・ CS レジスタ ・ G = 0 の場合 CS レジスタにはコードセグメント ( タイプ 4 ~ 7 ) のセ ミット < オフセット FFFFFFFFH レクタのみロードできます。また、 CS レジスタには 0 ・ G = 1 の場合 のセレクタ 3 をロードできません。 ミット x4KB) < オフセット FFFFFFFFH ・ DS 、 ES 、 FS 、 GS レジスタ これらのレジスタには、データセグメント ( タイプ 0 ~ スタックタイフ。のセグメントでアクセス可能な創用力 になるのは、おそらく次のような理由からでしよう。 IA- 2 大きさが 4GB のセグメントをイ及するモデル。 32 のスタックには、一上位から下位へ伸びていくという特 3 、セグメント・レジスタを無効にする " といナ未をもちます。 G=I : 0 < オフセット ( リミット x 4KB) 33 UNIX MAGAZINE 2002.6
オプションの角財斤では、 debug オフションを処理する 部分ですこし朱なことをしています。 getopt 関数を使 う場合、オフションは 1 文字のものしか認識できません。 これは getopt 関数の信様なので変えられません。しかし telnetd では、この debug だけか文字列のオプションと して定義されています。 -debug ではなく -d にすれば簡 単なのですが、このようにした理由はよく分かりません。 telnetd プログラムの作者はこの問題の解決策として、 getopt 関数に対しては一 d オプションのみを定義し、そ れに ebug という引数が付いているかどうかを調べるガ去 を採用しています。 getopt 関数では、オプション窈日疋 時に d : と言当すれば、 -d を引数をとるオプションとして 定義することができます。この機能を使って、 -debug が 指定されたときに、 -d オプションとその引数として文字 列 ebug カ甘旨定されているかどうかを調べています。 case ) d : if (strcmp(optarg, "ebug") debug + + ; break ; usage() ; / * NOTREACHED * / bre ak ; 上のコードを見ても分かるように、オプションとして -d カ甘旨定されたときはその引数を調べ、 ebug であれば debug オプションカ甘旨定されたとみなします。引数がそ オび人タ ) 文字列の場合は、誤ったオプションカ甘旨定されて いると判断し、 Usage 出力を出力してプログラムを終了し ます。 ただし、 getopt ライプラリ関数を利用していることで イ I' 合な部分はどうしても出てきます。たとえはこのコー ドでは、—d ebug と指定したときにも debug オプショ ンカ甘旨定されたと認識してしまいます。もっとも、普通の 使い方でこのような指定をすることはます考えられないの で、これでよいのかもしれません。 オプションの解析か終ると、 debug オプションカ甘旨定 された場合の処理か読きます。前回紹介したようにこの 部分のコードでは inetd から起動するのではなく、自分自 身でソケットを用意して接続を受理するための処理をおこ ないます。この処理を終えた時点で、ファイル・ディス クリプタの 0 が、受理したネットワークの孑を表すディ スクリプタとなっています。これは、 inetd から起動した UNIX MAGAZINE 2002.6 プログラミング・テクニック 場合も、 debug オプション付きて起動されて接続を受理 した場合も同じです。 次に、 openlog ライプラリ関数を使ってログの準備を します。 openlog ( "telnetd" , LOG—PID ー LOG—ODELAY , LOG_DAEMON) ; telnetd では、ログの名前を telnetd 、ファシリティを daemon とすることが分かります。ファシリティはログ の不頁を指定するもので、システムのデーモン・プログラ ムも daemon を利用しています。 次は接続元の情報の恥等です。凾に考えると、 accept システムコールの段階で相手側の情報か陬得できるのに どうしてここでまた取得するのだろうと疑間に思うかもし れません。 telnetd では、自分で accept するだけでなく、 inetd からクライアントと接続した状態て呼び出されるこ ともあります。このどちらの場合にも正しく重川乍するよう に、 accept の段階で得られる情報は使わす、ここで新た にクライアント窈青報を取得するわけです。 fromlen = sizeof (from) ; if (getpeername ( 0 , (struct sockaddr * ) &from, -exit(l) ; warn("getpeername") ; &fromlen) く 0 ) { 79 警告を出さないように、 / * NOTREACHED * / という doit は終了することのない関数ですが、コンパイラが return(O) ; / * NOTREACHED * / doit ( (struct sockaddr * ) &from) ; ます。 理をおこなう doit 関数を呼び出し、 main 関数は終了し こて取得したクライアントの情報を使って、実際の処 数のアドレスです。 体 ) のアドレスと、その構造体のサイズをオ褓内した整数変 はこれに類する特定のプロトコルに依存したアドレス構造 様の値を指定します。つまり、 sockaddr 構造体 ( もしく ます。第 2 、第 3 引数には、 accept システムコールと同 取得したいクライアントか接続しているソケットを指定し リ関数を利用します。この関数の第 1 引数には、情報を クライアント情報の取得には getpeername ライプラ
連載 / IPv6 の実装ー① 図 4 ループパック・インターフェイスへの出力ー里 2245 sendpkt : 2254 2264 2265 2266 if ((ifp—>if—flags & IFF—LOOPBACK) ! = 0 ) { return( (*ifp->if—output) (origifp, m, (struct sockaddr *)dst , ln-hold を解放していることから分かるとおり、 KAME の近隣キャッシュがデータリンク層アドレスの鮹夬処理の あいだに溜めておける IP バケットは 1 つだけです。 ln—>ln—expire く time—second) { nd6_mmaxtries & & if (ln—>ln—asked く (ln—>ln—expire) { 2 , 234 ~ 2 , 242 行目は、近隣要請バケットの送信処理で 2236 2235 2234 if す。 time_second 十 2238 ln—>ln_expire 2237 ln—>ln_asked 十十 ; トを送信します。 一定時間経過していたら ( 2 , 236 行目 ) 、近隣要請バケッ を超えておらす ( 2 , 235 行目 ) 、かつ以前の近隣要請から 近隣要請バケットの最大再送回数 (nd6-mmaxtries) 2239 nd—ifinfo [ifp—>if—index] . retrans / 1000 ; 近隣要請バケットの氾濫を防ぐために、最大再送回数と 再送間隔で蒲剏しています。 KAME では、再送間隔はイ ンターフェイスごとに設定可能で、初期値は 1 秒になっ ています。 2240 2241 2242 2243 nd6—ns-output (ifp , dst , NULL , 1 Ⅱ , 0 ) ; return(0) ; データリンク層アドレスがまだ判明していないので、 イスへの出力について特別な処理をおこなっています。出 図 4 の 2 , 254 行目では、ルーフ。バック・インターフェ る場合は、そのままバケットを送信することができます。 探索か不要なネットワーク・インターフェイスを使ってい データリンク層アドレスかすでに分かっていたり、近隣 データリンク層出力ルーチンの呼出し ケットを送信します。 2 , 240 行目で nd6-ns-output() を呼び出し、近隣要請パ 68 カ先のインターフェイスがルーフ。バック・インターフェイ スになるのは、以下の 2 つの場合です。 ルーフ。バック・インターフェイスのアドレスにバケット を出力する ( たとえは、終点アドレスが、、 : : 1 " のバケッ トを出力する場合 ) 。 ・自分自身のネットワーク・インターフェイスに設定され ているアドレスに出力する。 KAME では、自分自身のネットワーク・インターフェ イスがもつアドレスに対する経路が、ループバック・イン ターフェイスを向きます。経路情報での出力インターフェ イスはルーフ。バック・インターフェイスですが、実際に は別のネットワーク・インターフェイスです。この場合 は、茁妾ルーフ。バック・インターフェイスに出力するので はなく、実際のネットワーク・インターフェイスである origifp に出力しなければなりません ( 2 , 264 行目 ) 。 2276 return((*ifp—>if—output) (ifp, m, (struct sockaddr *)dst, (t)) ; そうでない場合は、出力インターフェイスとして指定さ れた i ゆに IP バケットを出力します。 の出力処理の手順は以下のようになります。 て送信先のデータリンク層アドレスを調べます。近隣要請 ク層アドレスか判明していない場合は、近隣要請を出力し なければ出力できません。バケットの出力時にデータリン IP バケットは、データリンク層アドレスが分かってい 近隣要請の出力処理 ものです。 以下、とくに明記しないかぎりコードは nd6-nbr. c の 3. 近隣要請バケットの送信 2. オプション処理 1. 近隣要請バケットの構築 UNIX MAGAZINE 2002.6
連載 JavaServer Pages— 図 18 旅彳赭・に対して新するメッセージ (taxfree. html) 図 19 旅彳赭ではない場合研見客画面 (taxation ・ jsp) なフル旧編集 ) 表示素 ) シャンプゆプマ旧 ) タスクヘルプ⑧ - ファイ弗表示 (Y) 強常ジャンプ 0 プめ、ゆ但 ) タスク田へルプせ ホーム、複常朝カクマ、を”。、新着、、お都ゆ、メンバーズ ホーム犢常朝カりマー第いを““新着、お宿物′ー 値札の金額が 2002 円の消費税の税額は 95 円です。 旅行者は免税です。 消費税の税額は 0 円です。 図 20 消費税を計算して表示する taxation ・ jsp べージ く % page contentType="text/htm1 ; charset=EUC—JP" % > く % page import="tax. * " % > く % page errorPage="goform. html" % > く ! DOCTYPE HTML PUBLIC "—//W3C//DTD HTML 4 . 0 TransitionaI//EN"> く html > く head> く meta http—equiv="Content—Type " content="text/html ; charset=EUC—JP"> く title > 消費税額の計算く / title > く /head> 油曹尉ⅱーいにいを 、キー 1 黔者一第い [ 諏をう 角同ロ く body> type="tax. Tax" scope="request" / > く Jsp:useBean id="taxBean' 値札の金額が property= price" / > 円く / b > く b> く j sp : getProperty name="taxBean の消費税の税額は property="tax" / > 円く / b > く b> く j sp : getProperty name="taxBean' です。 く /body> く /html> 消費税額をバする 2 ページ目の処理は、旅行者かどう ページの内容です。 かによって異なります。 t 算に使う JavaBean やメッセージを表小する処理な どは、 beanName 属性の説明の際にとりあげたサンフ。ル 旅行者の場合の里 コード tax. jsp と同様てす。ただし、 taxation ・ jsp ペー 旅行者の場合に ( 訂見額を引算する必要はないので、つね ジ内ではオプジェクトを生成せす、 に図 18 のようなメッセージを表示する HTML ファイル く Jsp:useBean id="taxBean' type="tax. taxfree. html を呼び出すだけです。 taxfree. html では特 scope="request" / > 別な処理はおこなわないので、 HTML のソースコードは によって request スコープに保存されている taxBean 割愛します。 オプジェクトを取り出し、プロバティの取得に使ってい 旅行者ではない場合の里 ます。 旅行者ではない場合は、 taxation. jsp ページを呼び出 例外が発生したとき し、指定された言夥見方式 ( 外税か内税か ) に従って税額を すでにお話ししたように、正しい手順を経すにいきなり 表示します。図 19 は、 taxation ・ jsp を表示したプラウザ taxation. jsp ファイルにアクセスすると、 taxBean オプ の画面 ( 内税の場です。また、図 20 は taxation ・ jsp 一三ロ 92 UNIX MAGAZINE 2002.6