33 #include <sys/types.h>
39 #define MAX_LOGFILES 128
40 #define MAX_GREPSTRINGS 10
44 static char buff[1024] ;
45 static struct stat statb ;
46 static time_t mytime, earliest;
47 static int time_requested = 0;
48 static int triggered, last_file=0;
49 static int got_finished = 0;
50 static int scan_from_end = 0, monochrome = 0;
51 static char start[128] =
"", finish[128]=
"", suppress[128]=
"";
54 static struct tm *filemodtime, *wtime;
56 static int level=0, mins, first_buff;
58 static int in_hour, in_min, in_sec;
59 static int req_hour, req_min, start_time;;
60 static char level_str[] =
"dummy string";
62 static char logfiles[MAX_LOGFILES][128] = {
64 "/RTS/log/trigger.log",
69 static char in_buff[MAX_LOGFILES][1024] ;
70 static int in_buff_full[MAX_LOGFILES];
72 static int daysinmonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
74 static char grep_string[MAX_GREPSTRINGS][128] = {
79 static FILE *files[MAX_LOGFILES] ;
80 static int rectime[MAX_LOGFILES] ;
81 static int found_start[MAX_LOGFILES];
82 static int oldsizes[MAX_LOGFILES] ;
94 #define COL_MAGENTA 35
101 #define PRINT0 printf("\033[%d;%d;%dm%s\033[0m",NORMAL,COL_NONE,COL_NONE,in_buff[first_buff])
103 #define PRINT1 printf("\033[%d;%d;%dm%s\033[0m",NORMAL,COL_NONE,COL_NONE,in_buff[first_buff])
105 #define PRINT2 printf("\033[%d;%d;%dm%s\033[0m",NORMAL,COL_NONE,COL_CYAN,in_buff[first_buff])
107 #define PRINT3 printf("\033[%d;%d;%dm%s\033[0m",BOLD,COL_NONE,COL_MAGENTA,in_buff[first_buff])
109 #define PRINT4 printf("\033[%d;%d;%dm%s\033[0m",BOLD,COL_YELLOW,COL_MAGENTA,in_buff[first_buff])
111 #define PRINT5 printf("\033[%d;%d;%dm%s\033[0m",BOLD,COL_BLACK,COL_RED,in_buff[first_buff])
115 void parse_arguments(
char **argv,
int argc);
116 void find_starting_point(
int i,
int start_time);
118 int main(
int argc,
char *argv[])
125 off_t bytes_left[MAX_LOGFILES];
132 parse_arguments(argv, argc);
136 printf(
"files to be scanned: \n");
138 while(logfiles[i][0] != 0) {
140 files[i] = fopen(logfiles[i],
"r") ;
142 if(files[i] == NULL) {
143 perror(logfiles[i]) ;
147 printf(
"\t%s\n",logfiles[i++]);
151 for (i=0; i<last_file; i++) {
153 if (scan_from_end) fseek(files[i], 0, SEEK_END);
154 else if (time_requested != 0) {
155 start_time = 3600*((req_hour+16)%24) + 60*req_min;
156 find_starting_point(i,start_time);
160 ret = stat(logfiles[i],&statb) ;
162 bytes_left[i] = (statb.st_size - ftello(files[i]));
172 if(has_colors() == FALSE) {
174 printf(
"This terminal does not support color: \n\
175 use /usr/dt/bin/dtterm -background white\n");
183 off_t new_bytes_left, rate;
184 int inlevel, ib, still_looking;
189 for (i=0; i<last_file;i++) {
191 if (in_buff_full[i])
continue;
198 fret = fgets(in_buff[i],
sizeof(in_buff[i]),files[i]) ;
201 perror(logfiles[i]) ;
206 ret = stat(logfiles[i],&statb) ;
208 perror(logfiles[i]) ;
213 if(statb.st_size < oldsizes[i]) {
215 files[i] = fopen(logfiles[i],
"r") ;
219 if ((eof_found = feof(files[i]))==1) clearerr(files[i]);
220 oldsizes[i] = statb.st_size ;
222 if ((tries%10000) == 0) {
224 printf(
"\nwaiting for data..%s \r",logfiles[i]);
231 sscanf(in_buff[i],
"%*s %d:%d:%d",&in_hour,&in_min,&in_sec);
232 if ((data_in%2000) == 0) {
234 printf(
"\nscanning records: %s %02d:%02d \t\t\t\r",
235 logfiles[i],in_hour,in_min);
238 ret = stat(logfiles[i],&statb) ;
241 new_bytes_left = (statb.st_size - ftello(files[i]));
242 rate = new_bytes_left - bytes_left[i];
244 printf(
"skipping records to catch up\n");
245 fseeko(files[i], new_bytes_left/2 , SEEK_CUR);
247 new_bytes_left = (statb.st_size - ftello(files[i]));
249 bytes_left[i] = new_bytes_left;
252 rectime[i] = 3600*((in_hour +16)%24) + in_min*60 +in_sec;
256 if (time_requested && !found_start[i])
257 if (rectime[i] < start_time) {
269 if (strstr(in_buff[i],start) != NULL) triggered = 1;
279 if (strstr(in_buff[i],finish) != NULL) got_finished = 1;
282 else if (suppress[0]) {
284 if (strstr(in_buff[i],suppress) != NULL) {
293 while (grep_string[g][0]) {
294 if (strstr(in_buff[i],grep_string[g]) == NULL) compare=0;
297 if ((!compare) && (!got_finished)) {
303 if (strstr(in_buff[i],
": DEBUG:" ) != NULL) inlevel=0;
304 else if(strstr(in_buff[i],
": NOTICE:" ) != NULL) inlevel = 1;
305 else if(strstr(in_buff[i],
": WARNING:" ) != NULL) inlevel = 2;
306 else if(strstr(in_buff[i],
": ERROR:" ) != NULL) inlevel = 3;
307 else if(strstr(in_buff[i],
": OPERATOR:") != NULL) inlevel = 4;
308 else if(strstr(in_buff[i],
": TERR:" ) != NULL) inlevel = 5;
309 else if(strstr(in_buff[i],
": CRITICAL:") != NULL) inlevel = 5;
320 }
while ((!eof_found) && still_looking );
329 for (ib=0; ib<last_file; ib++) {
330 if (in_buff_full[ib]) {
331 if (earliest > rectime[ib]) {
332 earliest = rectime[ib];
338 if (first_buff < 0)
continue;
342 printf(
"%d: %s",first_buff,in_buff[first_buff]);
344 printf(
"%s",in_buff[first_buff]);
374 in_buff_full[first_buff] = 0;
380 printf(
"finish string encountered...exiting\n");
383 if(!data_in) sleep(1) ;
391 void parse_arguments(
char **argv,
int argc)
397 for (i=2; i<=argc; i++) {
398 if (strncmp(argv[i-1],
"-h",2)==0) {
406 for (j=0,i=2; i<=argc; i++) {
407 if (strncasecmp(argv[i-1],
"-t",2)==0) {
408 if (argc == i) printusage();
409 if (strstr(argv[i],
":") == NULL) {
410 sscanf(argv[i],
"%d",&mins);
411 abstime = mytime - 60*mins;
412 wtime = localtime(&abstime);
413 req_hour = wtime->tm_hour;
414 req_min = wtime->tm_min;
417 sscanf(argv[i],
"%d:%d",&req_hour,&req_min);
420 printf(
"display records starting from %02d:%02d\n", req_hour, req_min);
423 else if (strncasecmp(argv[i-1],
"-n",2)==0) {
424 if (argc == i) printusage();
425 strcpy(level_str,argv[i++]);
426 if (strncasecmp(level_str,
"DEB",3)==0) level = 0;
427 else if (strncasecmp(level_str,
"NOT",3)==0) level = 1;
428 else if (strncasecmp(level_str,
"WARN",4)==0) level = 2;
429 else if (strncasecmp(level_str,
"ERR",3)==0) level = 3;
430 else if (strncasecmp(level_str,
"OPER",4)==0) level = 4;
431 else if (strncasecmp(level_str,
"CRIT",4)==0) level = 5;
432 else if (strncasecmp(level_str,
"TERR",4)==0) level = 5;
435 else if (strncasecmp(argv[i-1],
"-e",2)==0) {
438 printf(
"scanning from current end(s) of file\n");
440 else if (strncasecmp(argv[i-1],
"-m",2)==0) {
443 printf(
"monochrome version - no escape sequences\n");
445 else if (strncasecmp(argv[i-1],
"-s",2)==0) {
446 if (argc == i) printusage();
447 strcat(start,argv[i++]);
449 else if (strncasecmp(argv[i-1],
"-f",2)==0) {
450 if (argc == i) printusage();
451 strcat(finish,argv[i++]);
453 else if (strncasecmp(argv[i-1],
"-g",2)==0) {
454 if (argc == i) printusage();
455 if (ngrep==MAX_GREPSTRINGS) printusage();
456 strcat(grep_string[ngrep++],argv[i++]);
457 grep_string[ngrep][0] = 0;
459 else if (strncasecmp(argv[i-1],
"-v",2)==0) {
460 if (argc == i) printusage();
461 strcat(suppress,argv[i++]);
464 strcpy(logfiles[j],argv[i-1]);
465 if (strstr(logfiles[j],
"/")==NULL) {
468 strcpy(temp, logfiles[j]);
469 strcpy(logfiles[j],
"/RTS/log/");
470 strcat(logfiles[j],temp);
476 if (j>0) logfiles[j][0] = 0;
477 triggered = (start[0]) ? 0:1;
479 printf(
"level=%d\n",level);
480 if (start[0]) printf(
"start \"%s\"\n",start);
481 if (finish[0]) printf(
"finish \"%s\"\n",finish);
484 printf(
"strings required:\n");
485 while (grep_string[j][0]) printf(
"\t\"%s\"\n",grep_string[j++]);
487 if (suppress[0]) printf(
"suppress \"%s\"\n",suppress);
493 void find_starting_point(
int i,
int start_time)
497 off_t fsize, fpos, lastpos, bytes_rem;
499 int req_hour, req_min;
501 req_hour = (start_time/3600+8)%24;
502 req_min = (start_time%3600)/60;
503 printf(
"find_starting_point(): file %s: start time requested %02d:%02d\n",
504 logfiles[i], req_hour, req_min);
506 lastpos = fpos = ftello(files[i]);
508 ret = stat(logfiles[i],&statb) ;
509 fsize = statb.st_size;
510 bytes_rem = fsize - fpos;
512 while (bytes_rem > 10000) {
513 fret = fgets(in_buff[i],
sizeof(in_buff[i]),files[i]) ;
516 perror(logfiles[i]) ;
519 fseeko(files[i], 0, SEEK_SET);
524 fret = fgets(in_buff[i],
sizeof(in_buff[i]),files[i]) ;
527 perror(logfiles[i]) ;
530 fseeko(files[i], 0, SEEK_SET);
534 sscanf(in_buff[i],
"%*s %d:%d:%d",&in_hour,&in_min,&in_sec);
538 ltime = in_sec + 60*in_min + 3600*((in_hour+16)%24);
542 if (ltime < start_time) {
543 lastpos = ftello(files[i]);
544 if (fsize - lastpos <= bytes_rem/2 )
break;
545 fseeko(files[i], bytes_rem/2, SEEK_CUR);
546 bytes_rem = bytes_rem/2;
548 else if (ltime > start_time) {
549 if (ftello(files[i]) < bytes_rem/2 ) {
550 fseeko(files[i], 0, SEEK_SET);
553 fseeko(files[i], -bytes_rem/2, SEEK_CUR);
554 bytes_rem = bytes_rem/2;
561 if (ltime >= start_time) fseeko(files[i],lastpos,SEEK_SET);
563 printf(
" starting %s at time %02d:%02d after %d iterns\n",
564 logfiles[i], in_hour, in_min, niter);
570 printf(
"usage: logBrowser [-n ALARM_LEVEL] [-t time] [-s \"start string\"]
571 \t[-f \"stop string\"] [-g \"grep string\"] [-v \"suppress string\"]
572 \t[file1 [,file2,....]]
574 ALARM_LEVEL={DEBug,NOTice,WARNing,ERRor,OPERator,CRITical,TERR}
575 specifies the lowest level to be printed. Values of ALARM_LEVEL
576 are not case sensitive. Values may be abbreviated as indicated
577 in upper case. If no alarm level specified all messages will be
580 Log files specified by filename[s] will be displayed. If none are
581 specified, all log files will be shown. Default path is /RTS/log/.
583 -t\t max age (minutes) of message to be displayed.
584 -t\t hour:min absolute time to start displaying messages.
585 \tDefault value = all messages (beginning of file(s)).
586 \tArguments containing ':' will be treated as absolute time
587 \tusing 24 hour clock. logBrowser assumes that a file starts at 08:00
588 \tand lasts no more than 24 hours. If a start string [-g] is specified,
589 \tthe default time is beginning of file.
591 -s\tstart string: no lines will be shown until this string
592 \tencountered. Quotes are required if whitespace is part of string.
594 -f\tstop string: program will print this string, then terminate.
595 \tQuotes are required if whitespace is part of string.
597 -g\tgrep string: only lines containing (all of) these strings will
598 \tbe displayed. Multiple [up to %d] grep strings may be specified.
599 \tQuotes are required if whitespace is part of string. To specify
602 \t\t-g string1 -g string2 -g \"string 3\".
604 -v\tsuppress string: lines containing this string will not
605 \tbe displayed. Quotes are required if whitespace is part of string.
607 -e\tstart scanning at the end of file(s).
609 -m\tmonochrome version (no escape strings sent to terminal).
612 HINT: In order to get the records interleaved in correct time order from
613 more than one file, it is necessary to wait for a reocrd from each file
614 which meets all of the qualifications (-g, for example). If this is not what
615 you want, then open a separate logBrowser window for each file.\n\n",MAX_GREPSTRINGS);