
<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>
次にgdを用いて、合成した画像を出力するカウンタを紹介します。
#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);
}
| このカウンタの本体については、 前の項でも説明してあるので、そちらを参照して下さい。 |