CGIプログラミング
for
マイクロソフト Personal Web Server



あなたは,人目のお客様です。

 この文書ではPersonal Web Server(以下PWSと言います),version 1.0を対象としたCGIプログラミングについての概略をお話しします。話を簡単にするため,語句の言い換え,本来の意味とは違う説明,詳細の省略を行っている場合があります。あらかじめご承知置きください。

 PWSに特化したCGIプログラミングという事で,OSはWindows95,開発システムはマイクロソフトのVisual C++,version 4.2/5.0(以下VC)を想定しています。他のOSや開発システムでの場合については,OS,ブラウザ,PWS,開発システムに付属のオンラインヘルプなどをご参照ください。


 ご意見,ご質問などは,
「ホームサーバ接続」デモ・マスター <demo-master@argus.ne.jp>
までお願いします。



1.CGIとは
 CGI(Common Gateway Interface)は,WebページとHTTPサーバ内のユーザプログラムの橋渡しをするものです。このCGIにより,単なるテキストフォーマットであるHTMLを使用したWebページが,情報収集機能,判断機能を持つ様になります。同様の事はHTTPサーバ側の機能としてはSSI(サーバサイドインクルード),ネットスケープなどのWebブラウザが動いているクライアント側の機能としてはWebページに仕込まれたスクリプト(JavaScript,VBScriot)やJavaなどでも可能ですが,CGIはその中で一番歴史があるものです。



2.CGIプログラムの形式
 UNIXで動いているHTTPサーバの場合,標準状態ででも,CGIプログラムはともかく実行可能なファイルならば何でも構いません。Cなどで開発した実行形式のファイルはもちろんの事,shellスクリプト(DOSのバッチファイルが近いもの)やPerlその他のスクリプト言語のソースファイル,何でもOKです。

 デフォルト状態のPWSの場合,CGIプログラムの形式は実行形式であるEXEファイル,それもWin32の実行形式に限られています。DOSなどのEXEやCOM,そしてBAT,これらは全てアウトです。Win32の実行形式であれば,そのCGIプログラムの拡張子はEXE以外でも構いません。

 VCでCGIを作成する場合,DOSプログラムのWindows版とも言えるコンソールアプリケーションが良いでしょう。もちろんWindowsアプリケーションでも構いませんが,CGIプログラムは,別にWindowsに対するGUIを必要としていませんから,無用と言えば無用の事です。MFCを使用したアプリケーションは,データベースアクセスやその他の,MFCを使用するとプログラミングが楽になる機能をCGIが必要としている場合に有用かもしれません。


3.メソッド
 Webページのフォームでの入力などのデータを,CGIプログラムに渡す方法には,GETメソッドとPOSTメソッドがあります。  GETメソッドは単純で短いデータをCGIに渡す場合に,POSTメソッドは大量のデータを渡す場合に使用されるのが通例です。


4.非常に簡単なCGI
 CGIプログラムは,リクエストを発したクライアント(Webブラウザが動いているPC)へ,リクエストに応じたテキストや画像などのデータを送り返します。このデータの返送はHTTPサーバを通して行います。インターネットなどを通して,CGIプログラムが直接行うのではありません。

 具体的にはCGIプログラムが標準出力に出力したデータはHTTPサーバが受け取る事になります。HTTPサーバはこのデータに若干の処理をした後に,インターネットなどを通して,クライアントに送ります。


 Webベージからデータを取らず,ただ単純にHTMLなどのテキストデータを標準出力に吐き出すCGIが一番簡単なCGIです。"HELLO!"というテキストを表示するCGIを作ってみましょう。名前はhello.cgiとします。

    hello.cgiのテスト,開発パッケージのダウンロードは,「ホームサーバ接続」のデモ・サーバで行って頂けます。通常,デモ・サーバは,午後11時(23時)頃から午前3時頃まで稼働します。

 現在のデモ・サーバの稼働状態は,
    
