/************************************************************************ ssi.c ssi もどき gcc 版 98/07/07 Ver.0.02 うーむ、つかれた。 Perl の方が楽だよね。 表示の開始は、わずかに速いようだけど、他は perl の方が速いような(^^;;; 日付時刻の表示は内蔵したので速いとおもう。 99/11/15 Ver.0.03 パラメータがない時の getenv("QUERY_STRING") の戻り値が変わった? BIGLOBE のサーバーの設定変更による? 99/11/15 Ver.0.04 REMOTE_HOST を REMOTE_ADDR から設定、他 99/12/11 Ver.0.05 99/12/14 Ver.0.06 99/12/14 Ver.0.07 bugfix コンパイル方法 >gcc ssi.c -o ssic.cgi Copyright (c) 1998,1999 がま <gama@mvg.biglobe.ne.jp> ************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <time.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> void ssicmd(char *s); void exec(const char *tag, const char *val); void echo(const char *tag, const char *val); void config(const char *tag, const char *val); void ip2hostname(char *ip); /***********************************************************************/ /* 省略時に表示するファイル名 */ char *dflt_filename = "welcome.htm"; /* timefmt の初期値 Tuesday, 07-Jul-98 11:59:59 JST */ char timefmt[BUFSIZ] = "%A, %d-%b-%y %H:%M:%S %Z"; /***********************************************************************/ #define errname "**** ssi: error filename(%s) **** " #define erropen "**** ssi: error at fopen(%s) ****" #define errexec "**** ssi: error at system(%s) ****" #define errfmt "**** ssi: format error near (%s) ****" /***********************************************************************/ void main() { FILE *HTML; char *filename; char *i, *j, *k; char strbuf[BUFSIZ]; printf( "Content-type: text/html\n\n"); filename = getenv("QUERY_STRING"); if (*filename == NULL) { /* ???? */ /* if (filename == NULL) { */ filename = dflt_filename; /* 省略時のファイル名 */ } if ( strstr(filename,"..")|| *filename == '/' ) { printf (errname, filename); return; } if (!(HTML=fopen(filename,"r"))){ printf (erropen, filename); return; } while ( fgets(strbuf, BUFSIZ, HTML ) ) { /*** 行内に複数の指定は考慮している */ i=strbuf; while ( j = strstr( i, "<!--#") ) { /*** 複数行にわたる指定は考慮していない */ if ( k = strstr ( j+5, "-->") ) { *j=0; fputs(i, stdout); /* <!--# の前 */ *k=0; ssicmd(j+5); /* まんなか */ i=k+3; /* --> の後ろ */ } else { printf(errfmt, i); /* error */ break; } } fputs(i, stdout); } } /************************************************************************ SSI の一般形 <!--#command tag1="value1" tag2="value2" --> ssicmd, ssitag, ssival あとの2つは??手抜き(^^;;; ************************************************************************/ void ssicmd(char *s) { char *ssicmd, *ssitag, *ssival, *t; /****************************************/ ssicmd=s; /* command */ while (*s) { if (isspace(*s)) { break; } *s=tolower(*s); s++; } *s++=0; while (isspace(*s) && *s ) { s++; } /****************************************/ ssitag=s; /* tag1 */ while (*s) { if (*s == '=') { break; } *s=tolower(*s); s++; } *s++=0; while ( *s != '"' && *s ) { s++; } /****************************************/ if (*s++ !='"' ) { /* " を読み飛ばし */ printf(errfmt, ssicmd); /* error */ return; } ssival=s; /* value1 */ while (*s) { if (*s == '"' ) { break; } s++; } *s=0; /***************************************/ if (strcmp("exec",ssicmd) == 0 ) { t=ssival; while (*t++) { if (*t == '?') { *t = ' '; } } exec(ssitag, ssival); } else if (strcmp("echo",ssicmd) == 0 ) { echo(ssitag, ssival); } else if (strcmp("config",ssicmd) == 0 ) { config(ssitag, ssival); } } /***********************************************************************/ void exec(const char *tag, const char *val) { fflush(stdout); if ( system(val) == -1 ) { /* system */ printf(errexec, val); } } /***********************************************************************/ void echo(const char *tag, const char *val) { time_t now; struct tm *tp; char strbuf[BUFSIZ]; char *env; if ( strcmp("DATE_LOCAL", val) == 0 || strcmp("DATE_GMT", val) == 0 ) { now = time(NULL); if ( strcmp("DATE_GMT",val) == 0 ) { tp =gmtime(&now); } else { tp =localtime(&now); } strftime(strbuf, BUFSIZ, timefmt, tp); /* 時刻の形式の変換 */ printf("%s", strbuf); return; } if ( strcmp("REMOTE_HOST", val) == 0 ) { ip2hostname(getenv("REMOTE_ADDR")); return; } if ( strcmp("HTTP_X_FORWARDED_FOR", val) == 0 ) { ip2hostname(getenv(val)); return; } printf("%s", getenv(val)); } /***********************************************************************/ void ip2hostname(char *ip) /* IP アドレスからホスト名を表示 */ { struct hostent *hostname; unsigned char addr[4]; int type = AF_INET; int len = 4; int j = 0; char *i; if (ip == NULL) { printf("%s",ip); return; } i = ip; addr[0]=0; while (*i) { if ( isdigit(*i) ) { addr[j]=addr[j]*10+(*i-'0'); } else if ( *i == '.' ) { j++; addr[j]=0; } else { printf("%s",ip); return; } i++; } if ( NULL != (hostname = gethostbyaddr(addr, len, type))) { printf("%s", hostname->h_name); return; } printf("%s",ip); } /***********************************************************************/ void config(const char *tag, const char *val) { if ( strcmp("timefmt",tag) == 0 ) { strcpy(timefmt, val); } }