#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "array.h"
#include "intcnt.h"
extern "C" {
#include "error.h"
}
#include "utils.h"
#define MINUTE_STEP 5 /* interval for displaying per-minute info */
#define SECOND_STEP 5 /* interval for displaying per-second info */
class procdata
{
public:
intcnt month;
intcnt dayofmonth;
intcnt hour;
intcnt minute;
intcnt second;
time_t prevts;
intcnt freqs;
char *procname;
};
procdata **procs = NULL;
int nprocs = 0;
char *months[] = {"Jan", "Feb", "Mar", "Apr", "May",
"Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec"};
time_t gen_time_t(int year, int month, int day, int hour, int minute, int seconds)
{
struct tm then;
memset(&then, 0x00, sizeof(then));
then.tm_year = year;
then.tm_mon = month;
then.tm_mday = day;
then.tm_hour = hour;
then.tm_min = minute;
then.tm_sec = seconds;
return mktime(&then);
}
int split_line(char *in, int *year, int *month, int *day,
int *hour, int *minute, int *seconds,
char **proc,
char **line)
{
char rc = 0;
char *fields[6];
char *copy = mystrdup(in);
int loop;
/* format:
* Mmm dd hh:mm:ss host proc[pid]: line
* examples:
* Oct 24 14:44:46 muur snort: spp_portscan: PORTSCAN DETECTED to port 4365 from 195.241.135.194 (STEALTH)
* Oct 24 14:44:52 muur smbd[3059]: [2003/10/24 14:44:52, 0] smbd/oplock_linux.c:linux_init_kernel_oplocks(287)
*/
/* split line up into fields */
fields[0] = copy;
for(;;)
{
char *dummy;
for(loop=1; loop<6; loop++)
{
dummy = strchr(fields[loop-1] + 1, ' ');
if (!dummy)
{
rc = -1;
break;
}
*dummy = 0x00;
dummy++;
while(*dummy == ' ')
dummy++;
fields[loop] = dummy;
}
if (rc == -1) break;
/* year unknown */
*year = 0;
/* month */
for(*month=0; *month < 12; (*month)++)
{
if (strcmp(fields[0], months[*month]) == 0)
break;
}
if (*month == 12)
{
rc = -1;
break;
}
/* day */
*day = atoi(fields[1]);
/* time */
*hour = atoi(fields[2]);
*minute = atoi(&fields[2][3]);
*seconds = atoi(&fields[2][6]);
/* procname */
dummy = strchr(fields[4], '[');
if (dummy)
*dummy = 0x00;
dummy = strchr(fields[4], ':');
if (dummy)
*dummy = 0x00;
*proc = mystrdup(fields[4]);
/* description */
*line = mystrdup(©[fields[5] - fields[0]]);
break;
}
free(copy);
return rc;
}
int process_line(char *in)
{
int rc = 0;
char *proc = NULL, *line = NULL;
time_t now = time(NULL);
struct tm *curtm = localtime(&now);
for(;;)
{
int year, month, day, hour, minute, seconds;
time_t curts;
procdata *curproc = NULL;
int loop;
/* ignore '-- MARK --' lines */
if (strcmp(&in[strlen(in) - 10], "-- MARK --") == 0)
break;
/* ignore "last message repeated x times" lines */
if (strstr(in, "last message repeated ") != NULL && strcmp(&in[strlen(in) - 6], " times") == 0)
break;
/* split line in fields */
if (split_line(in, &year, &month, &day, &hour, &minute,
&seconds, &proc, &line) != 0)
{
rc = -1;
break;
}
/* gen timestamp */
year = curtm -> tm_year;
curts = gen_time_t(year, month, day, hour, minute, seconds);
/* update statistics if already known */
for(loop=0; loop<nprocs; loop++)
{
if (strcmp(procs[loop] -> procname, proc) == 0)
{
curproc = procs[loop];
/* calculate most popular interval */
(curproc -> freqs).add(curts - curproc -> prevts);
curproc -> prevts = curts;
break;
}
}
/* add if new */
if (loop == nprocs)
{
nprocs++;
procs = (procdata **)myrealloc(procs, nprocs * sizeof(procdata *), "procdata *");
procs[nprocs - 1] = new procdata;
if (!procs[nprocs-1])
error_exit("cannot allocate procdata object");
curproc = procs[nprocs - 1];
curproc -> prevts = curts;
curproc -> procname = strdup(proc);
}
(curproc -> month).add(month);
(curproc -> dayofmonth).add(day);
(curproc -> hour).add(hour);
(curproc -> minute).add(minute);
(curproc -> second).add(seconds);
break;
}
free(proc);
free(line);
return rc;
}
void secondstostring(time_t ts, char *to)
{
sprintf(to, "%02d:%02d:%02d", ts / 3600, (ts / 60) % 60, ts % 60);
}
void show_frequency_tables(void)
{
int loop;
printf("<H2>Frequencies</H2>\n");
printf("<TABLE BORDER=\"1\">\n");
printf("<TR><TD><B>Process</B></TD>");
for(loop=0; loop<5; loop++)
printf("<TD><B>Interval / Frequency</B></TD>");
printf("</TR>\n");
for(loop=0; loop<nprocs; loop++)
{
int loop2;
printf("<TR><TD><B>%s</B></TD>", procs[loop]-> procname);
procs[loop] -> freqs.sort();
for(loop2=0; loop2<min(5, procs[loop] -> freqs.getn()); loop2++)
{
char buffer[128];
secondstostring(procs[loop] -> freqs.getvalue(loop2), buffer);
printf("<TD>%s / %d</TD>", buffer, procs[loop] -> freqs.getcnt(loop2));
}
printf("</TR>\n");
}
printf("</TABLE>\n");
}
void show_topx_tables(void)
{
int loop;
printf("<H2>Top10 tables</H2>\n");
/* count */
printf("<H3>Months</H3>\n");
printf("<TABLE BORDER=\"1\">\n");
printf("<TR><TD><B>Month</B></TD>");
for(loop=0; loop<5; loop++)
printf("<TD><B>Process [count]</B></TD>");
printf("</TR>\n");
for(int month=0; month<12; month++)
{
array *amonth = new array(1);
for(loop=0; loop<nprocs; loop++)
amonth -> addstring(procs[loop] -> procname, procs[loop] -> month.getcntfromvalue(month));
amonth -> sort(0);
printf("<TR><TD><B>%s</B></TD>", months[month]);
for(loop=0; loop<min(nprocs, 5); loop++)
if (amonth -> getcounter(loop, 0) == -1)
printf("<TD></TD>");
else
printf("<TD>%s [%d]</TD>", amonth -> getstring(loop), amonth -> getcounter(loop, 0));
printf("</TR>\n");
delete amonth;
}
printf("</TABLE>\n");
printf("<BR>\n");
printf("<H3>Day of month</H3>\n");
printf("<TABLE BORDER=\"1\">\n");
printf("<TR><TD><B>Day</B></TD>");
for(loop=0; loop<5; loop++)
printf("<TD><B>Process [count]</B></TD>");
printf("</TR>\n");
for(int day=0; day<31; day++)
{
array *adayofmonth = new array(1);
for(loop=0; loop<nprocs; loop++)
adayofmonth -> addstring(procs[loop] -> procname, procs[loop] -> dayofmonth.getcntfromvalue(day));
adayofmonth -> sort(0);
printf("<TR><TD><B>%d</B></TD>", day + 1);
for(loop=0; loop<min(nprocs, 5); loop++)
if (adayofmonth -> getcounter(loop, 0) == -1)
printf("<TD></TD>");
else
printf("<TD>%s [%d]</TD>", adayofmonth -> getstring(loop), adayofmonth -> getcounter(loop, 0));
printf("</TR>\n");
delete adayofmonth;
}
printf("</TABLE>\n");
printf("<BR>\n");
printf("<H3>Hour</H3>\n");
printf("<TABLE BORDER=\"1\">\n");
printf("<TR><TD><B>Hour</B></TD>");
for(loop=0; loop<5; loop++)
printf("<TD><B>Process [count]</B></TD>");
printf("</TR>\n");
for(int hour=0; hour<24; hour++)
{
array *ahour = new array(1);
for(loop=0; loop<nprocs; loop++)
ahour -> addstring(procs[loop] -> procname, procs[loop] -> hour.getcntfromvalue(hour));
ahour -> sort(0);
printf("<TR><TD><B>%d</B></TD>", hour+1);
for(loop=0; loop<min(nprocs, 5); loop++)
if (ahour -> getcounter(loop, 0) == -1)
printf("<TD></TD>");
else
printf("<TD>%s [%d]</TD>", ahour -> getstring(loop), ahour -> getcounter(loop, 0));
printf("</TR>\n");
delete ahour;
}
printf("</TABLE>\n");
printf("<BR>\n");
printf("<H3>Minute</H3>\n");
printf("<TABLE BORDER=\"1\">\n");
printf("<TR><TD><B>Minute</B></TD>");
for(loop=0; loop<5; loop++)
printf("<TD><B>Process [count]</B></TD>");
printf("</TR>\n");
for(int minute=0; minute<60; minute += MINUTE_STEP)
{
array *aminute = new array(1);
int dummy;
for(dummy=0; dummy<MINUTE_STEP; dummy++)
{
for(loop=0; loop<nprocs; loop++)
aminute -> addstring(procs[loop] -> procname, procs[loop] -> minute.getcntfromvalue(minute + dummy));
}
aminute -> sort(0);
printf("<TR><TD><B>%d</B></TD>", minute);
for(loop=0; loop<min(nprocs, 5); loop++)
if (aminute -> getcounter(loop, 0) == -1)
printf("<TD></TD>");
else
printf("<TD>%s [%d]</TD>", aminute -> getstring(loop), aminute -> getcounter(loop, 0));
printf("</TR>\n");
delete aminute;
}
printf("</TABLE>\n");
printf("<BR>\n");
/* let's not do per-second, it ain't that intresting */
}
int main(int argc, char *argv[])
{
int fd = 0;
/* open file if filename is given */
if (argc == 2)
{
fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
fprintf(stderr, "Failed to open file %s, reason: %s\n", argv[1], strerror(errno));
return 1;
}
}
buffered_reader br(fd);
/* read & parse logfile */
for(;;)
{
char *line = br.read_line();
if (!line) /* EOF */
break;
(void)process_line(line);
free(line);
}
/* now generate them statistics */
/* show headers */
printf("<HTML><BODY><H1>");
if (argc == 2)
printf("Statistics for '%s'", argv[1]);
else
printf("Syslog statistics");
printf("</H1>\n");
/* frequency table */
show_frequency_tables();
/* tables per month/year/etc. */
show_topx_tables();
/* show trailer */
printf("<BR>\n");
printf("<HR>\n");
printf("slst, (C) by folkert@vanheusden.com\n");
printf("</BODY></HTML>\n");
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1