となっています。このインジケータが,
    緑色の「デモサーバ(demo.argus.ne.jp)は現在稼働中です。」となっている場合はテスト,ダウンロードをして頂けます。
    黄色の「デモサーバ(demo.argus.ne.jp)は現在稼働していません。」となっている場合はテスト,ダウンロードは出来ません。
    
    hello.cgiのテスト (http://demo.argus.ne.jp/cgi-bin/hello.cgi)
    hello.cgiパッケージのダウンロード (http://demo.argus.ne.jp/download/)

そのソースコードは以下の様なものです。
#include	<stdio.h>

void main(void)
{
	puts("Content-type: text/plain");
	puts("");
	puts("HELLO!");
}

 このhello.cgiが吐き出すテキストはご推察の通り,
となります。"\n"は改行コードです。

 1行目 "Content-type: text/plain"は,このデータの形式が単純テキストである事を知らせるヘッダです。
データ形式がHTMLテキストならば,"Content-type: text/html"となります。
JPEG画像ならば,"Content-type: image/jpeg"です。
つまり"Content-type:"の後に来るデータ形式文字列は,MIMEタイプとして定義されているものです。
 2行目 ヘッダとデータを区切りの空行で,絶対に必要です。これが無いと,HTTPサーバはエラーを起こす場合があります。
 3行目 このhello.cgiが送り出すテキストの"HELLO!"です。


MIMEタイプには色々な種類がありますが,例えば次の様なものです。
インターネットで一般的なもの
 text/plain単純なテキスト
 text/html HTMLテキスト
 image/gif GIF形式のイメージ
 image/jpeg JPEG/JFIF形式のイメージ
 audio/aiff AIFF形式の音声データ
 audio/midi MIDIシーケンス
またこの様なものもあります。^^;
 application/msexcel MS-エクセルのスプレッドシート
 application/msword MS-ワードのドキュメント

 次の絵は,ネットスケープナビゲータ,バージョン3.01の設定ダイアローグです。この中の「ファイルタイプ」がMIMEタイプを表しています。




5.Webベージからデータを取る(GETメソッド)
 GETメソッドでデータが送られて来た場合,そのデータは環境変数"QUERY_STRING"に入ります。CGIプログラムは,getenv()関数を使用して,この"QUERY_STRING"を得る事が出来ます。

 "QUERY_STRING"の内容は,WebブラウザがHTTPサーバに送った文字列そのものです。そしてその文字列は,若干のエンコードが行われています。
エンコードされた文字元の文字,意味
&各データのセパレータ
=データラベルとデータのセパレータ
+空白
%引き続く2文字が16進文字コード

 例えば,"Name"と"Category"というテキストボックスがあるフォームで,"Name"に"アーガスネット","Category"に"デモ"と入力して,このフォームの内容をhttp://www.argus.ne.jp/cgi-bin/not-real-cgi.cgiに送るとすると,そのURL行は, となります。そして環境変数"QUERY_STRING"の内容は, となります。

 "Name"や"Category"がテキストボックスの名前(=データラベル),"%83A%81%5B%83K%83X%83l%83b%83g"や"%83f%83%82"などが個々のデータです。テキストボックスの入力文字列が漢字であったため,7ビットASCIIで表現出来ない文字は"%"を使用した文字コード表記にエンコードされています。

 文字コードのパターンを見てお分かりの様に,これはシフトJISのコードです。文字コードセットは,フォームが入っているWebページで使用されているセット,またはWebブラウザのデフォルトが用いられます。テキストボックスに同じ文字列を設定した場合でも,各文字コードセットによって,URL行中のデータ,そして"QUERY_STRING"の内容は変わって来ます。

文字コードセット"QUERY_STRING"の内容
 シフトJIS Name=%83A%81%5B%83K%83X%83l%83b%83g&Category=%83f%83%82
 JIS    Name=%1B%24B%25%22%21%3C%25%2C%259%25M%25C%25H%1B%28B&Category=%1B%24B%25G%25b%1B%28B
 EUC    Name=%A5%A2%A1%BC%A5%AC%A5%B9%A5%CD%A5%C3%A5%C8&Category=%A5%C7%A5%E2

 CGIプログラムは,このエンコードを元に戻す必要があります。そして"name=value"が"&"で区切られているデータを切り分ける必要もあるでしょう。そのサブルーチンは例えば以下の様なものです。
int ProcessQueryString(char *s)
{
	char	*pd;
	int	ch,n;
	
	pd = s;	n = 0;
	while(*s) {
		switch(*s) {
			case '&':	//データのセパレータ
				*pd++ = '\0';
				s++;
				n++;
				break;
			case '+':	//空白
				*pd++ = ' ';
				s++;
				break;
			case '%':	//文字コードエスケープ
				sscanf(s + 1,"%02x",&ch);
				*pd++ = (char)ch;
				s += 3;
				break;
			default:	//7ビットASCII文字
				*pd++ = *s++;
				break;
		}
	}
	*pd++ = '\0';	*pd++ = '\0';
	return n;
}

 そして更に,どの文字コードセットを使っているか分からない様な色々なページからCGIが呼び出されるGOOやYahoo!の検索の様に,汎用的に使用されるCGIで漢字を扱う場合では,使用されている文字コードセットをCGIが判断する必要があります。テキストを見て判断する場合,シフトイン・シフトアウトコードがあるJISとそれ以外は簡単ですが,シフトJISとEUCの見分けは難しいです。短いテキストでは不可能な場合があります。



 それでは,Webベージからデータを取るCGIプログラムを作ってみましょう。名前は"greeting.cgi"とします。

    greeting.cgiのテスト,開発パッケージのダウンロードは,「ホームサーバ接続」のデモ・サーバで行って頂けます。通常,デモ・サーバは,午後11時(23時)頃から午前3時頃まで稼働します。

 現在のデモ・サーバの稼働状態は,
    
となっています。このインジケータが,
    緑色の「デモサーバ(demo.argus.ne.jp)は現在稼働中です。」となっている場合はテスト,ダウンロードをして頂けます。
    黄色の「デモサーバ(demo.argus.ne.jp)は現在稼働していません。」となっている場合はテスト,ダウンロードは出来ません。
    
    greeting.cgiのテスト (http://demo.argus.ne.jp/greeting.html)
    greeting.cgiパッケージのダウンロード (http://demo.argus.ne.jp/download/)

そのメインルーチンは以下の様なものです。
void main(void)
{
	char	QueryString[1024],Name[1024],Email[1024],RemoteHost[1024];
	char	*p,*pData,*pLabel;
	int	len,error;

	error = 0;

	//環境変数"QUERY_STRING"を取得,バッファにコピー
	p = getenv("QUERY_STRING");
	strncpy(QueryString,p,sizeof(QueryString) - 1);
	QueryString[sizeof(QueryString) - 1] = '\0';

	//"QUERY_STRING"のデコードと切り分け
	ProcessQueryString(QueryString);

	//"QUERY_STRING"から目的のデータを取り出す
	pData = QueryString;
	while(*pData) {
		//「お名前」,データ名は"Name"
		pLabel = "Name=";	len = strlen(pLabel);
		if(strncmp(pData,pLabel,len) == 0) {
			if(strlen(pData + len) != 0)
				strcpy(Name,pData + len);
			else	error += 1;
			
		}

		//「メイルアドレス」,データ名は"Email"
		pLabel = "Email=";	len = strlen(pLabel);
		if(strncmp(pData,pLabel,len) == 0) {
			if(strlen(pData + len) != 0)
				strcpy(Email,pData + len);
			else	error += 2;
		}

		//セパレータ(='\0')を探す
		while(*pData)	pData++;

		//次のデータの先頭へ
		pData++;
	}

	//環境変数"REMOTE_HOST"はクライアントのホスト名またはIPアドレスを示している
	p = getenv("REMOTE_HOST");
	if(p != NULL)	strcpy(RemoteHost,p);
	else		strcpy(RemoteHost,"多分インターネット");


	if(error == 0) {	//エラーなし,HTML出力開始
		puts("Content-type: text/html");
		puts("");

		puts("<HTML>");
		puts("<HEAD>");
		puts("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=Shift_JIS\">");
		puts("<TITLE>PWS用CGIプログラム,\"greeting\"からのご挨拶</TITLE>");
		puts("</HEAD>");

		puts("<BODY><CENTER>");
		puts("<H1>PWS用CGIプログラム,\"greeting\"からのご挨拶</H1></CENTER><BR><BR>");

		puts("<B><FONT COLOR=#0000FF>");
		puts(RemoteHost);
		puts("</FONT></B>からお越しの<B><FONT COLOR=#0000FF>");
		puts(Name);
		puts("</FONT></B>さんですね,<BR><BR>");

		puts("PWS用CGIプログラム,\"greeting\"がご挨拶を申し上げます。<BR><BR>");
		puts("ようこそ,ようこそいらっしゃいました。<BR><BR>");

		puts("<B><FONT COLOR=#0000FF>");
		puts(Name);
		puts("</FONT></B>さんのメイルアドレスは<B><FONT COLOR=#0000FF>");
		puts(Email);
		puts("</FONT></B>と承っております。<BR><BR>");

		puts("<HR><BR>");
		puts("<ADDRESS>Copyright(c) ARGUS NET<BR>All rights reserved.<BR></CENTER></ADDRESS><BR>");
		puts("</BODY></HTML>");
	}
	else {	//エラー,HTML出力開始
		puts("Content-type: text/html");
		puts("");

		puts("<HTML>");
		puts("<HEAD>");
		puts("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=Shift_JIS\">");
		puts("<TITLE>PWS用CGIプログラム,\"greeting\"</TITLE>");
		puts("</HEAD>");

		puts("<BODY><CENTER>");
		puts("<H1>PWS用CGIプログラム,\"greeting\"は悲しく思います。</H1><BR><BR>");
		
		if(error & 1)	printf("お名前");
		if(error & 2) {
			if(error != 2)	printf(",そして");
			printf("メイルアドレス");
		}
		puts("が未入力です。<BR><BR>");
		puts("今回はご挨拶は致しません。<BR><BR>");

		puts("<HR><BR>");
		puts("<CENTER><ADDRESS>Copyright(c) ARGUS NET<BR>All rights reserved.<BR></CENTER></ADDRESS><BR>");
		puts("</BODY></HTML>");
	}
}
6.CGIプログラムが受け取る環境変数
 CGIプログラムが受け取る事の出来る環境変数には,3つの種類があります。
 CGIのパラメータとしてWebブラウザがHTTPサーバに渡す情報は,GETメソッドでのフォームの内容です。例えば先のgreetingでは,名前や電子メイルアドレスは,"QUERY_STRING"と言う環境変数に格納されてCGIプログラムに渡されました。

 CGIのパラメータ以外でWebブラウザがHTTPサーバに渡す情報は,WebブラウザがHTTPサーバに渡すコマンド行の中のURLの後に付加されています(これをヘッダフィールドと言います)。それらは,Webブラウザの種類,どの様なファイル種別をWebブラウザが受け取るかなどの情報です。例えば,ネットスケープコミュニケータの場合"http://www.argus.ne.jp/index.html"のURLをアクセスすると,そのコマンド行は次の様になります。 このコマンド行中の"User-Agent:"や"Accept:"などが,先頭に"HTTP_"が付いた形,ヘッダフィールドのラベル中の小文字は全て大文字に変換されて,環境変数となります。それは次の様なものです。
 HTTPサーバが付け加える情報は,HTTPサーバ自体や稼働しているコンピュータから得られる情報,接続に関して得られた情報などです。例えば次の様な環境変数です。  HTTPサーバの種類によっては,上のリストに無い環境変数がある場合もありますし,その逆の場合もあります。


 一部環境変数を除く環境変数の一覧を返すCGIが"dumpenv.cgi"です。

    dumpenv.cgiのテスト,開発パッケージのダウンロードは,「ホームサーバ接続」のデモ・サーバで行って頂けます。通常,デモ・サーバは,午後11時(23時)頃から午前3時頃まで稼働します。

 現在のデモ・サーバの稼働状態は,
    
となっています。このインジケータが,
    緑色の「デモサーバ(demo.argus.ne.jp)は現在稼働中です。」となっている場合はテスト,ダウンロードをして頂けます。
    黄色の「デモサーバ(demo.argus.ne.jp)は現在稼働していません。」となっている場合はテスト,ダウンロードは出来ません。
    
    dumpenv.cgiのテスト (http://demo.argus.ne.jp/cgi-bin/dumpenv.cgi)
    dumpenv.cgiパッケージのダウンロード (http://demo.argus.ne.jp/download/)


7.POSTメソッドを使用するCGIプログラム
 GETメソッドでは,フォームの内容がコマンドラインの一部としてWebブラウザからHTTPサーバに渡され,その内容は環境変数"QUERY_STRING"としてCGIに渡されました。POSTメソッドの場合は,フォームの内容はコマンドラインに引き続くデータとしてWebブラウザからHTTPサーバに渡され,CGIは標準入力からこのデータを受け取る事になります。

このため,フォームデータが大量になる場合(フォーム中の入力フィールドが多い場合やTEXTAREAなどで長い文字列を渡す場合)には,POSTメソッドを使用した方が良いでしょう。GETメソッドの場合,WebブラウザやHTTPサーバ,OSの制限から大量のフォームデータを扱えない場合があります。

 GETメソッドでは環境変数の"QUERY_STRING"から,POSTメソッドでは標準入力から,の様に両メソッドではパラメータ/フォームデータを何処から得るかの違いはありますが,"&"が各フォームデータの区切り,"+"はスペースのエスケープ文字,%が16進エスケープ,などの文字列のエンコード形式は同じです。

 POSTメソッドでフォームデータが渡される場合,環境変数の"REQUEST_METHOD"の値は"POST"になります。また標準入力からどれだけの文字を読み取れば良いかは,環境変数の"CONTENT_LENGTH"で与えられています。

 CGIの仕様に合ったフォームデータの取得方法は,この"CONTENT_LENGTH"の値を数値化して標準入力から取るべき文字数の長さを得,その値の文字数だけを標準入力から読み取る事です。UNIX系のHTTPサーバを相手にするCGIでは,"CONTENT_LENGTH"を見ないでも標準入力が閉じられる,つまりgetchar()の戻り値がEOFになる事などで,全フォームデータをCGIプログラムが引き取った事を検出する方法が取れる事もあります。PWSではこの方法は使用出来ませんし,そしてこの方法は正統的なものではありません。PWSはブラウザから受け取った文字列をCGIに渡した後もパイプを切らないため,CGIプログラムは来るはずの無いデータを永遠に待ち続ける事になります。

 POSTメソッドの場合のフォームデータを取得するコードは以下の様なものです。
	char	*p,*method,*param;
	int	len,n,done;
	
	done = FALSE;	//コードの最後でdoneがTRUEになっていれば正常にパラメータを取得出来た
	
	method = getenv("REQUEST_METHOD");			//"REQUEST_METHOD"を取る
	if(method != NULL) {					//"REQUEST_METHOD"が取れた
		if(stricmp(method,"POST") == 0) {		//POSTメソッド
			p = getenv("CONTENT_LENGTH");		//"CONTENT_LENGTH"を取る
			if(p != NULL) {				//"CONTENT_LENGTH"が取れた
				len = atoi(p);			//"CONTENT_LENGTH"を数値に変換
				param = calloc(1,len + 1);	//パラメータバッファを用意
				if(param != NULL) {		//パラメータバッファが確保出来たら
					n = fread(param,1,len,stdin);	//fread()で一気に読み込む
					if(n == len)	done = TRUE;	//正常に終了
				}
			}
		}
	}



8.GET,POSTの両メソッドに対応するCGIプログラム
 GET,POSTの両メソッドに対応するCGIプログラムは,どの様な方法でデータが渡されるのかを調べる事から始まります。

 前章のお話で,もう察しは付いているかと思いますが,それは環境変数"REQUEST_METHOD"が"GET"であれば環境変数の"QUERY_STRING"によって,"POST"であれば標準入力から,データが渡されます。メソッドに従って環境変数あるいは標準入力からデータを引き取った後は,文字列のデコード処理など必要な処理を行います。これは,GET/POSTとも,全く同じ処理になります。

 GET,POSTの両メソッドに対応するCGIプログラムのパラメータ/フォームデータを読み込む部分のコードは次の様になります。
	char	*p,*method,*param;
	int	len,n,done;
	
	done = FALSE;	//コードの最後でdoneがTRUEになっていれば正常にパラメータを取得出来た
	method = param = NULL;	//後でメモリを解放するための初期化
	
	method = getenv("REQUEST_METHOD");			//"REQUEST_METHOD"を取る
	if(method != NULL) {					//"REQUEST_METHOD"が取れた
		if(stricmp(method,"POST") == 0) {		//POSTメソッド
			p = getenv("CONTENT_LENGTH");		//"CONTENT_LENGTH"を取る
			if(p != NULL) {				//"CONTENT_LENGTH"が取れた
				len = atoi(p);			//"CONTENT_LENGTH"を数値に変換
				param = calloc(1,len + 1);	//パラメータバッファを用意
				if(param != NULL) {		//パラメータバッファが確保出来たら
					n = fread(param,1,len,stdin);	//fread()で一気に読み込む
					if(n == len)	done = TRUE;	//正常に終了
				}
			}
		}
		else if(stricmp(method,"GET") == 0) {	//GETメソッド
			p = getenv("QUERY_STRING");	//"QUERY_STRING"を取る
			if(p != NULL) {			//"QUERY_STRING"が取れた
				param = strdup(p);	//getenv()は揮発性の文字列を返して来るので,strdup()でコピー
				if(param != NULL)	done = TRUE;	//正常に終了
			
		}
		else {	//メソッドがPOSTでもGETでも無い
			//何もしない
		}
	}
	
	//この時点でdoneがTRUEで無ければ,何かのエラー処理を行う
	



9.画像を扱うCGIプログラム
 今まで見てきたCGIプログラムは,text/htmlやtext/plainなどの文字を出力結果とするものでした。しかしCGIプログラムが結果として出力するデータは,何も文字だけとは限りません。画像も,MIDIシーケンスも,PCMデータも出力する事が出来ます。そしてそのデータは,HTTPサーバを通してクライアントマシンのWebブラウザに送られ,画像が表示されたり,音楽や音声が再生されたりします。

 これまでの章の,CGIのテストとダウンロードの所には,デモ・サーバの稼働状態を示すインジケータがありました。それはこの様なものです。


  


  



 この部分は,画像を出力するCGIプログラムで実現しています。その部分のHTMLは,

    <IMG SRC=/cgi-bin/demostat/demostat.cgi>

の様になっています。demostat.cgiは,デモ・サーバの稼働状態を調べ,それに応じた画像データ(gifフォーマット)を送り返しています。これ自体は,UNIX上で動作するCGIプログラムですが,これと同じ機能を果たすPWS用のdemostat.cgiを作成する事が出来ます。と言うより,UNIX用とPWS用は同じソースコードで作成されたものです。

    demostat.cgiのテスト,開発パッケージのダウンロードは,「ホームサーバ接続」のデモ・サーバで行って頂けます。通常,デモ・サーバは,午後11時(23時)頃から午前3時頃まで稼働します。

 現在のデモ・サーバの稼働状態は,
    
となっています。このインジケータが,
    緑色の「デモサーバ(demo.argus.ne.jp)は現在稼働中です。」となっている場合はテスト,ダウンロードをして頂けます。
    黄色の「デモサーバ(demo.argus.ne.jp)は現在稼働していません。」となっている場合はテスト,ダウンロードは出来ません。
    
    demostat.cgiのテスト (http://demo.argus.ne.jp/cgi-bin/demostat/demostat.cgi)
    demostat.cgiパッケージのダウンロード (http://demo.argus.ne.jp/download/)


 demostat.cgiが何を行っているかは,ダウンロードした開発パッケージを見て頂く事にして,画像を扱うCGIプログラムの注意点のお話をしましょう。それは,「標準出力やファイルアクセスの場合のモードに注意!」という事です。

 DOS/Windowsでは,テキストの行末コードは,CR(キャリッジリターン,0Dh)とLF(ラインフィード,0Ah)の2文字が標準です。しかしUNIXでは行末コードはLFの一文字です。このUNIXに仕様を合わせるために,VCを始めとするDOS/Windows上のCコンパイラでは,ライブラリのファイル入出力ルーチンが行末コードの変換を行います。

 CGIプログラムがテキストデータを扱う場合,行末コードの変換が行われても行われなくても,あまり問題はありません。けれども画像を扱うCGIプログラムの場合,CGIプログラムがファイルから読み込み,標準出力に出す画像データは,テキストではなくてバイナリである事がほとんどです。ここで行末コードの変換を行われてしまうと,正しい画像データを扱う事が出来なくなってしまいます。

 ファイル入出力ルーチンに行末コードの変換を行わない様に指定するには,(1)CGIプログラムを作成する時にBINMODE.OBJを一緒にリンクする,(2)ファイルを開く前に大域変数(システム変数)の_fmodeにO_BINARYをセットする,または(3)ファイルをバイナリモードで開く,のいずれかを行います。

 ストリームファイルアクセスの場合   fp = fopen(filename,"rb");
 低水準ファイルアクセスの場合   fd = open(filename,O_RDONLY | O_BINARY);

 標準出力,stdoutは,実行ファイルのスタートアップ・コードが既に開いているファイルです。ですから,上の(2)及び(3)の方法は適用外です。また、(1)の方法,デフォルトのファイルモード指定は,stdoutには(そして,stdin,stderrにも)適用されません。よって,setmode()を使用して,stdoutをバイナリモードに変更します。

    setmode(fileno(stdout),O_BINARY);



10.画像を作成して表示するCGIプログラム
 近日登場!もうしばらくお待ちください。


11.VBによるCGIプログラミング
 「VBでCGIプログラムは出来ないのか」のお問い合わせが多数寄せられていますので,この「VBによるCGIプログラミング」を追加する事にしました。
 近日登場!もうしばらくお待ちください。






Copyright(c) ARGUS NET
All rights reserved.