<html> <head> <title></title> </head> <body> あなたは <!--#exec cmd="./count1"--> 番目のお客様よ! </body> </html> |
SSIを含んだHTMLファイルです。 このHTMLファイルがサーバーから送出される前に、 サーバー側で、<!--#exec cmd="./count1"--> の部分が、プログラムcount1の出力に置き換えられます。 ここが、クライアントのリクエストで起動するCGIとは違うところです。 |
#include <stdio.h> #include <unistd.h> main() { long i; int retcode; FILE *fp; char *link="count.link",*count="count.dat"; for(i=0;i<5;i++){ retcode=symlink(count,link); if(retcode==0) break; sleep(5); } fp=fopen(count,"r+"); rewind(fp); fscanf(fp,"%6ld",&i); i++; rewind(fp); fprintf(fp,"%06ld",i); printf("%06ld",i); fclose(fp); unlink(link); } |
ソースコードはこれだけです。 同時アクセスを避けるためのファイルロックには、 あちこちで紹介されているシンボリックリンクを用いる方法を 採用しました。まず、カウントファイルにシンボリックリンクを 張ろうとします。複数ユーザーがアクセスした場合、後の人は、 既に同じ名前のリンクが出来ているので、エラーとなります。 5秒待って5回リトライします。それでもだめな時は、 なんかの理由で、ロックファイルが不正に残ってしまったものとして、 ロックを無視して次に進みます。 カウンタ本体は、カウントファイルのデータをインクリメントして、 その数値を標準出力に書き出しているだけです。 仕事が終ったら、ロックファイルになっているリンクを 削除します。 カウンタを設置する時に、"000000"というないようのファイル count.datを準備しておいて下さいね。パーミッションは666です。 また、カウンタを置くディレクトリのパーミッションも666など nobokyが書き込めるようにして下さい。そうでないと、シンボリック リンクを作成できないからです。 |
#include <stdio.h> #include <unistd.h> main() { long i; char s_count[6],obuf[50]; int retcode; FILE *fp; char *link="count.link",*count="count.dat"; for(i=0;i<5;i++){ retcode=symlink(count,link); if(retcode==0) break; sleep(5); } fp=fopen(count,"r+"); rewind(fp); fscanf(fp,"%6ld",&i); i++; rewind(fp); fprintf(fp,"%06ld",i); sprintf(s_count,"%06ld",i); for(i=0;i<6;i++){ sprintf(obuf, "<img src=\"images/n%c.gif\" align=middle hspace=0>\0", s_count[i]); printf("%s",obuf); } fclose(fp); unlink(link); } |
左はグラフィッカルカウンタのソースコードの
例です。前項の例と同様にSSIを使って呼び出します。 カウンタの数字をsprintf()関数で文字列に変換して、 一桁ごとに分解し、一桁毎の画像をリクエストする <IMG>タグを作成します。 このプログラムを使うためには、 0から9までの画像ファイルを準備する必要があります。 |
#include <stdio.h> #include <unistd.h> #include <string.h> #define MAXLEN 4096 main() { char buf[MAXLEN]; FILE *fp; void counter(); char *docfile="index1.html"; char *mark="<!--counter-->"; printf("Content-type: text/html\n\n"); fp=fopen(docfile,"r "); while(fgets(buf,MAXLEN,fp)){ if(strstr(buf,mark)) counter(); else puts(buf); } fclose(fp); fflush(stdout); } void counter() { long i; char s_count[6],obuf[50]; int retcode; FILE *fp; char *link="count.link",*count="count.dat"; for(i=0;i<5;i++){ retcode=symlink(count,link); if(retcode==0) break; sleep(5); } fp=fopen(count,"r+"); rewind(fp); fscanf(fp,"%6ld",&i); i++; rewind(fp); fprintf(fp,"%06ld",i); sprintf(s_count,"%06ld",i); for(i=0;i<6;i++){ sprintf(obuf, "<img src=\"images/n%c.gif\" align=middle hspace=0>\0", s_count[i]); printf("%s",obuf); } fclose(fp); unlink(link); } |
<html> <head><title> テストページ </title></head> <frameset cols="100%,*" FRAMEBORDER="no"> <FRAME SRC="index1.cgi" SCROLLING="auto" MARGINWIDTH="0" NAME="content"> <FRANE SRC="dummy.html" SCROLLING="no" MARGINWIDTH="0" NAME="dummy"> </frameset> <noframes> <body> <a href="index1.cgi">ここから入ってください</a><p> </body> </noframes> </html>
#include <stdio.h> #include <string.h> #include <unistd.h> #include "gd/gd.h" int main(){ gdImagePtr im,im_in; FILE *in; int brown,i; long count; char s_count[6],inputfile[40]; int width=19,height=28,xoffs=4,yoffs=4; long counter(); count=counter(); sprintf(s_count,"%06ld",count); im=gdImageCreate(122,36); brown=gdImageColorAllocate(im,64,0,0); gdImageFill(im,1,1,brown); for(i=0;i<6;i++){ sprintf(inputfile,"images/n%c.gif\0",s_count[i]); in=fopen(inputfile,"r "); im_in=gdImageCreateFromGif(in); fclose(in); gdImageCopy(im,im_in,xoffs+width*i,yoffs,0,0,width,height); gdImageDestroy(im_in); } printf("Content-type: image/gif\n\n"); gdImageGif(im,stdout); fflush(stdout); gdImageDestroy(im); } |
左にソースコードを示します。下に示したcounter()ルーチン
でカウント数を得ます。そして、それぞれの数字に対応して
準備したgifファイルから画像を読み込んで、合成してひとつの
画像にしてから、出力します。 gdImageCreate()でまず、ブランク画像を生成します。 次に、バックグラウンドの色を定義、アローケートして、 その色で画像を塗りつぶします。 次に、上位の桁から一桁ずつに対応するgifファイルから gdImageCreateFromGif()で画像を読み込んで、 gdImageCopy()で画像を合成します。 画像データはMIMEヘッダを送出した後、 gdImageGif()を用いて、標準出力に送出します。 使いおわった画像データ領域は、 gdImageDestroy()で忘れずに開放します。 |
long counter() { long i; char s_count[6],obuf[50]; int retcode; FILE *fp; char *link="count.link",*count="count.dat"; for(i=0;i<5;i++){ retcode=symlink(count,link); if(retcode==0) break; sleep(5); } fp=fopen(count,"r+"); rewind(fp); fscanf(fp,"%6ld",&i); i++; rewind(fp); fprintf(fp,"%06ld",i); fclose(fp); unlink(link); return(i); } | このカウンタの本体については、 前の項でも説明してあるので、そちらを参照して下さい。 |