連載 /UNIX Communication Notes— く hr noshade slze=" 1 " > 0 く input type="submit" value = ”カ′く一シート作成 " > く input type="reset" val Ⅱ e = " 入力のリセット " > く / f0 て m > く /body> く /html > END_ OF_HTML exit ( の ; # 送信者の選択 sub selector—sender { 10Ca1 $usrid, $usrname , $usrorg, $usrdpt , print qq ーく select name="Sender">\n 信 . /faxcover/users . db") ; open(USERDB , " く while ( く USERDB>) { $usrtel, $usrfax, $usremail ; ($usrid, $usrname , $usrorg , $usrdpt , $usrtel , J code : : convert (\$usrname , ) euc ) ; print qq l<option value="$usrid" >$usrname\n ー cIose(USERDB) ; print qql</select>\nl; # 出力先プリンタの選択 sub selector—printer { 10Ca1 $prnid , $prndsc , $prnname ; print qql く select name="Printer">\nl; open (PRNDB , " く . /faxcover/printer. db") ; while( く PRNDB>) { ($prnid , $prndsc , $prnname) jcode: :convert(\$prndsc, $usrfax , $usremail) print qq l<option value=" $prnid">$prnname ($prndsc) \ 司 ; c10se(PRNDB) ; print qql</select>\nl; # テンプレート・ファイルのデータベースから情報を取り出す sub selector_template { 10Ca1 $tmplid, $tmpldsc , $tmplname ; print qql く select name="Printer">\nl; open (TMPLDB, " く . /faxcover/template. db") ; while ( く TMPLDB>) { ($tmplid, $tmpldsc , $tmplname) jcode: : convert (\$tmpldsc, euc ) ) ; print qq 区 opt 土 0 Ⅱ value="$tmplid">$tmplname ($tmpldsc) \ Ⅱに 68 print qql</select>\nl; c10se(TMPLDB) ; UNIX MAGAZINE 2001.5
連載 UNIX Communication Notes— 0 c10se(LATEXF) ; c10se(TEMPLATE) ; # LaTeX の実行 # dvi2ps の実行 c10se(CMDOUT) ; print $ ー while( く CMDOUT>) { # open(CMDOUT, "/usr/local/bin/jlatex $$. tex に ) ; open(CMDOUT , " (export PATH=/usr/10ca1/bin : /usr/bin : /bin ; chdir($datadir) ; print LaTeX compiling start : $$. tex ー > $$. dvi\n" /usr/local/bin/jlatex $$. tex) Convert DVI file to PS file : $ $ . dvi ー > $ $ . ps\n" pr int open(CMDOUT, "/usr/10ca1/bin/dvi2ps —c $$. ps $ $ . dvi 2 > & 1 卩 ) ; while ( く CMDOUT>) { print $ ー c10se(CMDOUT) ; # プリンタへの出力 Printing PS file t0 the Printer\n" print print "/usr/bin/lpr -P$va1ues{'Printer'} $ $ . ps\n" #open(CMDOUT, "/usr/bin/lpr -P$va1ues{'Printer'} $ $. ps 2 > & 1 卩 ) ; unlink "$$ . tex" print delting garbages\n" # 作業ファイルの消去 #c10se(CMDOUT) ; print $ ー #while ( く CMDOUT>) { done\n" # サプルーチン群 print # タグ初期化 : データファイルで使用するタグ sub taginit { @tag = ('SrcOrg' ' DestOrg ' 'SubJect' ' SrcDpt ' 'Srcperson 'SrcTe1' ' SrcFAX ' 'SrcEmai1' 'DestPerson' ' Temp1ate ' 'Message'); 'DestTe1' 'Date' UNIX MAGAZINE 2001.5 73
連載 UNIX Communication Notes— 0 # データファイルをもとにした送付状 (LaTeX ソース ) の作成 . /faxcover/data' ) ; chdir ( ' open(CMDOUT, " . /dat2ps $datafilel " ) ; while( く CMDOUT>) { print $ ー # Web クライアントに表示するべージの末尾 print " く /pre>\n" print " く hr noshade>\n" print end—html ; exit(O) ; # サプルーチン群 # 現在時刻の取得 sub currenttime{ # テータファイルへの書出しの順番のため、 Message はかならす末尾にする # タグ初期化 $year = $year + 1900 ; ($sec,$min,$hour,$mday,$mon,$year, $wday,$yday,$isdst) localtime(time) ; sub taginit { ( 'SrcOrg' ) SrcDpt ) @t ag 'DestOrg' ) , 'Temp1ate' 'Subject' , 'Message') ; ) SrcPerson ' 'DestPerson' , 'DestTe1 ' 'Date' # 送信者データベースからの情報の取出しと格納 sub set—srcinfo { local($target) 'SrcFAX' 'SrcTe1' 'SrcEmai1' 10Ca1 $usrid, $usrname , $usrorg, $usrdpt, $usrtel, $usrfax, $usremail; . /faxcover/users . db") ; open(USERDB , " く while ( く USERDB>) { ($usrid , $usrname , $usrorg , $usrdpt , $usrtel , $usrfax, $usremail) $usremail cIose(USERDB) ; 1ast ; if ($usrid $target) { : convert (\$usrname , jcode : : convert(\$usrorg, jcode : : convert(\$usrdpt , 70 Jcode: euc ) ; ' euc ) ; UNIX MAGAZINE 2001.5
連載 .. / UN Ⅸ Communication Notes— 0 リスト 2 フォームに入力されたデータをもとに里をおこなうプログラム (mkfaxcover ・ cgi) use CGI qw( : standard) ; require "jcode¯2.10. p1 # mkfaxcover. cgi : 第 2 版 # ! /usr/local/bin/perl $mycgi= new CGI ; # クライアントからのフォームデータを格納 ¤ttime ; &taginit ; # 初期化と時刻取得 # Web クライアントに表示するべージの先頭部分 c10se(DATA) ; print DATA $values{ ' Message ' } ; print DATA " \ Ⅱ " printf DATA ("%s :%s\n" , $tag[$i] , $values{$tag[$i] } ) ; for ($i open(DATA, " > $datapath") Ⅱ die "Can't open $datafile\n" $datapath = $datadir . $datafile ; $year , $ mon + 1 , $mday , $ ho , $min , $sec) ; $datafile= sprintf ( " % d % 02d % 02d % 02d % 02d % 02d. dat" $datadir = ' . /faxcover/data/ ' ・ # データファイルの書出し $ mon + 1 , $mday , $year , $hour , $min) ; $values{ 'Date ' } sprintf ( " % 02d / 加 2d / % d % 02d : 加 2d " &set—printer( $mycgi->param( 'Printer' ) ) ; &set—template( $mycgi—>param('Template') ) ; &set—msg($subject, $message) ; $subject " ()o Subject) ” if ( length($subject) $subj ect= $mycgi—>param( ) Subject ' ) ; $message= $mycgi—>param( ) Message ' ) ; $mycgi—>param( 'DestTe1') ) ; &set—dstinfo($mycgi—>param( 'DestOrg') , $mycgi->param( 'DestPerson' ) , &set—srcinfo( $mycgi—>param('Sender') ) ; print pr int pr int pr int print header; start—html ( ' Making FAX Coversheet ' ) ; ”く b>FAX Coversheet wi11 be printed out on your printer. く /b> く br>\n" " く hr noshade>\n" ・ UNIX MAGAZINE 2001.5 69
連載 UNIX Communication Notes— 0 size="50"> く /td> く td> く /td> く td > 受取人く / td > く td> く input type= く /tr> row3 く tr> く td> く /td> く td > 電話番号く / td > く td> く input type= 'text" く /tr> row4 ーー > く tr> く td > 2 . 用件く / td > く td> 表題く /td> く td> く input type= 'text' く /tr> row5 ーー > く tr> く td> く /td> 'text" name = name = name = "DestPerson" "DestTe1t' size="50"> く /td> "Subj ect " SIZe= " 50 " > く / td > く td> メッセージく / td > く td> く textarea name= く /textarea> く /td> く /tr> 6 く tr> く td>3. 送信者く / td > く td> く /td> く td> END_OF_HTML &selector_sender; print くく END—OF_HTML ; く /td> く /tr> row 7 ーー > く tr> く td > 4 . 使用するテンプレートく / td > く td> く /td> く td> END_OF_HTML "Message" UNIX MAGAZINE 2001.5 く /table> く /tr> く /td> print くく END—OF-HTML ; &selector—printer; END ー OF_HTML く td> く td> く /td> く td > 5 . プリンタく / td > く tr> row 8 く /tr> く /td> print くく END—OF—HTML; &selector—template ; rows=5 cols = 50 > 67
. /faxcover/template. db") ; open(TMPLDB , ”く while( く TMPLDB>) { ($tmplid , $tmpldsc , $tmplname) if ($tmplid = = $target) { 連載 /UNIX Communication Notes— # 空行はメッセージとのセパレータ 0 1ast ; c10se(TMPLDB) ; $tmplname $values{ ' Temp1ate ' } $tmplname ; リスト 3 データファイルから FAX 送付状を印刷するプログラム (dat2ps) # ! /usr/local/bin/perl print "REMOTE—ADDR: $ENV{ 'REMOTE—ADDR' } \ Ⅱ " # データファイルの読込み $datafile = $ARGV [ 0 ] ; reading datafile : $datafile\n" 、 print open(DATAF, " く $datafile") Ⅱ die "Can't open $datafile. " ・ ($key , $val) 1ast ; if (length($-) chop ; while ( く DATAF>) { while ( く DATAF>) { $values{$key} = $val ; $vaIues{'Message'} $tmplfile $tmpldir . $values{ ' Temp1ate ' } ; # LaTeX ファイルの作成 $datadir = ' /usr/local/www/faxcover/data/' ; $tmpldir ' /usr/local/www/faxcover/) &taginit ; # 変数の初期化 c10se(DATAF) ; $va1ues{'Message'} . tex" $latexfile = $datadir . $ $ pr int pr int making LaTeX source file: template file: $latexfile\n" $tmplfile\n" open(TEMPLATE, " く $tmplfile") Ⅱ die "Can't open $tmplfile" ・ open(LATEXF, " > $latexfile") Ⅱ die "Can 't open $latexfile" ・ while ( く TEMPLATE>) { for ($i $tagname = $tag[$i] ; s/==$tagname==/$values{$tagname}/ ; pr int LATEXF $ ー 72 UNIX MAGAZINE 2001.5
102 集 Plan 9 のファイルシステム イル言当子、バッフア、およびバッフアのサイズである。 int fd2path(int fd, char *buf , int nbuf) これは、ファイル言当子か無効なときにはエラーを返す。そうでないときは、 fd に対応した名 前をバッフアに入れる ( 名前が長すぎる場合は切りつめられる。この場合もエラーとするべきだ ろう ) 。 fd2path システムコールがおこなうのは、 Cname 文字列をユーザー空間にコピーするこ とだけなので、きわめて効率がよい。 PIan 9 での getwd の実装は、 fd2path を使用しており、 UNIX で必要とされる複雑なアル ゴリズムは不要である (UNIX の getwd には、バッフアの大きさを示す引数はない ) 。 char* getwd(char *buf , int nbuf) int Ⅱ , fd ; fd = open(" . ", OREAD) ; if()d く 0 ) ret urn NULL ; Ⅱ = fd2path(fd, buf, nbuf) ; close(fd) ; if(n く 0 ) ret urn NULL ; return buf ; この getwd は明快であるだけでなく、きわめて効率的であり、糸Ⅲ囚み pwd コマンドの性能に ひけをとらない。また、 pwd だけでなく、すべてのコマンドか意味のあるディレクトリ名を参照 できるようにする。 以下に、オープンされているそれぞれのファイル言当子に対応するファイル名を表示するルー チンを示す。これは、ネットワーク・デーモンやテキストエデイタによって開かれたままになっ ているファイルをみつける場合などに役立つ。 #define NBUF 256 void openfiles(void) int i ; char buf CNBUF] ; for(i=O; i く NFD; i + + ) if (fd2path(i, buf , NBUF) > = 0 ) print("%d: %s\n", i, buf) ; よい名前を使う 正しい名前を付ける測饑となったのは pwd だが、正しいファイル名は多くの状況で役に立ち、 PIan 9 のプログラム環境の主要な部分を占めるに至った。コンパイラは、シンポルテープルに ソースファイルの完全な名前を言当求する。これにより、バグがみつかった旧いソフトウェアの ソースを探し出すのカ鎔易になり、さらに、それを自重加勺におこなう src というプログラムを実 装できる。プログラムの名前が与えられると、 src はそのシンポルテープルを読み取り、ファイ UNIX MAGAZINE 2001.5
連載 /UNIX Communication Notes— 図 7 デーモンの起動と確認 # /usr/local/bin/safe—mysqld & [ 1 ] 43194 method="POST"> and you are welcome t0 modify and redistribute it under the GPL license This software comes with ABSOLUTELY NO WARRANTY . This is free software, Copyright (C) 2000 MySQL AB & MYSQL Fin1and AB & TCX DataKonsu1t AB mysqladmin Ver 8.18 Distrib 3.23.35 , f0 て unknown—freebsde1f3.5.1 0 i386 # mysqladmin version Starting mysqld daemon with databases from /usr/local/var 0 Server version 3 . 23 .35 P て 0t0C01 version 10 Connection Loca1host via UNIX socket UNIX socket /tmp/mysql . sock Uptime: 16 sec Threads : 1 Questions : 1 SIOW queries : 0 Opens : Open tables : 0 Queries per second avg: 0.06 ? ームについてコンパイル済みバイナリ・パッケージも公開して いる。これらのパッケージを利用する場合は、ダウンロード して適当なディレクトリで展開する。どのパッケージにもイ ンストールカ 1 去を記したファイルが含まれているので、それを よく読んでからファイルを必要な場所にコピーする。続いて、 mysql-install-db PJ 、降の処理をおこなえばよい。 Linux 用に は、 RPM 形式のバイナリ・パッケージが用意されている。 FreeBSD では、 ports に MySQL が含まれている (data- bases/mysq1323-server が最新版である ) 。これらのプラッ トホームでは、パッケージを使うと簡単にインストールできる。 6 F1ush tables : 1 次回は、 MySQL を用いた CGI プログラムの開発ガ去 1999 tive Guide, Second Edition, O'Reilly & Associates, [ 1 ] Ben Laurie and Peter Laurie, 員佖 c ん e - ー The 〃 e 五れ [ 赭文献 ] ( やまぐち・すぐる奈良先端科物支術大完大学 ) について説明する。 リスト 1 FAX 送付状への情報入力用フォームを生成するプログラム (faxcoverform ・ cgi) # ! /usr/local/bin/perl require 'jcode-2.10. pl " ・ print くく END—OF_HTML ; Content—type : text/html く html> く he ad> く titIe>Making FAX Cover Sheet く /title> く meta http—equiv="Content—Type" content="text/html ; く /head> く bOdy bgcolor="white"> く h2>FAX Cover Sheet く /h2> く hr noshade SIze=" 1 " > く form action="/cgi—bin/mkfaxcover. cgi" charset=euc—J apanese " > く table border="0"> rowl く tr> く td>l . 送付先く / td > く td > 組織名く /td> く td> く input type="text ー く /tr> く tr> 66 Size= " 50 " > く / td > UNIX MAGAZINE 2001.5
連載 UNIX Communication Notes— 155 図 1 週言者データベース (/usr/local/faxcover/users. db) 1 : 山口英 : 奈良先端科学技術大学院大学 : 情報科学研究科 : 0743 ー 72 ー XXXX : 0743 ー 72 ー YYYY : suguru@wide.ad ・ jp 2 : 山田太郎 : 慶応義塾大学 : 環境情報学部 : 0466 ー 47 ー XXXX : 0466 ー 47 ー YYYY : tarou@keio ・ ac ・ jp 3 : 河村花子 : 東京大学 : 工学部 : 03 ー 3456 ー XXXX : 03 ー 3456 ー YYYY :hanako@u—tokyo ・ ac ・ jp 図 2 テンプレート・ファイルのデータベース (/usr/local/faxcover/template. db) 1 :Simp1e but enough:temp1ate01. tex 2 : レターヘッド付き :temp1ate02. tex 表 1 各テータベースのフィールド (a) users. db ( 送信者 ) ID : 名前 : 所属屠 : 電話番号 : FAX 番号 : メールアドレス (b) template. db ( テンプレート・ファイ ) の ID : 説明 : ファイル名 (c) printer. db ( プリンタ ) ID : 説明 : プリンタ名 2 ~ 4 の問題は、プログラムやテンプレートに埋め込ま れている項目をユーサーがフォームで選べるようにすれ ばよい。それにはまず、パスワード・ファイル (/etc/ passwd) 当策な、いくっかの要素を : ( コロン ) で区 切ったエントリからなるデータベース・ファイルを用意す る。そして、そのファイルから得た情報をもとにユーサー か 1 嚇甫を選ぶようにする。このデータベース・ファイルは 管理者か設定する。つまり、 Web 側からはデータベース に対する追加や削除はおこなわれないと仮定する。 今回は、以のような方針にもとづいてシステムを構築 する。 データベース・ファイルの作成 まず、ユーサー ( 送信者 ) 、テンプレート・ファイル、プ リンタなどの情報を格納するデータベース・ファイルを用 意する。それそれ刎列を図 1 ~ 3 に示す。このように各要 素をコロンで区切っておけば、 PerI で簡単に扱うことが できる。 レート、プリンタを選べるようにしなければならない。こ これに対して第 2 版では、ユーサーが送信者、テンプ いことを前提としていたからである。 index. html とした。これは、表示する内容か変更されな 第 1 版では、 FAX で送信する情報の入力フォームを フォーム CGI プログラムの作成 各データベースのフィールド構成を表 1 に示す 60 図 3 プリンタのデータベース (/usr/local/faxcover/printer. db) 1 : 3 階教授室 : prn-prof 2 : 4 階学生室 : prn-student れらの選択肢は、データベース・ファイルの記述に応し て生成する必要がある。そこでます、フォームを作成する CGI プログラムを実装する。このページを表示させたい 場合は、ほかのページからのアンカーとしてこの CGI プ ログラムを指定すればよい。 このプログラムでは、データベース・ファイルを読み込 み、プルダウン・セレクタでデータお尺できるようにす る。作成した faxcoverform. cgi を末尾のリスト 1 に このプログラムは Perl で書かれている。以下に記すよ うに、 HTML ファイルの作成は叫屯なガ去で実現してお り、前回紹介した CGI. pm などは利用していない。 ている部分のあいだで実行される。 して作成する。それぞヒアドキュメントで出力され tor-sender 、 selector-template 、 selector-printer と 3. セレクタを生成するプログラムを、サプルーチン selec- 分以外をそのまま print に渡す。 2. ヒアドキュメントの機能を使い、セレクタをはめ込む部 る ( セレクタをはめ込む部分は空白にしておく ) 。 1. フォームを出力するための HTML ファイルを作成す UNIX MAGAZINE 2001.5 ウが表示される。 このプログラムを実行すると、図 4 のようなウインド charset を euc-japanese" にする。 保存し、さらに meta タグの http-equiv の機能を使って erform. cgi のなかでは、日本語文字列をすべて EUC で れた日本語を EUC で扱うようにした。ファイル faxcov- ログラムである。そこでます、プログラム自体に埋め込ま ある。 faxcoverform. cgi は、日本語文字列を出力するプ 実装する際には、出力する日本言韶 ) 扱いに注意が必要で 出力するようにヒアドキュメントに追加する。 4. 最後に、プログラムの頁に Content-Type と空行を
表 1 TARGET 引数のプラットホーム名 TARGET 引数プラットホーム名 # (cd exit . /include ; tar Bpcf ) ー tar Bpxf netbsd freebsd2 bsdi3 freebsd3 openbsd bsdi4 freebsd4 NetBSD 1.5 FreeBSD 2.2.8-RELEASE BSDI BSD/OS 3.1 ( * ) FreeBSD 3.5-RELEASE OpenBSD 2.8 BSDI BSD/OS 4.2 patchlevel 0 FreeBSD 4.2-RELEASE そして、カーネルを作成するために各プラットホーム用 * kame/VERSION を参照 kame/CVS/Repository kame/kame/sys/netkey/keydb. c kame/kame/sys/netkey/keydb. h kame/kame/sys/netkey/keysock. c kame/kame/sys/netkey/keysock. h すでに KAME をインストールしたことがある場合は、 /usr/local/v6 を消します。設定ファイルなどを残して おきたいのなら、 /usr/Iocal/v6 を /usr/locaI/v6. old へ 変更すればよいでしよう。 rm も mv も避けたい場合は、 爛氏限 /usr/local/v6/lib 以下を消去します。 次に、各フラットホームごとのコンパイルの準備をしま す。 kame ディレクトリに移動し、 TARGET 引数に表 1 のフラットホーム名を指定して make prepare を実行し ます。 FreeBSD 3.5 の場合は、次のようになります。 % cd kame % make TARGET=freebsd3 prepare ()d /usr/tmp/kame ; perl prepare . pl kame freebsd3) start : kame , .. /kame , freebsd3 exclude in freebsd3: . /.. / .. /kame/sys/netkey/keysock. c 1 Ⅱ -s freebsd3/sys/netkey/keysock. c unlink freebsd3/sys/netkey/keysock. h (sy mlink) . /.. / .. /kame/sys/netkey/keysock. h ln -s freebsd3/sys/netkey/keysock. h これで、 kame/freebsd3 以下に KAME をコンノヾイル する準備カいます。 # cd include . clean # mkdir include . clean # cd /usr # cp /kernel /kernel . previous % su 次に、カーネルなどのバックアップをとります。 UNIX MAGAZINE 2001.5 のコンパイル・ディレクトリに移動します。 % cd freebsd3 % pwd /usr/tmp/kame/freebsd3 % cd sys/i386/conf FreeBSD 3.5 の工竟で PAO を使う場合には、 点で PAO のカーネルバッチを当てます。 % cd /usr/tmp この時 % fetch -P ftp://daemon.jp.freebsd.org/pub/FreeB SD ー jp / PAO / PA03 ー 20001021. tar ・ gz ← PAO を入手 % tar xvfz PA03 ー 20001021. tar ・ gz % cd /usr/tmp/kame/freebsd3 % patch -p2 く /usr/tmp/PA03/sys/sys-pao. diff PAO のカーネルバッチを当てると、一部 reject され るので手て修正します。 % find . / -name " * . rej " —print . /sys/conf/files . rej sys/conf/files. rej をみれは分かるように、これは一部 の SCSI テンヾイスの成疋ファイルの追加に失敗しているだ けなので、、、十 " カ咐いている部分を sys/conf/files へ追 加します。かなり強引ですが、次のようにします。 % cat > > . /sys/conf/files cam/scsi/scsi_ cam/scsi/SCS1 cam/scsi/scsi_ cam/scsi/scsi cam/scsi/scsl cam/scsi/scsi_low . C cam/scsi/scsi low-pisa low—pisa 10W . C low-pisa 10W . C od . c . C . C . C optional Od opt i 0 Ⅱ a1 opt i 0 Ⅱ aI opt i 0 Ⅱ aI optional optional optional IICV ncv nsp nsp stg stg あとは KAME を make し、それから PAO 関連の make をす川まよいでしよう。 さて、もとに戻ります。カーネルの設定ファイルの物旧杉 が GENERIC. v6 です。もし、オリジナルの ( 変更を加 えた ) カーネル設正ファイルを使用している場合は、この 芻旧杉をベースに斑央しましよう。 % pwd /usr/tmp/kame/freebsd3 % cd sys/i386/conf % cp GENERIC. v6 CONFIGFILE 51