Output.
もうちょっと踏み込んでみる(1998/5/18)
それではもう少し色々とやってみましょう。例として実行したtest.cgiはHello!と表示しました。表示されたということは当然ながら実行した結果、Hello!という文字が標準出力に送られたというわけですね。前にcgiプログラムをうまく機能させるために標準入力と標準出力が使われている、と書きました。つまりcgiプログラムが標準出力に出力したモノがブラウザに配信されることになっているわけです。とすれば、cgiプログラムがHTMLを標準出力に出力してやれば、それがブラウザに配信されて表示されるはずです。で、果たして本当にそれだけでOKかどうか、さっそく試してみましょう。test.cgiを以下のようにします。
print "<html>\n";
print "<head>\n";
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=shift_jis\">\n";
print "<title>Test</title>\n";
print "</head>\n";
print "<body>\n";
print "This is output by test.cgi\n";
print "</body>\n";
print "</html>\n";
言わなくても既に気づいていると思いますが、printは指定されたモノを標準出力に出力しています。上記のプログラムでは簡単なHTMLを標準出力に出力しています。補足をすると、\nというのは改行を表しています。また3行目を見ると所々に\"があります。これは"をそのまま出力します。\は出力されません。このような書き方になっている理由は判りますか? printでは標準出力に出力して欲しい文字列を"で括っています。何も考えずに"と書いてしまうと、そこで文字列が終わりなのかと勘違いされてしまいます。なので、文字列中に"を入れたいときは\"という書き方をします。3行目は実際には
<meta http-equiv="Content-Type" content="text/html; charset=shift_jis">
このような文字列を出力します。これが標準出力に出力されれば、それがブラウザに配信されてめでたく表示される、という算段です。ですが、果たしてうまくいくでしょうか? 上記のcgiプログラムを呼び出すようURLを指定してブラウザから実際に呼び出してみましょう。結果は如何だったでしょうか。うまくいかずにエラーとなるはずです。
実はcgiプログラムをhttpで利用する際には約束事があります。今作ったcgiプログラムがエラーになるのはそれらの約束事を満たしていないためです。まずcgiプログラムには適切なpermissionと、拡張子がcgiのファイルをcgiプログラムとして認識してもらうための設定が必要です。これらの他にもcgiプログラムが出力する内容にも多少のルールがあります。これらを順を追って見ていくとします。
まずはtest.cgiに与えるpermissionですね。test.cgiはcgiプログラムとして実行されることになるわけなので、実行可能属性が必要です。で、当然ながら誰しもが実行できないと意味がないのでnobodyの実行可能属性を指定します。telnet等で最終動作確認を行うこともあるかと思うのでownerにも実行可能属性を付けておくと良いでしょう。permissionとしてはd rwx --- --xくらいが適当でしょうか。ISPが使っているサーバによってはnobodyの属性に実行可能属性だけではなく読み出しの属性も必要な場合があります。もしnobodyの属性が--xでうまくいかない場合はr-xでも試してみて下さい。
さてお次。今度はtest.cgiをcgiプログラムとして認識させる設定です。これはISPのサーバ側で行われている設定如何によって必要な場合と必要でない場合があります。ホームページを見たりするためにはサーバ上でhttpd(hyper text transfer protocol daemon)が動作している必要があります。web serverに必須のサーバ・ソフトウェアのことだと思って下さい。このhttpdの設定によってcgiプログラムとして認識させる設定が必要かどうかが決まります。srm.confファイルでhttpdの設定があると、拡張子がcgiのファイルは全てcgiプログラムとして認識してもらえるので、あなたが設定を行う必要はありません。
これはHPにそれらしき情報が載ってないか調べるなり管理者にメールで聞いてみる等しないとちょっと判りません。HPにはおそらく載ってないと思います。あまりサーバの内情まで教えるISPはないでしょう。しかし調べる方法はあります。方法は簡単で単にブラウザからcgiプログラムのURLを指定して実行させてみるだけです。あなたが何も設定せずとも問題なく実行されるようならsrm.confファイルで設定が行われているのだと思います。逆にうまく動作しないようであれば、あなたが設定を行う必要があります。ただ、今の段階ではまだcgiプログラムとして必要な体裁がまだ整っていないので、具体的な設定方法は後の方で触れます。
設定はちょっとおいておくとして、今度はcgiプログラムが守るルールです。cgiプログラムは、ブラウザに表示させたい内容を標準出力に出力してやれば良いのですが、その時に多少のルールがあります。cgiプログラムが標準出力に出力した内容は素通りでブラウザに配信されるわけではなく、間にhttpdを介在させます。httpdがcgiプログラムの標準出力の内容に目を通すので、その内容をブラウザに配信しなければいけないモノだとhttpdに思わせないといけません。実際にcgiプログラムがすべきことは簡単で
Content-type: text/html
このようなヘッダ文字列をまず最初に標準出力に出力してやるだけで済みます。Content-type: text/htmlとあるのは、それがHTMLテキストであることをhttpdに知らせています。つまりcgiプログラムが出力した内容がHTMLテキストであることを教えています。また、ヘッダ文字列の後は空白行が必要です。この空白行がないとヘッダ文字列があってもエラーになります。これをまずtest.cgiに追加しましょう。以下の行をtest.cgiの先頭に追加します。
print "Content-type: text/html\n\n";
一番最後の2つの\nに注目して下さい。これがヘッダ文字列後の空白行になります。さてもう1つルールがあります。今度は標準出力の内容ではなくて、test.cgiの中身です。cgiプログラムがC/C++のような言語で作られたバイナリの実行形式の場合は別なのですが、test.cgiのようにプログラムといえども実際にはただのテキストファイルという場合には先頭行に記述しておかないといけない内容があります。test.cgiの先頭に以下の行を追加して下さい。
#! /usr/local/bin/perl
これは、このcgiプログラムをどうやって実行すれば良いかを表しています。この/usr/local/bin/perlという部分はperlの在処を意味しています。このcgiプログラムを/usr/local/bin/perlに実行してもらいたいと教えているわけです。前の方のトピックでwhich perlを実行したと思いますが、その時に表示された内容を#!に続けて/usr/local/bin/perlの代わりに書きます。大抵は/usr/local/bin/perlで大丈夫だと思いますが、ISPによっては違う場合もあるのでwhich perlを実行して確かめて下さい。最終的には以下のようになります。
#! /usr/local/bin/perl
print "Content-type: text/html\n\n";
print "<html>\n";
print "<head>\n";
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=shift_jis\">\n";
print "<title>Test</title>\n";
print "</head>\n";
print "<body>\n";
print "This is output by test.cgi\n";
print "</body>\n";
print "</html>\n";
1つ言うのを忘れていましたが、#からその行の終わりまではコメントとなります。perlは#を見つけると、そこからその行の終わりまでを無視します。では#!は一体何なんだ? と思った方もいらっしゃるかもしれません。最初の行は#で始まっているので、perlはこの行を無視します。無視されるのに何故#!の行が必要かというと、実はhttpdがこの部分を解釈するのです。perlのためではなくて、実はhttpdのために必要な行だったのですね(正確に言うとhttpdではなくて、httpdがcgiプログラム実行のために起動させるシェルが解釈します)。
さて、test.cgiの方はとりあえず動作するモノができあがりました。繰り返しになりますが、test.cgiをftpでISPのサーバに転送する時にはasciiモードで行うようにしましょう。
残るはhttpdにtest.cgiをcgiプログラムとして認識させる設定です。サーバにtest.cgiを転送し、適切なpermissionを付け、特に何も設定せずともブラウザからの直接URL指定でtest.cgiが問題なく動作したのであれば、ここからは読み飛ばして構いません。
まずcgiプログラムとして認識させるための設定は、それ用のテキストファイルを用意することで行います。ファイル名は.htaccessです。まずtest.cgiを置いたディレクトリに移動します。そのディレクトリに以下の内容の.htaccessというファイルを置いてください。
AddType application/x-httpd-cgi .cgi
この1行だけです。ただしこのAddTypeという指定の仕方はNCSAhttpdの場合です。Apache等の他のサーバでは指定の仕方が違う場合があります。例えばApacheではAddTypeの代わりにAddHandlerという指定をする場合があります。application/x-httpd-cgiという部分はMIME(multipurpose internet mail extensions)タイプを表しています。これはどのような内容のデータなのかを示すために利用されます。application/x-httpd-cgiは、それがcgiプログラムであることを示すMIMEタイプです。少し例を挙げておくとtext/plain、text/html、image/gif、image/jpeg等があります。他にも沢山あります。この辺は見ただけでだいたい何を表すMIMEタイプか見当がつくでしょう。
AddTypeとあるのはMIMEタイプを追加したいことを表しています。で、application/x-httpd-cgiのMIMEタイプを適用するのが拡張子.cgiのファイルというわけです。もし必要なら1行だけとはいわず、複数を指定することもできます。
AddType application/x-httpd-cgi .cgi
AddType text/plain .dat
判りますよね? 拡張子が.cgiのファイルをcgiプログラムとして指定しています。また拡張子が.datのファイルを通常のテキストファイルとして指定しています。そうそう、誰かにイタズラされたりしないよう.htaccessにもpermissionも付けておきましょう。d rw- --- r--で良いかと思います。
test.cgiのあるディレクトリに.htaccessファイルを置いたらブラウザで直接URLを指定して動作するかどうか試してみましょう。ついでに言っておくと.htaccessファイルが置いてあると、そのディレクトリ内のファイルだけでなく更に下の階層のディレクトリ内にあるファイルにも適用されます。逆に、親ディレクトリで.htaccessがあっても子ディレクトリに.htaccessがあれば、子ディレクトリでは子ディレクトリの.htaccessが適用されます。public_htmlでAddType application/x-httpd-cgi .cgiの.htaccessがあっても、public_html/mydirにAddType text/html .cgiの.htaccessがあればpublic_html/mydir内の拡張子.cgiファイルはHTMLとして認識されます。
このトピックで取り上げたスクリプトはココからダウンロード出来ます。圧縮してあるので適当なディレクトリに解凍してください。