filter - みる会図書館


検索対象: UNIX MAGAZINE 2003年12月号
10件見つかりました。

1. UNIX MAGAZINE 2003年12月号

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 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 連載 / Pe 日活用のヒント $self->{relayfork} warn "—relayfork is not allowed under if ( $self->{relayfork} ) { if ( $self->{threads} ) { —threads . \n" if ( $ 0 eq "MSWin32" ) { ( $self → {daemon} ) { if if else { warn iS not supported OII Windows . $self—>{daemon} = 0 ; ( $self → {relayfork} ) { warn "—relayfork is not supported 0 Ⅱ Windows . \n" $self—>{relayfork} $self—>{relayfork} $self; 1 unless ( defined($self—>{relayfork}) ) ; # Direction specific filters are defined here . # These are Ⅱ u11 in this class . # Some of sub classes would have non Ⅱ u11 filters . sub req—filter { } sub res—filter { } sub forward { # forward from $from tO $to unidirectionary ( $recordfilename ne " filter" $req_or_res my $filter my $recordfh; ($self , $from, $to, $req-or-res , $recordfilename) if my if ( $recordfh = IO: :Fi1e—>new()> $recordfilename") ) { my $block; warn "open: > $recordfilename : else { binmode($recordfh) ; $recordfh—>autoflush(l) ; close($to) or warn "close: > : $req—or_res : $ ! \n" close($from) or warn "close : く : $req_or—res : $ ! \n" shutdown($to, 1 ) ; warn "record failed: $req-or-res : $ ! \ Ⅱ " print $recordfh $block or if ( $recordfh ) { warn "output failed: $req—or-res : $ ! \ Ⅱ " print $tO $block or $self → $filter(\$block) ; while ( sysread($from, $block, BLOCKSIZE) ) { UNIX MAGAZINE 2003. 12 81

2. UNIX MAGAZINE 2003年12月号

連載 / Pe 日活用のヒント UNIX MAGAZ 工 NE 2003. 12 こなえることである。私は Web アプリケーションの開発 になることが多いちょっとした機能拡張や変更を気軽にお そもそも relaytcp を PerI で書く利点は、その場かぎり 指向になったのである。 たり、コーディングや機能をみなおす過程でオプジェクト サプルーチン呼出しの形式だった。連載でとりあげるにあ relaytcp も、最近まではオプジェクト指向ではなく甬の C 言語で書いたことがある。じつをいうと、 perl で書いた ない。私はしばらく前に、 relaytcp のようなプログラムを ト指向にすることでプログラミングが容易になるわけでは relaytcp がおこなう TCP 通信の中継は、オプジェク TCP. pm かオブジェクト指向である理由 している。 中継先からの HTTP 応答の両方を書き換えたうえで中継 なわれる。具イ柘勺には、クライアントからの HTTP 要求、 filter は空ではないので、中継データに対して処理がおこ : :TCPHTTPHostHack クラスでは req-filter と res- あるいは res-filter メソッドカ剛乎び出される。 Net::Relay nofork メソッドカ剛乎び出されると、そのなかで req-filter て、 (TCP. pm で定義された ) forward あるいは relay- Net::ReIay::TCPHTTPHostHack オプジェクトに対し 以外は、 Net::ReIay::TCP のメソッドを継承している。 -filter と res-filter の 2 つのメソッドだけである。それ TCPHTTPHostHack クラスで定義されているのは、 req Net::ReIay::TCP のサプクラスである Net::Relay:: のデータは res-filter に渡される ( 図 3 ) 。 メソッドに渡される。逆に、中継先からクライアント方向 きたクライアントから中継先に向かうデータは req-filter 記述できるようにするためである。 relaytcp につないで req-filter や res-filter に中継内容に対する任意の処理を 「 es_filter() クライアント req-filter() re laytcp 図 3 req-filter と res-filter によるテータの受渡し 中継先 過程で、実際に以下の作業をおこなった。 ・ User-Agen フィールドでプラウザの種類を判断する web ページに、 PC のプラウザから i モードのふりを してアクセスしたい。そこで、 relaytcp に User-Agen を書き換える機能を加え、それを通して Web ページに アクセスした。 ・ web アプリケーションの表示に問題があり、助言を求め られた。 HTML の書き方の改善案を思いついたが、提 案する前に効果を確かめたい。そこで、従来の HTML を改善案に沿って書き換える機能を relaytcp に加え、そ れを通して Web アプリケーションにアクセスして効果 を確認した。 決まった機能をもつツールならどの言語で書かれている かは重要ではない。 relaytcp は標準の機能を使うだけでも 有用だと思うが、それだけでは使いこなしているとはいえ ない。自分で機能拡張を施してはじめて使いこなしている といえるだろう。 perl で書く利点である、、機能拡張を簡単に " を追求し た結果、 TCP. pm をオプジェクト指向で記述することに した。 TCP. pm をオプジェクト指向にし、 relaytcp に -class オプションを導入した結果、機能拡張や変更を本体 に手を加えすに最小限の手間でおこなえるようになった。 relaytcp の機能拡張は、多くの場合、以下のようにおこ なわれる。 1. Net::Relay::TCP のサプクラスを作り、そのなかの req -filter や res-filter に中継内容に対しておこないたい処 理をする。 2. 作成したサプクラスを—class で指定して relaytcp を 起動する。 69

3. UNIX MAGAZINE 2003年12月号

連載 / Pe 日活用のヒント 1 () 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 2 7 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 use our sub strict ; base 'Net: :Re1ay: %OPT_SPEC = req—filter { : TCP ' ・ my ($self , $blockref) my $rex = $self—>{req_filter—rex} ; my $rep = $self->{req-filter-rep}; unless ( $rex ) { my $hostname = lc $self->{hostname} ; my $hostname—re $hostname ; $hostname—re $hostname—re $hostname eq 'localhost ) ? ) (localhost) ) " ($hostname—re ー localhost) " my $localport $self—>{localport}; my $localport-re $localport : $localport" $self—>{req—filter—rex} $rex = qr/$hostname—re$localport—re/i ; my $targethost $self—>{targethost} ; my $targetport $self->{targetport}; my $targetport-str = $targetport 80 ? " " $self—>{req—filter-rep} $rep = $targethost s/$rex/$rep/g; sub res_filter { my ($self , $blockref) my $rex = $self—>{res_filter_rex}; my $rep = $self—>{res—filter-rep}; unless ( $rex ) { my $targethost—re $self->{targethost} ; $targethost—re my $targetport $self—>{targetport} ; $$blockref : $targetport " $targetport—str; my $targetport-re $targetport : $targetport " $self—>{res—filter—rex} $rex = qr/$targethost-re$targetport—re/i; my $hostname = $self—>{hostname}; my $localport $self->{localport} ; my $localport—str = $localport 80 ? " " $self—>{res—filter—rep} $rep = $hostname : $localport" $localport—str; $$blockref $$blockref $$blockref s/$rex/$rep/g; s/A(set—cookie: UNIX MAGAZINE 2003. 12 87

4. UNIX MAGAZINE 2003年12月号

連載 / Pe 日活用のヒント 公開 (export) していた。 relaytcp. pl は、おおよそ以下 チン ( メソッドではない ) があり、このサプルーチンだけを 変更前の TCP. pm には relay-server というサプルー クト指向にした未がより明確に理解できる。 説明しておこう。それが分かれば、 TCP. pm をオプジェ オプジェクト指向になる前の relaytcp について簡単に オプシェクト指向になる前の TCP. pm コマンド行の処理 sub main { sub res—filter { . sub req—filter {. use Net: :ReIay: :TCP; のようになっていた。 70 身は、基本的には relaytcp. pl から渡されたコマンド行オ こない、それ以外の処理はしていない。インスタンスの中 コンストラクタとしてインスタンス作成の操作のみをお new メソッド 説明である。続いてコードを具体的に解説する。 こまでが、 TCP. pm のコードを理解するための背景 る現在の手法のほうが好ましい。 のサプクラスに言し、そのクラスを relaytcp に指定す これにくらべると、拡張部分だけを Net::Relay::TCP の差異が生じてしまう。 最近作ったものではコマンド行の扱いカ少に異なるなど んできてしまう。そうなると、以前に作った機能拡張版と や res-filter だけが異なる relaytcp. pl のコピーがたくさ 張を気軽に " はかなり実現できている。しかし、 req-filter これでも、 perl で言する利点である、、ちょっとした拡 ある。 理を言古する。それから relaytcp-hacked. pl を使うので し、そのなかの req-filter や res-filter におこないたい処 をコピーする。たとえば relaytcp-hacked. pl にコピー その場かぎりの機能拡張をする場合は、まず relaytcp ・ pl いたのである。 それらのサプルーチンへの参照を relay-server に渡して relaytcp. pl のなかで req-filter や res-filter を定義し、 main() ; \&req-filter, \&res—filter) ; $localport , $recorddir, relay—server ($targethost , $targetport , プションの解析結果である。 new メソッドは、それに対し て以下の操作をおこなう。 データを実際に使用する形式に整える。 UNIX MAGAZINE 2003.12 ただし、 こではまだ標準ェラー出力をファイルに結び うが、 /dev/null でも間違いではない。 能性があるのでファイルに結び付けておくのがよいと思 ラー出力については、エラーメッセージが出力される可 のように /dev/null に結び付けることである。標準工 open(STDIN, " く /dev/null") ; 力については、 perl のプログラムでの正しい処理は、標準入力や標準出 してはならない。 でも起こる可能性があるので、これらも閉じたまま放置 バグの原因になる。同様のことは、標準入力や標準出力 これは、場合によっては再現性が低くデバッグの難しい つまりファイル言子 2 に出力するようになっている。 イプラリは、エラーメッセージや警告を標準工ラー出力、 使う可能性があるからである。また、 UNIX の各種のラ ログラムのなかで開いたファイルがファイル言杢子 2 を ァイル言杢子 (file descriptor) 2 ) が閉じられると、プ ま放置してはならない。なぜなら、標準ェラー出力 ( フ 大きな間違いである。とくに標準工ラー出力は閉じたま れらを閉じて放置しているプログラムも散見されるが、 ラー出力への対処が必要になる。デーモンになる際にこ 付けられていることが多い標準入力、標準出力、標準ェ ながりをなくす必要がある。そのためには、端末に結び プロセスをデーモンにする際には、起動した端末とのつ なし ) 。 デーモンにできないので—daemon オプションは使え あてはまらない。そもそも Windows ではプロセスを 以下は UNIX についての説明であり、 Windows には 311 行目 if ( $self- 〉 {daemon} ) { main メソッド ・関連するオプション間の整合性をとる。 ・プラットホーム特有の制限を課する。 ・必要な項目か第定されているかをチェックする。 設疋する。 明示的に指定されていないオプションにデフォルト値を

5. UNIX MAGAZINE 2003年12月号

連載 / Pe 日活用のヒント る。ただし、 %OPT-SPECI に含まれるオプションは、 ば、ファイルに出力する内容を標準工ラー出力にも出力す opt" に保存する。 -verbose オプションが指定されていれ という行が連続する形式でテキストファイル、、 . relaytcp. オプション名 : 値 解励鮗ったコマンド行オプションは、 store-opt サプルーチン は Net::ReIay::TCP のサプクラスである。 う。実際、 Net::Relay::TCPHTTPHostHack クラス Net::Relay::TCP のサプクラスになることが多いだろ をもつ必要がある。 -class オプションで指定するのは、 は、 Net::Relay::TCP と同様の外部インターフェイス my $fh = IO: :Fi1e—>new(" く $filename") or do { 込む。 store-opt によって保存されたオプションデータを読み retr-opt サブルーチン ファイルへの保存対象からは除かれる。 末尾のリスト 2 に TCP. pm を示す。以降では TCP. TCP. pm とができる。 、 IO::FiIe- 〉 new(" く $filename")" とすればこれを防ぐこ ラムはファイルを書込み用に開いてしまう。上記のように 〉を最初にもつ名前を指定すれば、 PerI のプログ name) とすると、ユーザーがファイル名として、、〉 foo" の が指定する場合がある。このとき IO: :FiIe- 〉 new($file- relaytcp. pl にはない機能だが、ファイル名をユーザー 用に開いてしまうのを防ぐためである。 くを付けているのは、想定外の状況でファイルを書込み をファイル名に含める必要はない。それにもかかわらす してほしい。ファイルを読込み用として開く場合は、 のように、ファイル名の前に くを付けていることに注意 68 Net::Relay::TCP クラスのコンストラクタで、唯一の new TCP. pm の各メソッドの概要 pm を解説する。 クラスメソッドである。 m am 外部からの呼出しカ誤定される唯一のインスタンス・メ ソッドである。このメソッドがクライアントからの接続 を受け付け、個々のクライアントに対してプロセスまた はスレッドを作成してその処理をおこなわせる。 relay main から呼び出され、クライアントと中継先のあいだ の双方向の中継をおこなう。 fork して各プロセスが 1 方向ずつ中継する。 forward relay から呼び出され、クライアントから中継先、ある いは中継先からクライアントのいずれか 1 方向のデータ 中幻医をおこなう。 relay-nofork relay と同様に、クライアントと中継先のあいだの双方 向の中継をおこなう。 relay との違いは、名前が示すと おり fork せず、 1 つのプロセスのままで双方向の中継 をおこなう点である。 forward にあたるメソッドは使わ ず、 relay-nofork 自体か双方向の中継をおこなう。 req-filter res -filter この 2 つのメソッドについては次項で説明する。 CIean —dir -clean オプションが指定されたときに main から呼び 出されるメソッドで、ファイルの消去をおこなう。 retr—count -clean オプションが指定されなかったときに main か ら呼び出されるメソッドで、以下の処理をおこなう。 1. 記録サプディレクトリの有無を調べ、ある場合はサプ ディレクトリ名の初期値を求める。 2. 言彖ファイル番号の初期値を求める。 req-filter と res-filter の働き req-filter と res-filter の両メソッドは、 forward と relay-nofork から呼び出される。しかし、いすれも中身 は空で何もしない。 forward や relay-nofork は、何もし ないメソッドをなせ呼び出しているのだろうか。それには もちろん理由がある。 Net::ReIay::TCP のサプクラスで、 UNIX MAGAZ 工 NE 2003. 12

6. UNIX MAGAZINE 2003年12月号

対策 、、自ホスト名 : 自ポート番号 " →、、中継先ホスト名 : 中継 連載 / Pe 日活用のヒント り、 TCPHTTPHostHack.pm で実装されている。おも を書き換えるのが -httphosthack オプションの効果であ 以上のような問題を解決するために HTTP 通信の内容 自ポート番号 " 、、中継先ホスト名 : 中継先ポート番号 " →、、自ホスト名 : 2. HTTP 応答の置換え 先ポート番号 " 1. HTTP 要求の置換え な処理は以下の 2 つである。 74 属性カ咐いていたら削除する。 れる Set-Cookie フィールドに expires または max-age 破算になる。具体的な処理としては、 HTTP 応答に含ま すれば、 relaytcp を通して設定された Cookie はすべてご Web プラウザの動作中にしている。 Web プラウザを終了 は HTTP 応答に含まれる Cookie の有効期限をすべて この問題への対処として、 TCPHTTPHostHack.pm org : 80 へ送ってしまう。 くと、 www.perl.org/80 からの Cookie を history. perl. の後、 Web プラウザで http://mars.pm.0rg:8000 を開 ポート番号を 8000 にしてふたたひ動かしたとしよう。そ め、中継先を別の Web サーバー history. perl. 0rg:80 、自 の Cookie として保存する。次に、 relaytcp をいったん止 org から送られてきた Cookie を、、 mars.pm.org : 8000 をセットすると仮定しよう。 Web プラウザは、 www.perl. : 80 だったとする。そして、 www.perl.org/80 は Cookie ポートで relaytcp か勠いていて、中継先が www.perl.org 理由は以下のとおりである。 mars ・ pm.org の 8000 番 送られる可能性がある。 は、ある Web サイトの Cookie が別の Web サイトに このままでは Cookie に関する問題が起きる。具体的に 以上で HTTP 通信の中継という目的は達成できるが、 Cookie への配慮 ある。 ポート番号は relaytcp カ続を受け付けるポート番号で 自ホスト名は relaytcp カ働いているホストの名前、自 末尾のリスト 3 に TCPHTTPHostHack.pm のコー ドを示す。見てのとおり Net::Relay::TCP のサプクラス である Net::Relay::TCPHTTPHostHack クラスを定 義している。このクラスでは req-filter と res-filter メソ ッドが定義されていて、それ以外は親クラスのメソッドを 継承している。 14 行目 our %OPT-SPEC = ( ) ; Net::ReIay::TCPHTTPHostHack クラスには独自 のコマンド行オプションはないので、 %OPT-SPEC は 空である。中身カ啌でもハッシュ自体は必要である。 16 行目 sub req-filter { 文字列の置換えの内容をメソッドカび出されるたびに 計算するのでは効率カいため、置換え内容をオプジェ クトに保存して繰り返し使っている。 38 行目 sub res-filter { reqT11ter メソッドと同様に、文字列の置換え内容を保 存して繰り返し使っている。最後の部分に Cookie 対策 カ第されている。 relaytcp の拡張方法 こまで読んだ方にはお分かりだと思うが、 relaytcp を 拡張するには Net::Relay::TCP のサプクラスに Net:: Relay::TCP との差分を言杢し、 relaytcp の起動時にそ れを指定すればよい。 PerI のクラスの親子関係はクラス名とは関係ないので、 新たに作る Net::Relay::TCP のサプクラスは MyFilter のようなクラス名でもかまわない。 relaytcp の限界 HTTP を中継 / 言泉するコマンドとして relaytcp を使 った場合、以下のような不便またはイ薪哈な点がある。 HTTP 要求 / 応答に対する処理の正確さ TCPHTTPHostHack.pm の処理は正確さに欠ける。 req-filter や res-filter は HTTP 要求 / 応答の全体に 適用されるとはかぎらず、中継されるデータの塊ごとに 適用されるからである。謝奐え対象の文字列が複数の部 コード UNIX MAGAZINE 2003. 12

7. UNIX MAGAZINE 2003年12月号

連載 / Pe 日活用のヒント 135 136 137 138 139 140 141 142 143 144 145 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 82 if ( $recordfh ) { close($recordfh) or warn 'tclose : record: relay { $req_or_res : sub use sub my ($self , $client , $target , $recorddir, my $fnamesub = $self—>{record} ? sub {"$recorddir/$- [ 0 ] -$count"} my $pid = fork; defined($pid) or die "fork: if ( $pid ) { $self—>forward($client , IO: :Se1ect; relay—nofork { else { $self—>forward($target, $target , $client, 'req $count) $fnamesub->("res") ) ; $fnamesub → ("req") ) ; $count) my my ($self , $client , $target , $recorddir, ($client = > $target, my %dest $target = > $client) ; ($client = > "req' %req_or_res $target = > "res") ; my %recordfh; if ( $self → {record} ) { foreach my $i ( ($client, $target) ) "$recorddir/$req-or-res{$i}-$count" my $filename if ( my $fh = IO: :Fi1e->new()> $filename") ) { warn "open: > $filename : else { binmode($fh) ; $fh->autoflush(l) ; $recordfh{$i} = $fh; 工 0 : :Se1ect->new($c1ient, $target) ; my $select $block; $self->$filter(\$block) ; " filter' my $filter = $req—or—res my $req—or-res $req-or-res{$src}; next ; $select—>remove($src) ; shutdown($dest , 1 ) ; sysread($src, $block, BLOCKSIZE) or d0 { my $dest $dest{$src}; foreach my $src ( @ready ) { while ( my @ready = $select—>can-read() ) { UN 工 X MAGAZ 工 NE 2003. 12

8. UNIX MAGAZINE 2003年12月号

連載 / Pe 日活用のヒント UNIX MAGAZINE 2003.12 る。 threads- 〉 new() にはサプルーチンへの参照を渡す クライアントの処理をさせる別のスレッドを作ってい 355 行目 my $thr = threads- 〉 new(sub { め、このようにしている。 ションを使わないかぎり問題カ起こらないようにするた る。 threads カ吏えない Per け竟でも—threads オプ は、これがコンパイル時に無条件で実行されるからであ グマが肩効になるようにしている。 use を使わない理由 -threads オプションが有効なときだけ threads プラ 354 行目 require threads; 化の残りの作業をおこなっている。 準工ラー出力をファイルに結ひイ寸けるといったデーモン IO::Socket::INET- 〉 new の処理を乗り切ったので、標 330 行目 if ( $self- 〉 {daemon} ) { ように設疋している。 カ絲冬了してしまう。そこで、 PIPE シグナルを無視する PIPE シグナルでプロセスが終了すると relaytcp 全体 クライアントを 1 つのプロセスで処理しているので、 しかし、 -threads オプションが有効な場合はすべての スが終了しても、影響が全体におよぶことはない。 理されるからである。 PIPE シグナルが発生したプロセ は問題にならない。各クライアントカ甥リのプロセスで処 PIPE シグナルは、—threads オプションが無効な場合 了である。 PIPE シグナルに対するデフォルトの動作はプロセス終 現象が発生し、 relaytcp が PIPE シグナルを受け取る。 しい手順を踏まずにソケットを閉じたときにそのような 了しない場合がある。ネットワーク障害カ起きたり、正 relaytcp のクライアントや中継先との通信が正しく完 324 行目 $SIG{PIPE} = 'IGNORE' ・ い作らないので、この設疋をする必要はない。 オプションが指定されている場合は子プロセスをいっさ ンビとして残らないようにする設定である。 -threads 前回に説明したように、子プロセスを wait しなくてもゾ ( $self- 〉 {threads} ) ; 323 行目 $SIG{CHLD} = 'IGNORE' unless からである。 を起こしたときに端末にエラーメッセージを出力したい い IO::Socket::INET- 〉 new が次に控えており、エラー 付けていない。その理由は、比較的工ラーを起こしやす こでは、、 sub {... } " によって作られた名前のな い (anonymous) サプルーチンを渡している。 この名前のないサプルーチンはクロージャとして機能す る。クロージャについてはコラムを参照してほしい。 365 行目 $self- 〉 relay-nofork($client, $target, $recorddir, $count) ; マルチスレッドで動いているプログラムを fork しては いけない。 fork をともなう relay を使うことはありえ ないので、 こでは無条件に relay-nofork を呼び出し ている。 373 行目 if ( $pid = マルチプロセス動作の場合は、クライアントからの接続 があると fork し、子プロセスにその処理をおこなわせ る。 374 行目 close($listen) ; 接続を受け付けるソケット $listen は、クライアントの 処理をする子プロセスには不要なので閉じる。 389 行目 if ( $supercount ne -supercount オプションが指定された場合は、記録サ プディレクトリを切り替えるべきかを判断する。切り替 える必要があれば、 $count を初期値に戻して $super- count を増やし、新たなサプディレクトリを作る。 relay メソッド 143 行目 my $fnamesub = $self- 〉 {record} 記録ファイル名を返すサプルーチンをクロージャとして 作り、 $fnamesub に代入している。 148 行目 if ( $pid ) { fork して、親プロセスがクライアントから中継先の方向 に、子プロセスが中継先から親プロセスの方向に中継を おこなっ。 forward メソッド 123 行目 while ( sysread($from, $block, BLOCKSIZE) ) { 8 , 192 バイトを上限として、現在届いているデータを読 み込む。 EOF を検出するとループから抜ける。 124 行目 $self- 〉 $filter(\$block); req-filter または res-filter メソッドを呼び出す。読み 込んだ内容を書き換えるかもしれないので、 $block への 71

9. UNIX MAGAZINE 2003年12月号

連載 / Pe 日活用のヒント れは、 HTTP 要求とそれに対応する HTTP 応答を調 るいは応答が 1 つの言泉ファイルに残ることになる。こ ごとに言求ファイルを作るので、複数の HTTP 要求あ の HTTP 要求 / 応答を送る。 relaytcp は TCP 接続 ていは HTTP/I.1 を使用し、 1 つの TCP 接続で複数 可能である。 web プラウザも web サーバーも、たい 1 では、 1 つの TCP 接続で複数の要求 / 応答の処理が HTTP 要求 / 応を送るだけである。一方、 HTTP/I. HTTP/I.0 の場合、 1 つの TCP 接続では 1 つの 1 つの TCP 接続での複数の要求 / 応 可能性があるが、そうはしていない。 果、 Content-Length フィールドの書寸奐えが必要になる 分にわたると : 割奐えがおこなわれない。また謝奐えの結 べるうえで不便である。 UNIX MAGAZINE 2003 . 12 ている以上は避けられない。解決するためには、 relaytcp 以上の不都合は、 relaytcp が TCP 通イ言全般を対象とし イト数とのあいだに矛盾が生じてしまう。 た結果、 16 進数で書かれたバイト数とデータの実際のバ となっており、 www.asahi.com を localhost に置換し データく改行 > 16 進数で書かれたバイト数く改行 > chunked 工ンコーディングでは、データの塊ごとに asahi.com/ は、、 localhost " に置き換えられる。 —httphosthack により、 HTTP 応のなかの、、 www. —hostname localhost —localport 8000 —target www. asahi. com : 80 \ $ relaytcp —httphosthack \ //localhost:8000/ を開いたとしよう。 コマンド行を実行したうえで、 Web プラウザから http: -httphosthack は正しく動作しない。たとえば以下の ed 工ンコーディングを使っているが、それに対して たとえば、 www.asahi.com はトップページに chunk- HTTP 応答に対して想定したような結果カられない。 だけでは、これらのエンコーディングが使われている を使用している。 req-filter メソッドを普通に記述した ーは、、 chunked" や gzip といったエンコーディング coding という概念が導入され、一部の web サーバ HTTP/I.1 では content encoding 、 transfer en- chunked 、 gzip などのエンコーディング SC 翡 好評発売中 ! プログラミング テクニック 00 を EC ON プログラミング テクニック UN Ⅸコマンドのソースコードにみる 多治見第和 践フロクラミング手法 0 ー d れ一 0 : をける・ ー第の、を増し . を ( ートになる工強贔といった まを一れ 0 をあり第す . そこには . プ 0 ム第第にを第な・がと つ ' と・、一れてい一す . yaCC x ′ SC ・多治見寿和著 ・ B5 判、 240 ページ OISBN 4-7561-4389- X ・ 1 , 800 円 + 税 生きたプログラムから学ぶ 実践的手法の数々 フリーの UNIX やアプリケーションのソース コードを見ながら、プログラミングにおけ る " 名匠の技 " を学ばうというのが本書の 目的です。長い年月をかけ、多くの人の手 ですこしすっ改良されてきたソフトウェア は洗練の度合いを増し、名匠の手になる工 芸品といった趣があります。そこには、プ ログラム開発に必要な技術がどっさりと盛 ( 本書より ) り込まれています。 目次から ソースコードから学ぶ◆データ構造◆ 2 重リンクリ スト◆木構造◆ AVL 木◆ハッシュ◆端末の操作◆端 末の制御◆ cat コマンド◆コマンド◆ファイルの ロック◆パスワード・ファイル◆ワンタイム・バスワ ード◆公開鍵暗号◆ Secu 「 e S ⅱ e Ⅱ◆構文の解析◆ yacc ◆ lex ◆ ping ◆ telnet ◆ ftp ◆ inetd ◆ xst 「◆ cmp と cksum ◆ man ◆フィルタコマンド (UNIX MAGAZINE 1997 年 1 1 月号 ~ 2000 年 3 月号より ) 株式会社アスキー 〒 1 60 ー 8584 東京都新宿区信濃町 34 J 日信濃町ビル 出版営業部電話 (03) 5362 ー 3800 75

10. UNIX MAGAZINE 2003年12月号

図 44 Apache での言綻変更 (MSG. conf) # cat /etc/httpd/conf.d/MSG.conf く Directory /var/www/htm1/MSG> AddDefau1tCharset ISO ー 2022 ー JP DirectoryIndex threads . html index. html く /Directory> り、 Namazu が解釈可能な文字コードに変換できなくなり ます ( 図の例では、変換後の HTML ファイルの文字コー ドは JIS になります ) 。 また、この文字コードに合わせて、 Apache の設定も変 更する必要があります。 make-namazu で、 MHonArc が生成する HTML ファイルを /var/www/htmI/MSG 以下のディレクトリに置くようにしています。ここに生成 されるのは JIS コードのファイルなので、 Web プラウザ に JIS コードであることを伝えるために、図 44 の内容 のファイルを /etc/httpd/conf.d/MSG.conf として作 成します。図 44 では、 URL にファイル名が含まれていな かったときに使われるインデックス・ファイル名も指定し ています。これで、 http : //mlsvr. example . jp/MSG/xp1an/ を参照したとき、 MHonArc が生成するスレッド形式のリ スト threads. html が表示されるようになります ( 時系列 のリストにしたいときは、 maillist. html を参照するよう にします ) 。 HTML ファイルを生成して、 Namazu 用のインデッ クス・ファイルを作成するには、 /var/www/html/MSG や /var/www/namazu/index/majordomo を作ってか ら、さきほどの make-namazu を実行します。 こで作成されたインデックス・ファイルを検索対象と するように . namazurc ファイルと template ディレクト リを用意すれば、 web プラウザから Namazu による検索 UN 工 X MAGAZINE 2003. 12 Lang Rep1ace /var/www/html/ / template TempIate /var/www/namazu/index/maj ordomo/ lndex /var/www/namazu/index/maj ordomo # CP /etc/namazu/namazurc . namazurc # cd /var/www/cgi-bin ができるようになります。 メーリングリストと情報共有 ロ 51 ウンロードできます。 11 http://mm.tkikuchi.net/NAMAZU-How-To.html からダ 相当します。これ以外のメーリングリストも検索対象に含 YSeries メーリングリストのアーカイプ・ディレクトリに archives/private 以下にある、 XPlan メーリングリスト、 いる xplan と yseries です。これらは、 /var/mailman グリストは、図 45 の 2 行目の LISTS 変数で設定して 存されます ( 図 46 ) 。このスクリプトで処理するメーリン され、 /var/www/namazu/index/mailman 以下に保 メッセージ・アーカイプを対象としてインデックスが生成 行すると、 /var/mailman/archives/private 以下にある この make-namazu をユーザー mailman になって実 す ) 。 の開発者のページで紹介されているものをもとにしていま クリプトを作成します ( 図 45 。この例は、 pipermail ・ pl 次に、インデックスを作成するための make-namazu ス text/plain text/html ; x—type=pipermail text/html ; x—type=mhonarc 対応メティアタイプ : # mknmz —C 、、対応メディアタイプ " に pipermail カ功日わります。 こうすると、、、 mknmz ー C " を実行したときに出力される イレクトリ /usr/share/namazu/filter にコピーします。 うに、 pipermail.plll を入手し、 Namazu のフィルタ用デ man の書庫にある pipermail 形式のファイルを扱えるよ で検索できるようにしましよう。まず、 Namazu が Mail- 次は、 MaiIman の書庫にあるメッセージを Namazu Mailman の書庫を Namazu で検索 e nd /var/mailman/archives/private/${mlname} -media—type= ' text/html ; x—type=pipermail ' \ /usr/bin/mknmz ー 0 ${IND}/${m1name} \ endif mkdir ${IND}/${m1name} if ( ! -d ${IND}/${m1name} ) then foreach mlname (${LISTS}) setenv LANG j a-JP . eucJP set 工 ND=/var/www/namazu/index/mai1man set LISTS=(xp1an yseries) #!/bin/csh —f 図 45 /var/mailman/bin/make-namazu