SC 翡 好評発売中 ! プログラミング テクニック 連載 / Pe 日活用のヒント ことが多いので、これらの POP3 コマンドに対応する ための準備もここでおこなう。具体的には、 1MAP4 の FETCH コマンドを発行して INBOX の全メールにつ いて RFC822. SIZE と UIDL を読み込んでおく。そし て、 RFC822. SIZE の値を合計して POP3 の STAT コマンドに返すメールの合計バイト数を引算しておく。 初期の POP21MAP. pm では、 P()P3 の PASS コマ ンドに対して IMAP4 の LOGIN と SELECT しか発 行していなかった。そして、 POP3 の STAT 、 LIST 、 UIDL の処理で相互にデータを共有することもなかっ た。そのため、 POP3 の要求が STAT 、 LIST 、 UIDL と続いた場合、そのつど IMAP4 サーバーに、、 FETCH 1 : メール数 (rfc822. size)" または、、 FETCH 1 : メール 数 (uid)" を送っており、無駄があった。 STAT PASS コマンドを処理した段階で、 STAT コマンドへ の応答であるメールの数と合計バイト数は分かっている のでそれを返す。 IMAP4 サーバーへの要求は発生しな し ) LIST PASS コマンドを処理した段階で、 LIST コマンドへの 応答のデータを用意してあるのでそれを返す。 IMAP4 サーバーへの要求は発生しない。 UIDL PASS コマンドを処理した段階で、 UIDL コマンドへの 応答のデータを用意してあるのでそれを返す。 IMAP4 サーバーへの要求は発生しない。本来なら、メールの UID 属性の値だけではなく、 INBOX フォルダの UID- VALIDITY の値と UID 値とを組み合わせたものを POP3 クライアントに送るべきである。しかし、 IN- BOX の UIDVALIDITY か変わることはほとんどな いと考えられるので、この値は無視している。 UIDVALIDITY とは各フォルダ固有の整数値であり、 図 9 に示すように SELECT コマンドでフォルダを選 択した際に返される。 RETR メール番号 ます、 IMAP4 サーバーに、、 FETCH メール番号 (rfc 822 厂という要求を発行する。返されてきたデータの行 . があった場合、それを、、 .. " に置き換えたうえ で POP3 クライアントに送る。このままだと IMAP4 み 、グ 一ンク尠 グクト : ロテ ' プ ・多治見寿和著 ・ B5 判、 240 ページ ・ ISBN 4-7561-4389- X S ロー ・ 1 , 800 円 + 税 生きたプログラムから学ぶ 実践的手法の数々 フリーの UNIX やアプリケーションのソース コードを見ながら、プログラミングにおけ る " 名匠の技 " を学ばうというのが本書の 目的です。長い年月をかけ、多くの人の手 ですこしすっ改良されてきたソフトウェア は洗練の度合いを増し、名匠の手になる工 芸品といった趣があります。そこには、プ ログラム開発に必要な技術がどっさりと盛 り込まれています。 ( 本書より ) 目次から ソースコードから学ぶ◆データ構造◆ 2 重リンクリ スト◆木構造◆ AVL 木◆ハッシュ◆端末の操作◆端 末の制御◆ cat コマンド◆コマンド◆ファイルの ロック◆パスワード・ファイ丿レ◆ワンタイム・バスワ ード◆公開鍵暗号◆ Secu 「 e She Ⅱ◆構文の解析◆ yacc+lex ◆ ping ◆ telnet ◆ ftp ◆ inetd ◆ xst 「◆ cmp と cksum ◆ man ◆フィルタコマンド (UNIX MAGAZINE 1997 年い月号 ~ 2000 年 3 月号より ) 株式会社アスキー 〒 1 60 ー 8584 東京都新宿区信濃町 34 J 日信濃町ビル 出版営業部電話 (03) 5362 ー 3300 71 UN 工 X MAGAZ 工 NE 2004.2
連載 / Pe 日活用のヒント * OK [PERMANENTFLAGS (\Seen \Answered \F1agged \De1eted \Draft $MDNSent) ] Permanent flags * FLAGS (\Seen \Answered \F1agged \De1eted \Draft $MDNSent) * 76 RECENT * 749 EXISTS 001 select inbox 000 OK LOGIN completed. 000 login himazu XXXXXXXX * OK IMAP4rev1 server ready. Escape character iS Connected tO imap—server . $ telnet imap—server 143 図 8 telent による IMAP4 サーバーへのアクセス * OK CUIDVALIDITY 959 ] UIDVALIDITY value * OK CUNSEEN 1 ] ls the first unseen message 001 OK [READ—WRITE] SELECT completed. . SIZe uid) signing 0ff . 003 logout 002 OK FETCH completed. * 4 FETCH (RFC822. SIZE 3008 UID 22697 ) * 3 FETCH (RFC822. SIZE 139778 UID 22696 ) * 2 FETCH (RFC822. SIZE 1693 UID 22695 ) * 1 FETCH (RFC822. SIZE 3602 UID 22694 ) 002 fetch 1 : 10 ( て fC822 * BYE IMAP4rev1 server 1. IMAP4 サーバーは、接続を受けるとただちに以下の形 IMAP4 の通信は以下の手順で進む。 IMAP4 の通信の流れ 要求と応答における改行は CRLF である。 はできないし、よぶんな空白があってもいけない。 つだけ入れる必要がある。空白の代わりにタブを使うこと だ、複数の引数のあいだには文字コード 0X20 の空白を 1 タグとコマンド名のあいだや、コマンド名と引数のあい コマンド名の大文字と小文字は区別されない。 れることを想定しなければならない。 とがあるため、どの要求に対する応答でも複数の行が返さ 応には要求で明示的に求めていない情報が含まれるこ Connection closed by foreign host . 003 OK LOGOUT completed. 6. セッションを終了する。 5. 別のフォルダを扱う場合は 3 へ戻る。 4. メールの言囚みなどをおこなう。 3. フォルダを選択する。 2. ューザー認証をおこなう。 * OK メッセージ 式の応を返す。 68 ューザー認証 RFC3501 では、認証のためのコマンドとして LOGIN と AUTHENTICATE を規定している。 pop2imap で は、 POP3 の USER 、 PASS の両コマンドによる認証し か実装していない。したがって、認証のための IMAP4 コ マンドとして使用するのは LOGIN コマンドのみで、 AU- THENTICATE コマンドは利用しない。 図 8 の例をみても分かるように、 LOGIN コマンドには 引数としてユーザー名とパスワードを渡す。 フォルダ pop2imap は、その性質上 INBOX 以外のフォルダを こではフォルダについて最低限必 扱う必要がないので、 UNIX MAGAZ 工 NE 2004.2 る。 ・フォルダ名は、、 . " を使って階層構造をもっことができ フォルダ名については大文字と小文字は区別されない。 は実装依存と規定されている。ただし、 INBOX という ・メールフォルダ名の大文字と小文字を区別するかどうか ルダである。 要な事柄を述べるに留める。 INBOX はメールが届くフォ
連載 / Pe 日活用のヒント ルを取り出すだけで、メールを送る仕組みは提供しない。 あるだけで、フォルダの概念はない。また、 POP3 はメー POP3 サーバーには各ユーザーの郵便受けが 1 っすっ POP3 サーバーに telnet でアクセスすると、以下のよ POP3 の要求 / 応答の形式 うになる。 $ telnet pop—server 110 Connected tO pop—server. Escape character is + OK POP3 Server starting. user himazu + OK Password required: himazu pass XXXXXXXX + OK himazu has 189 messages ( 739333 1ist + OK 189 messages ( 739333 octets) 1 3104 2 1770 3 5152 4 2330 quit Connection closed by foreign host . octets) POP3 の要求の形式は以下のとおりである。 コマンド名 [ 引数・・・・・・ ] POP3 の応答は以下のいずれかである。 + OK メッセージ —ERR メッセージ ただし、要求によっては十 OK の行に続いて複数の応答 . のみの行で応答の終端が表される。上記の 行カき、 例では、 LIST 要求に対する応か馥数行になっている。 このほか、 POP3 全体に関しては以下のような規定が ある。 ・コマンド名の大文字と小文字は区別されない。 これに対して、応答の、、十 OK " 、、 -ERR" は大文字でな ければならない。 要求と応答における改行は CRLF である。 POP3 の通信の流れ POP3 の通信は以下の手順で進む。 UN 工 X MAGAZ 工 NE 2004.2 1. POP3 サーバーは、接続を受けるとただちに以下の形式 の応答を返す。 + OK メッセージ 2. ューザー認証をおこなう。 3. メールの言茫囚みや削除などをおこなう。 4. 通信を終了する。 クライアントが POP3 サーバーに接続してから切断す すれは澵しく届いたものを判断できるが、それではあまり メールをすべて読み込んで、以前に読み込んだものと比較 判断する材料としては十分とはいえない。郵便受けにある ト数は目安になるが、すでに読み込んだメールかどうかを どこまで読んだかを確実に判断できないからである。バイ れだけだとサーバーにメールを残したときに不便である。 メールの番号はセッション中しか有効ではないので、そ 不変の識別子 (Unique ID) けにあるメールにはつねに 1 から順に番号カ咐いている。 い。新しい POP3 セッションが始まった時点では、郵便受 は変わらないが、セッションを越えて保存されることはな にはその番号を指定する。番号は POP3 のセッション中 から始まる番号カ咐いており、メールの取出しや削除の際 郵便受けに入っている個々のメールには、届いた順に 1 メールの指定 スワードを指定する。 コマンドでは引数でユーザー名を、 PASS コマンドではパ 場面も限られるだろう。上記の例で分かるように、 USER いても、私はいまのところ必要性を感じていないし、使う 川いロ 師に相当する機能がない。また、その他の認証方法につ 認証しか実装していない。そもそも IMAP4 には APOP pop2imap では、 USER 、 PASS の両コマンドによる 1 つは実装していなければならない。 る。いずれも必彡頁ではないが、 POP3 サーバーは最低でも ている。さらに RFC1734 では別の認証方法を規定してい 組合せによる認証と、 APOP コマンドによる認証を規定し RFC1939 では、 USER コマンドと PASS コマンドの ユーザー認証 るまでを、 POP3 のセッションと呼ぶ。 にも効率カい。 65
連載 / Pe 日活用のヒント Cygwin での inetd および xinetd 研リ用 Cygwin では、いくつかのデーモンが Windows の、サービ ス " として利用できる。 Windows のサービスとは、 UNIX のデ ーモンに相当する機能である。 Windows のサービスは、 UNIX のデーモンと同様に OS 走カ時に自動的に走力され、 OS の動作 中は他のプログラムからの要求を受け付けてサーピスを提供する。 たとえば、 Cygwin の inetd は自身を Windows のサービ cygrunsrv —S inetd 下のコマンド行を実行する。 dows を再走明」ゼーずにサービスとして inetd を師カ・するには、以 dows の走カ時に自動的に inetd カ位ち上がる。登録後、 Win- でおこなえる。 inetd をサービスとして登録してしまえば、 W ⅱト inetd ——remove—as—servlce で、削除は、 inetd ——install—as—service スとして登録、削除する機能をもっている。登録は、 UNIX MAGAZINE 2004.2 ケージは、名前が示すとおり init カ駛うシェル・スクリプト群で ら起動されることを前提にしているのである。 initscripts パッ つまり xinetd は、 sysvinit パッケージに含まれる init か 2003 ー 01 / mSg00000. html ・ http://sources.redhat.com/ml/cygwin-announce カ雛奨されている。 initscripts 、 chkconfig の各パッケージも同時に利用すること にあるアナウンスを読むと、 xinetd を利用する際は sysvinit 、 ので Windows のサービスとして利用できない。以下の URL いばかりか、フォアグラウンドで動かすためのオプションもない 一方、 xinetd には一—install—as—service オプションがな る必要がある。 合、 inetd の引数に—d を指定し、フォアグラウンドで動作させ cygrunsrv コマンドで Windows のサーピスとして登録する場 監視したり停止できることが求められる。したがって、 inetd を フォアグラウンドで動作し、サービス管理の仕組みか勠 ( 糾犬況を ある。これに対して、 Windows のサービスとなるプログラムは スは終了し、子プロセスが実際のデーモンとして動作するからで り UNIX のデーモン ) は、走」するとすぐに fork して親プロセ スとして動作しない。なぜなら、 Cygwin のデーモン ( というよ ためのコマンド行オプションを cygrunsrv で推定してもサービ Cygwin に含まれているデーモンは、デーモンとして起動ーす - る grunsrv の使い方カ第当されている。 に読み込まれる。このなかの cygrunsrv. README に cy- ダウンロードすると、ソースファイルが /usr/src/cygrunsrv* にも、 Cygwin の setup コマンドで cygrunsrv のソースを cygrunsrv ー—help" で使い方の概要が表示される。このほか なうことができる。 cygrunsrv にはマニュアルページはないが、 cygrunsrv はサービスの開始のほか、中止、る点削除もおこ あり、 chkconfig は init の設疋作業を便利にするツールである。 ではここで、 xinetd 、 sysvinit 、 initscripts 、 chkconfig の 各パッケージがインストールされていることを朝豺是に、 xinetd を 使えるようにする手川頁をおおまかに説明しよう。 init を使い始めるためのコマンドとして、 init-config が用意 されている。これを実行すると、最初に /etc/inittab を上書き するかを訊かれる。 initscripts パッケージには /etc/inittab が含まれている。 init-config が作成する inittab は信用でき ないそうなので、最初の質問には no と答えるのがよさそうであ る。それ以外の質問に yes と答えると、 init の初期設疋がおこな われ、 Windows のサービスとして登録されて走」される。 init から走明」されるデーモンは、 /usr/sbin/chkconfig コマンドを 使って登録、削除、変更をおこなう。 chkconfig はあくまでも設 定ファイルを変更するだけなので、このコマンドを実行しただけ では新たに登録したデーモンは走師力されない。 chkconfig で新た に登録したデーモンを起動するには、たとえば以下を実行してラ ンレベルをいったん下げ、再度 - ヒげる操作をおこなう。 /sbin/telinit 0 /sbin/telinit 3 これで init については準備ができたので、次は xinetd であ る。 xinetd-config を実行すると、 xinetd の成疋ファイルが生 成される。 xinetd は /var/lock/subsys ディレクトリを使う のでこれを作成し、ユーザー SYSTEM かグループ Adminis- trators カき込めるようにしておく。これは、 init から走師力さ れるデーモン (xinetd を含む ) が、上記のユーザーやグループで 動作するからである。具体的には、たとえば以下のコマンド行を 実行する。 chown SYSTEM : Administrators /var/lock/subsys chmod 770 /var/lock/subsys さらに、 /var/log もユーザー SYSTEM かグループ Ad- ministrators カき込めるようにしておく。 続いて、 chkconfig コマンドで xinetd を登録し、 init から xinetd か徒師力されるようにする。 /usr/sbin/chkconfig ——add xinetd そのうえで、さきほど述べたようにランレベルを下げ、ふたた び上げれば xinetd か徒力される。 このように、 xinetd を使うには init の設疋が必要で敷居が 高い。しかし、 init を使うことには大きな利点がある。 init が Windows のサービスとして登録されていれば、それ以外にサー ビスとして Cygwin のデーモンを登録する必要はなく、すべて init から起動づ - ればよいのである。さきほど述べたように、 Cyg- win のデーモンは普通にデーモンとして起動しても Windows のサービスにならないが、 init から走明」されるのであればそのよ うな心靴は無用である。 63
特集 図 24 PPTP 車の / ヾッチを適用 pptp—conntrack-nat . patch NOT APPLIED ( 8 missing files) Testing. The extra/pptp¯conntrack—nat patch : Author : Hara1d We1te く laforge@gnumonks . org> Status : Beta DO you want t0 apply this patch [N/y/t/f/a/r/b/w/q/?] y 図 25 GRE と PPTP をサポートするか ? GRE protocol support (CONFIG-IP-NF-CT—PROTO_GRE) [N/m/?] (NEW) PPTP protocol support (CONFIG—IP—NF—PPTP) [N/m/?] (NEW) 安全なネットワー ク② y を入力するのは、この 1 回だけです。あとはふたたび リターンキーを押し続けます。 コマンド・プロンプトに戻ってきたら、次のコマンドを 実行してカーネルを再コンパイルし、インストールします。 さきほど PPTP サーバーのカーネルを再構築したとき # make install # make modules_install # make modules # make bzlmage # make dep # make oldconfig # make mrproper cd /usr/src/Iinux—2.4.20 ー 20.9 では、どちらも、、 m " ( モジュールとしてコンパイル ) を入 、いま当てたパッチによって追加されたものです。 これら 2 つのオプションは、名前から想像できるよう 状態になります。 oldconfig の実行中に、図 25 の質問か表示されて入力待ち 定ファイルを作成してくれました。しかし、今回は make は、 make oldconfig を実行すると、途中で止まらずに設 力してください。 UNIX MAGAZINE 2004.2 メントアウトしている場合は、それを外してください。 ip-conntrack-pptp モジュールをロードしている行をコ もし、前回紹介した rc. firewall ファイルを変更して、 ↓ defau1t=0 default=l うに書き換えて再起動します。 make install の実行後、 /etc/grub. conf を以下のよ # make menuconfig 次のコマンドを実行するとよいでしよう。 をカスタマイズしたい場合は、 make dep を実行する前に 必須ではありませんが、さらにコンパイル・オプション カーネルが起動したら、今度は iptables コマンドを再 コンパイルします。 新しいカーネルでは、前回紹介した rc.firewall スクリ プトでフィルタを登録するときにエラーメッセージが表示 され、 MASQUERADE ターゲットのルールが登録でき なくなります。これは、さきほど当てたパッチによって、 iptables のコマンドとカーネル・モジュール間で送受信す るデータ構造が更新され、両者のあいだで不整合が生じて いるからです。このため、 iptables コマンドを再コンパイ ルする必要があります。 Red Hat Linux 9 の配布サイト から、次の RPM パッケージを入手してください。 ・ iptables-l. 2.7aー2. src. rpm ダウンロードが終ったら、以下のコマンドを実行してコ マンドとモジュールを再構築します。 # rpm —ivh iptables—l . 2.7a ー 2. src. rpm # cd /usr/src/redhat/SPECS/ # rpmbuild —bp iptables . spec # cd .. /BUILD/iptab1es—1.2.7a / # make COPT_FLAGS= ー 02 —march=i686" - KERNEL_DIR=/usr/src/1inux—2.4.20 ー 20.9 - LIBDIR=/1ib # cp iptables /sbin/iptables # cp iptables—save /sbin/iptables—save # cp iptables-restore /sbin/iptables—restore # cp extensions/* . SO /lib/iptables/ 以上でファイアウォールでの作業は終りです。 それでは、 Windows から PPTP 接続をしてみましよ Windows での言又疋 こまで、長い長いイバラの道でした。途中で挫折せず、 最後まで歩きとおした成果を楽しむ時間です。 試しに、内部 LAN の Windows PC から DMZ にあ る PPTP サーバーに接続してみましよう。 131
ります。これを使って、変数が定義されているときにのみ 空白文字を含む文冽を指定すればよいのです。 これらの点を改善した reverse 」 ist 関数は次のようにな _revlist= reverse—list ( ) ります。 情報を出力します。この出力を、パイプを使って複数のコ マンドを実行してマウントされているファイルシステムの ファイルシステムが格納されています。まず、 mount コ この部分を処理するとき、変数 -fs にはマウントしたい てみましよう。 再度マウントしないように工夫している部分のコードをみ こでは、すでにマウントされているファイルシステムを に、さきほども紹介した eval コマンドを使っていますが、 システムをすべてマウントします。この値を取得するため filesystems- 名前 " という変数に格納されているファイル この関数は、引数に、、名前 " を指定すると、、、 critical- mount_critical filesystems 関数 というすこ凵辧隹な式を用いています。 —revlist="$_revfile${_revlist : + $—revlist}" for 文のリストが” $@”となり、 -revlist への追加では、 echO "$_revlist" done : + $_revlist}" —revlist="$—revfile${—revlist=> for —revfile in " $@" ; d0 マンドを実行するサプシェルに渡します。 mount ー ( _ismounted=no while read what —on 0 Ⅱ—type type ; if [ $on = $-fs ] ; then —ismounted=yes done if [ $_ismounted = Ⅱ 0 ] ; then do サプシェル内では、 read コマンドを while と組み合わせ て入力を行ごとに読み込み、目的のファイルシステムがす mount $—fs >/dev/null 2 > & 1 98 でにマウントされていれば、 -ismounted 変数を yes に設 定します。すべての入力を処理した段階で -ismounted 変 数が no のままであれば、マウントされていないことが分 かるので、 mount コマンドを使って実際にファイルシステ ムをマウントします。 通常、パイプの後ろには単一のコマンドを置きますが、上 記のようにサプシェルを配置することにより複雑な処理も おこなえます。今回のように複雑なシェル・スクリプトを 作成する場合には、このような使い方はたいへん効です。 check pidfile 関数 この関数は、第 1 引数に指定された pid ファイルを調 べ、 1 行目の先頭に書かれている値をプロセス ID とみな します。そして、第 2 引数に指定されたプロセスが、その プロセス ID で動作しているかどうかを調べます。動作し ていればそのプロセス ID を出力し、動作していなければ 何も出力しません。第 3 引数を指定することもでき、その 場合はインタープリタの指定とみなされます。第 3 引数が 指定されると、プログラム・ファイルの先頭を調べてイン タープリタ形式のファイルであることを確認し、プロセス の検索時にもこのインタープリタ名を利用します。 この関数でおもしろいところは、 pid ファイルの 1 行目 の先頭の単語をプロセス ID として取り出すことと、省略 可能な第 3 引数の処理でしよう。とはいっても、プロセス ID は read コマンドで簡単に取得できます。 read —pid —junk く $—pidfile この処理により、 -pidfile 変数が指すファイルの先頭行 カ毓み込まれます。また、 read コマンドは読み込んだ行に 含まれる単語数よりも引数に指定した変数のほうが多い場 合、後ろに指定された変数を空に設定します。逆に、変数 のほうが少ないときは、最後の変数に残りのすべての入力 を代入します。そのため、上のコードのように 2 つの変数 を指定しておけば、間違いなく先頭の単語が最初の変数に オ内されます。 省略可能な引数の処理には、さきほどと同様にパラメー タ展開の修飾子を利用しています。ここでは、修飾子とし て、、 : ー " を使っています。 find—processes $—procname ${—interpreter : UNIX MAGAZ 工 NE 2004.2
連載 / Pe 日活用のヒント 図 10 FETCH コマンドの充若例 * 1 FETCH (RFC822 { 3602 } Received: from tkwexbh02. xxxx. xx . com ( Cxxx. xxx. 6 .47 ] ) by tkwexmbOl . xxxx. xx. com with Microsoft - 002 OK FETCH completed. FLAGS (\Seen) ) Tue , 2 Dec 2003 23 : 34 : 43 + 0900 SMTPSVC ( 5 . 0 .2195 .5329 ) ; ・例 1 ( 既読フラグの解除 ) 要求 : 003 store 1 —flags (\seen) . * 1 FETCH (FLAGS ( ) ) 003 OK STORE completed . ・例 2 ( 削除済みフラグの付加 ) 要求 : 004 store 1 + flags . silent (\deleted) 応答・ 応答 : 004 OK STORE completed . EXPUNGE 削除済みフラグカ附いたメールを削除する。 要求例 : 005 expunge 応答例 : * 1 EXPUNGE * 749 EXISTS 005 OK EXPUNGE LOGOUT セッションを終了する。 要求例 : 006 logout completed . 応答例 : * BYE IMAP4rev1 server signing 概要 ムコードの説明の準備カった。 POP3 と IMAP4 の説明が終ったところで、 プログラムコードの説明 006 OK LOGOUT completed. off . プログラ pop2imap は以下の 2 つのファイルで構成されている。 ・ pop2imap. pl ・ POP21MAP. pm pop2imap. pl は、コマンド行オプションをもとに Mail ::POP21MAP クラスのインスタンスを作り、そのインス タンスに main メソッドを適用する。実質的な処理は、す べて POP21MAP. pm のなかに言当丕されている。 Perl の モジュールのなかには POP3 や IMAP4 に関するものも あるが、それらは使わずに POP3 から IMAP4 への変換 70 処理のコードを書いた。 POP3 や IMAP4 関連の既存のモジュールを使ってい ない理由は、 pop2imap の目的に合わないからである。た とえば、 POP3 のモジュールには POP3 クライアントの 機能を提供するものがあるが、 pop2imap は POP3 に関 してはサーバーである。したがって、 POP3 関連の既存の モジュールは役に立たない。 pop2imap は IMAP4 につ いてはクライアントなので、 IMAP4 関係のモジュールは 使えるかもしれない。しかし、それは回り道に思えた。な ぜなら、 pop2imap を実装するにあたり、次項で述べるよう に POP3 から IMAP4 への変換方法をそれぞれのプロト コルのレベルで決めたからである。一方、 PerI の IMAP4 クライアントのモジュールは、 IMAP4 を多少抽象化して いる。プロトコルレベルで決めた変換方法を、抽象化され た手段を使って実装するよりは、直接書いたほうが素直だ し見通しもよくなると考えたのである。 プロトコル変換の方法 POP21MAP. pm が、 POP3 の各コマンドを IMAP4 に変換する方法を説明しよう。 USER ユーザー ID ューザー名を保存するだけで、ハ IAP4 のコマンドは発 行しない。 PASS パスワード ユーザー名が分かっているはずなので、 PASS コマンド で渡されたパスワードとともに IMAP4 の LOGIN コ マンドを発行する。そして IMAP4 の SELECT コマ ンドで INBOX フォルダを選択する。この時点で IN- BOX にメールカ可通あるかが分かる。 POP3 の PASS コマンドの次には STAT 、 LIST 、 UIDL のうちのいくつか、あるいはすべてが要求される UN 工 X MAGAZINE 2004.2
プログラミング・テクニック 図 1 rc. subr ファイルのバージョン表示部分 # $NetBSD: rc . subr,v 1 .49 2002 / 05 / 21 12 : 31 : 01 lukem Exp $ # $FreeBSD : src/etc/rc . subr,v 1 . 11 2003 / 04 / 30 03 : 03 : 47 mtm Exp $ # Copyright (c) 1997 ー 2002 The NetBSD Foundation, lnc . # A11 rights reserved. イルの先頭にあるコメントのなかの、バージョンを示す部 分からも分かります ( 図 1 ) 。 さらに詳しい情報は、 rc. subr ファイルのオンライン・ マニュアルから得られます。ちょっと驚くかもしれません が、このファイルについてはマニュアル・エントリが用意 されています。直接実行するコマンドでもないのに珍しい ですね。逆に、それだけ重要な役割を担っているファイル だともいえます。 オンライン・マニュアルの HISTORY セクションには、 次のように書かれています。 rc. subr appeared ⅲ NetBSD 1.3. The rc. d(8) support functions appeared ⅲ NetBSD 1.5. rc. subr first ap- peared ⅲ FreeBSD 5.0. つまり、 rc. subr は NetBSD 1.3 で初めて使われ、現在 のように rc. d に置かれたファイルのための関数群が用意さ れたのは NetBSD 1.5 からです。そして、 FreeBSD で は 5.0 からこのファイルカ甘采用されたわけです。したがっ て、 NetBSD でも利用可能にしているというよりも、 Free- BSD に移植する際に NetBSD で使えなくならないように したというほうが正確かもしれません。 コピーライトの言己杢のあと、いつもどおりのコメントに 続いて、 OS に依存した変数を設定しています。この部分 でおこなっている処理は、 2003 年 12 月号でも簡単に紹介 しました。今回はもうすこし詳しく、実際のコードをみな がら説明しましよう。 OS 依存の変数としては、システム変数を取得するための SYSCTL-N 、システム変数を言定するための SYSCTL- W 、 OS の種類を示す OSTYPE などがあります。これら を決定している部分のコードは、次のようになっています。 independent variables Operating System dependent/=> UNIX MAGAZ 工 NE 2004.2 CMD_OSTYPE="${SYSCTL_N} kern ・ ostype" SYSCTL_N=" ${SYSCTL} ーⅡ " SYSCTL="/sbin/sysct1" OSTYPE= ( ${CMD_OSTYPE} ' case ${OSTYPE} in FreeBSD) SYSCTL_W=" ${SYSCTL} " NetBSD) SYSCTL_W=" ${SYSCTL} —w" e S 95 の SYSCTL-W 変数は、システムごとに値が異なります。 話を戻しましよう。システム変数に値を書き込むため しい値を取得できるようにしているのです。 ことで、展開されていない変数カ在していた場合にも正 ないと考えたのでしよう。そこで、 eval コマンドを用いる からないため、展開されていない変数が含まれるかもしれ TYPE 変数に格納されている値がどのようなものかは分 ります。これに対し、 /etc/rc ファイルでは、 CMD-OS- いため、普通にバッククオートで処理してよいことが分か ります。この値には展開されていない変数が含まれていな 値 ( 具体的には、、 sysctl -n kern. ostype") がすぐに分か 直前の行で値が設定されたものが格納されるので、実際の か。 rc. subr ファイルの場合、 CMD-OSTYPE 変数には ォートのみで処理をしています。これはどうしてでしよう が、 rc. subr のほうは eval コマンドを使わず、バックク って結果を取得する際に eval コマンドも利用しています っています。 /etc/rc ファイルでは、バッククオートを使 この OS 名を得る処理は / etc / rc ファイルでもおこな に十内します。 カられます。そこで、この値を取得して OSTYPE 変数 らのシステムも、 kern. ostype 変数の値を調べれば OS 名 ムの OS を示す OSTYPE 変数の値を決定します。どち ションを指定したものになります。これを使って、システ は、どちらの OS の場合にも sysctl コマンドに一 n オプ 変数の値のみを取得するコマンドを設定します。具体的に ます。 SYSCTL-N には、引数として指定されたシステム SYSCTL は、どちらのシステムも /sbin/sysctl となり
図 2 インタープリタが指定された場合のタ里 set $-interp -interp=${-interp#\# ! } read —interp く $—procname # read interpreter name # strip # ! if [ $-interpreter ! = $ 1 ] ; then warn "\$command_interpreter $—interpreter ! = $ 1 " interp=" $ * $—procname " —fp—args='—argv' —fp—match= ) case " $—argv" in # cleanup spaces , add —procname ${-interp} l"${-interp} " * ) ' います。これは、インタープリタを示す # ! がインタープリ タ名とつなげて書かれていても、分離されて書かれていて も正しくインタープリタを取得できるようにするためです。 インタープリタカ陬得できたら、それが引数として指定 されたものと等しいかどうかを比較し、異なっていれは警 告を出力します。また、 -fp-match 変数には、最終的にイ ンタープリタもしくはインタープリタになんらかの引数が 付いたものが十タされます。 この関数は、引数として指定されたプロセス ID をもつ プロセスがすべて終了するまで待機します。さらに、待機 中は 2 秒ごとに、終了していないプロセス ID のリストを 出力します。 この関数の実装は簡単です。処理すべきプロセスのリス トを保持し、 kill コマンドを使ってそのプロセスカって いるかどうかを調べます。プロセスカっていれば、新し いリストを表す変数にそのプロセス ID を追加します。 こでは、パラメータ置換の修飾子を使ってあいだの空白文 字を制御しています。 if kill ー 0 $—j 2>/dev/nu11; then -nlist="${-nlist}${-nlist: + }$-j" wait for pids 関数 f i このコードでは、 kill コマンドに一 0 オプションを指定 しています。 kill コマンドは、、、一数値 " という形式のオプ ションが指定されると、その数値に対応するシグナルをプ ロセスに送信します。 0 番というシグナルは定義されてい ませんが、この場合、プロセスか有在していれは真が返り、 存在しなけれは偽が返るようになります。 この処理をすべての引数についておこない、その結果と 100 して得られたリストカ啌なら無限ループを終了します。プ ロセスカっている場合はメッセージを出力して 2 不寺ち、 ループの頁に戻ります。 ☆ 今回は、 /etc/rc. d ディレクトリに置かれたスクリプト カ俐用するライプラリ関数のような関数群を紹介しました。 これらは /etc/rc. subr ファイルで定義されているシェル の関数で、それぞれのファイルから . コマンドを使って取り 込むことで利用します。 ただし、すべての関数を紹介したわけではありません。 もっとも重要な、スクリプトを起動するための run-rc- script など、ほかにも多くの関数カ甘是供されています。次 回は、これら残りの関数群をとりあげる予定です。 ( たじみ・ひさかず ) 好評発売中 ! UNiX CO 乢 EC 料 ON プログラミング テクニック ーをまコをント・ソースコ - ドにみ・ プログラミング テクニック ・多治見寿和著 ・ B5 判、 240 ページ ・ ISBN 4-756 ト 4389- X ・ ] , 800 円十税 本誌に好評連載中の「プログラミング・テク二ック」の 第 ] 回から 2000 年 3 月号までを単行本化。実際に使われ ている UN Ⅸコマンドのソースコードを読みながら、実践 的なプログラミング手法が学べます。 株式会社アスキー 〒 1 60 ー 8584 東京都新宿区信濃町 34 J 日信濃町ビル 出版営業部電話 (08) 5362 ー 8300 UNIX MAGAZINE 2004.2
連載 /Red Hat Linux のツールたち 図 16 smbclient の実イ列 Domain= [MYGROUP] OS= CWindows 5 . 1 ] Server= [Windows 2000 LAN Manager] Password : ←パスワードを入力 added interface ip = 192 .168 . 1 . 4 bcast=192.168.1.255 nmask=255.255.255.0 [hayao@valhalla hayao] $ smbclient //hostos/tmp smb: \ > IS t e st 新規テキスト smb: \ > ロ ドキュメント . txt 0 Mon Dec 0 Mon Dec 0 Mon Dec 0 Mon Dec 8 40014 blocks of size 262144. 17973 blocks 8 15 : 44 : 25 2003 8 15 : 44 : 25 2003 8 15 : 44 : 11 2003 15 : 44 : 25 2003 available タンをクリックすると、図 15 のような設定画面カれ ます。ここで、、フルコントロール " をチェックし、 [OK] ボタンをクリックします。 この場合、 Windows マシンに登録されているユーザー なら誰でも読み書き可能になるので、ユーザーごとにア クセス権限を変更したければ、図 15 の画面でユーザー 名を追加して設定する必要があります。 4. 最後に、図 14 の [ OK ] ボタンをクリックします。 上記の作業をおこなったあと、 UNIX マシン上で smb- client を実行すると、図 16 のようになります。 最初に、パスワードの入力を求められます。 Windows マシンに登録された正しいパスワードを入力すれば、 smb- client のプロンプト (smb: \ > ) が表示されます。この 場合、とくに指定しなければ、 smbclient を実行したユー ザー名で Windows マシンにアクセスするものとみなされ ます。 UNIX と Windows とでユーザー名が異なるので あれば、 -U オプションに続けてユーザー名を指定します (smbclient コマンドのオプションは、かならず共有名よ りも後ろに指定します ) 。 このようにしてアクセスすると、 ls や get などのサプコ マンドを使用して、 ftp コマンドと同様な感覚で共有フォ ルダ内のファイルやフォルダを扱うことができます。 help または、、 ? " サプコマンドを実行すると、 smbclient のサプ コマンドー覧が表示されます。さらに、 help サプコマン ド名 " を実行するとそのサプコマンドの簡単な使い方も表 示されるので、参考にするといいでしよう。 smbclient コ exit" または q サプコマンド マンドを終了するには、 を実行します。 図 16 からも分かるように、日本語の表示が可能な端末 174 (kterm など ) 上で smbclient を実行すれば、日本語の ファイル名も正しく表示されます。 UNIX 側で使用する漢 字コードは smb. conf の coding system ノヾラメータの値 によって変わりますが、 Red Hat Linux の場合は EUC を使うように設疋しておけばいいでしよう。 こでは共有フォルダにアクセスする場合のみを なお、 紹介しましたが、 smbclient を使って Windows の共有プ リンタを利用することも可能です ( 言田は、 2003 年 7 月号 [ 3 ] などを参照してください ) 。 smbfs smbfs は、 Windows マシンの共有フォルダを UNIX マシンにマウントして利用するためのファイルシステムで す。いったんマウントすれば、 ( いくつか制約はあります が ) ローカルなファイルと同様に扱うことができます。 smbfs の処理には Samba のサーバー・プログラムは介 在しないので、 Samba サーバーではない UNIX マシンで も smbfs を利用することができます (Samba のパッケー ジはインストールしておく必要があります ) 。ただし、ファ イルシステムに対する読み書きなどはカーネルが処理する ため、すべての UNIX 系 OS で使えるとはかぎりません。 Linux の場合、最近のカーネルは smbfs をサポートして いるので、ほとんどのディストリビューションで利用でき るはすです。さらに、 Red Hat Linux 7.3 では、 OS イ ンストール時のカーネルに smbfs のサポートが組み込まれ ていますから、カーネルを再構築して smbfs のサポートを 外していないかぎり、特別な設定をしなくても使えます。 コマンド行から Windows マシンの共有フォルダをマ ウントするには、スーパーユーザーの権限で / usr / b ⅲ / smbmount コマンドを実行します。基本的な使い方は、 UNIX MAGAZINE 2004.2