/************************************************************************
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);
}
}