如何阅读源代码
,log_fname?log_fp:stdin)!=NULL))
{
if (strlen(buffer) < BUFSIZE-1)
{
if (debug_mode && verbose) fprintf(stderr,"%s ",buffer);
break;
}
if (debug_mode && verbose) fprintf(stderr,"%s",buffer);
}
continue; /* go get next record if any */
}
这一段代码,读入一行,如果这一行超过了程序允许的最大字符数(则是错误的日志数据纪录),则跳过本行剩下的数据,忽略掉(continue进行下一次循环)。同时把total_bad增加一个。如果没有超过程序允许的最大字符数(则是正确的日志数据纪录),则
/* got a record... */
strcpy(tmp_buf, buffer); /* save buffer in case of error */
if (parse_record(buffer)) /* parse the record */
将该数据拷贝到一个缓冲区中,然后调用parse_record()进行处理。我们可以同样的推测一下,get_record()是这个程序的一个主要处理部分,分析了日志数据。在parse_record.c中,有此函数,
/*********************************************/
/* PARSE_RECORD - uhhh, you know... */
/*********************************************/
int parse_record(char *buffer)
{
/* clear out structure */
memset(&log_rec,0,sizeof(struct log_struct));
/*
log_rec.hostname[0]=0;
log_rec.datetime[0]=0;
log_rec.url[0]=0;
log_rec.resp_code=0;
log_rec.xfer_size=0;
log_rec.refer[0]=0;
log_rec.agent[0]=0;
log_rec.srchstr[0]=0;
log_rec.ident[0]=0;
*/
#ifdef USE_DNS
memset(&log_rec.addr,0,sizeof(struct in_addr));
#endif
/* call appropriate handler */
switch (log_type)
{
default:
case LOG_CLF: return parse_record_web(buffer); break; /* clf */
case LOG_FTP: return parse_record_ftp(buffer); break; /* ftp */
case LOG_SQUID: return parse_record_squid(buffer); break; /* squid */
}
}
可以看到,log_rec是一个全局变量,该函数根据日志文件的类型,分别调用三种不同的分析函数。在webalizer.h中,找到该变量的定义,从结构定义中可以看到,结构定义了一个日志文件所可能包含的所有信息(参考CLF,FTP, SQUID日志文件的格式说明)。
/* log record structure */
struct log_struct { char hostname[MAXHOST]; /* hostname */
char datetime[29]; /* raw timestamp */
char url[MAXURL]; /* raw request field */
int resp_code; /* response code */
u_long xfer_size; /* xfer size in bytes */
#ifdef USE_DNS
struct in_addr addr; /* IP address structure */
#endif /* USE_DNS */
char
refer[MAXREF]; /* referrer */
char agent[MAXAGENT]; /* user agent (browser) */
char srchstr[MAXSRCH]; /* search string */
char ident[MAXIDEN