00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdio.h>
00029 #include <errno.h>
00030 #include <unistd.h>
00031 #include <strings.h>
00032 #include <string.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <fcntl.h>
00036 #include <time.h>
00037 #include <curses.h>
00038
00039 #define MAX_LOGFILES 128
00040 #define MAX_GREPSTRINGS 10
00041
00042
00043
00044 static char buff[1024] ;
00045 static struct stat statb ;
00046 static time_t mytime, earliest;
00047 static int time_requested = 0;
00048 static int triggered, last_file=0;
00049 static int got_finished = 0;
00050 static int scan_from_end = 0, monochrome = 0;
00051 static char start[128] = "", finish[128]="", suppress[128]="";
00052
00053
00054 static struct tm *filemodtime, *wtime;
00055 static char *timestr;
00056 static int level=0, mins, first_buff;
00057 static int ngrep ;
00058 static int in_hour, in_min, in_sec;
00059 static int req_hour, req_min, start_time;;
00060 static char level_str[] = "dummy string";
00061
00062 static char logfiles[MAX_LOGFILES][128] = {
00063 "/RTS/log/rts.log",
00064 "/RTS/log/trigger.log",
00065 "/RTS/log/evp.log",
00066 "/RTS/log/det.log",
00067 } ;
00068
00069 static char in_buff[MAX_LOGFILES][1024] ;
00070 static int in_buff_full[MAX_LOGFILES];
00071
00072 static int daysinmonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
00073
00074 static char grep_string[MAX_GREPSTRINGS][128] = {
00075 "","","","","","",
00076 } ;
00077
00078
00079 static FILE *files[MAX_LOGFILES] ;
00080 static int rectime[MAX_LOGFILES] ;
00081 static int found_start[MAX_LOGFILES];
00082 static int oldsizes[MAX_LOGFILES] ;
00083
00084
00085
00086
00087
00088 #define COL_NONE 30
00089 #define COL_BLACK 40
00090 #define COL_RED 31
00091 #define COL_GREEN 32
00092 #define COL_YELLOW 33
00093 #define COL_BLUE 34
00094 #define COL_MAGENTA 35
00095 #define COL_CYAN 36
00096 #define COL_WHITE 37
00097 #define BOLD 1
00098 #define NORMAL 0
00099
00100
00101 #define PRINT0 printf("\033[%d;%d;%dm%s\033[0m",NORMAL,COL_NONE,COL_NONE,in_buff[first_buff])
00102
00103 #define PRINT1 printf("\033[%d;%d;%dm%s\033[0m",NORMAL,COL_NONE,COL_NONE,in_buff[first_buff])
00104
00105 #define PRINT2 printf("\033[%d;%d;%dm%s\033[0m",NORMAL,COL_NONE,COL_CYAN,in_buff[first_buff])
00106
00107 #define PRINT3 printf("\033[%d;%d;%dm%s\033[0m",BOLD,COL_NONE,COL_MAGENTA,in_buff[first_buff])
00108
00109 #define PRINT4 printf("\033[%d;%d;%dm%s\033[0m",BOLD,COL_YELLOW,COL_MAGENTA,in_buff[first_buff])
00110
00111 #define PRINT5 printf("\033[%d;%d;%dm%s\033[0m",BOLD,COL_BLACK,COL_RED,in_buff[first_buff])
00112
00113
00114 void printusage();
00115 void parse_arguments(char **argv, int argc);
00116 void find_starting_point(int i, int start_time);
00117
00118 int main(int argc, char *argv[])
00119 {
00120 char *fret ;
00121 int ret;
00122
00123 int i,j;
00124 int data_in ;
00125 off_t bytes_left[MAX_LOGFILES];
00126 int tries = 0;
00127
00128
00129
00130
00131
00132 parse_arguments(argv, argc);
00133
00134 i = 0;
00135
00136 printf("files to be scanned: \n");
00137
00138 while(logfiles[i][0] != 0) {
00139
00140 files[i] = fopen(logfiles[i],"r") ;
00141
00142 if(files[i] == NULL) {
00143 perror(logfiles[i]) ;
00144 exit(1);
00145 }
00146
00147 printf("\t%s\n",logfiles[i++]);
00148 }
00149 last_file = i;
00150
00151 for (i=0; i<last_file; i++) {
00152 found_start[i]=0;
00153 if (scan_from_end) fseek(files[i], 0, SEEK_END);
00154 else if (time_requested != 0) {
00155 start_time = 3600*((req_hour+16)%24) + 60*req_min;
00156 find_starting_point(i,start_time);
00157 }
00158
00159
00160 ret = stat(logfiles[i],&statb) ;
00161
00162 bytes_left[i] = (statb.st_size - ftello(files[i]));
00163 in_buff_full[i] = 0;
00164 }
00165
00166
00167 sleep(3);
00168
00169 if (!monochrome) {
00170 initscr();
00171
00172 if(has_colors() == FALSE) {
00173 endwin();
00174 printf("This terminal does not support color: \n\
00175 use /usr/dt/bin/dtterm -background white\n");
00176 exit(1);
00177 }
00178 endwin();
00179 }
00180
00181 for(;;) {
00182
00183 off_t new_bytes_left, rate;
00184 int inlevel, ib, still_looking;
00185 int eof_found;
00186
00187 data_in = 0 ;
00188
00189 for (i=0; i<last_file;i++) {
00190
00191 if (in_buff_full[i]) continue;
00192
00193 still_looking = 1;
00194 eof_found = 0;
00195
00196 do {
00197 errno = 0 ;
00198 fret = fgets(in_buff[i],sizeof(in_buff[i]),files[i]) ;
00199 if(fret == NULL) {
00200 if(errno) {
00201 perror(logfiles[i]) ;
00202 sleep(1) ;
00203 continue ;
00204 }
00205
00206 ret = stat(logfiles[i],&statb) ;
00207 if(ret < 0) {
00208 perror(logfiles[i]) ;
00209 sleep(1) ;
00210 continue ;
00211 }
00212
00213 if(statb.st_size < oldsizes[i]) {
00214 fclose(files[i]) ;
00215 files[i] = fopen(logfiles[i],"r") ;
00216 oldsizes[i] = 0 ;
00217 continue ;
00218 }
00219 if ((eof_found = feof(files[i]))==1) clearerr(files[i]);
00220 oldsizes[i] = statb.st_size ;
00221 tries++;
00222 if ((tries%10000) == 0) {
00223 fflush(stdout);
00224 printf("\nwaiting for data..%s \r",logfiles[i]);
00225 fflush(stdout);
00226 }
00227 continue ;
00228 }
00229
00230 data_in++ ;
00231 sscanf(in_buff[i],"%*s %d:%d:%d",&in_hour,&in_min,&in_sec);
00232 if ((data_in%2000) == 0) {
00233 fflush(stdout);
00234 printf("\nscanning records: %s %02d:%02d \t\t\t\r",
00235 logfiles[i],in_hour,in_min);
00236 fflush(stdout);
00237 }
00238 ret = stat(logfiles[i],&statb) ;
00239
00240
00241 new_bytes_left = (statb.st_size - ftello(files[i]));
00242 rate = new_bytes_left - bytes_left[i];
00243 if (rate >2000) {
00244 printf("skipping records to catch up\n");
00245 fseeko(files[i], new_bytes_left/2 , SEEK_CUR);
00246
00247 new_bytes_left = (statb.st_size - ftello(files[i]));
00248 }
00249 bytes_left[i] = new_bytes_left;
00250
00251
00252 rectime[i] = 3600*((in_hour +16)%24) + in_min*60 +in_sec;
00253
00254
00255
00256 if (time_requested && !found_start[i])
00257 if (rectime[i] < start_time) {
00258
00259
00260 continue;
00261 }
00262 else {
00263 found_start[i] = 1;
00264
00265 }
00266
00267
00268 if (!triggered) {
00269 if (strstr(in_buff[i],start) != NULL) triggered = 1;
00270 else {
00271 in_buff_full[i] = 0;
00272 continue;
00273 }
00274 }
00275
00276
00277 if (finish[0]) {
00278
00279 if (strstr(in_buff[i],finish) != NULL) got_finished = 1;
00280 }
00281
00282 else if (suppress[0]) {
00283
00284 if (strstr(in_buff[i],suppress) != NULL) {
00285 in_buff_full[i] = 0;
00286 continue;
00287 }
00288 }
00289
00290 if (ngrep) {
00291 int g=0, compare=1;
00292
00293 while (grep_string[g][0]) {
00294 if (strstr(in_buff[i],grep_string[g]) == NULL) compare=0;
00295 g++;
00296 }
00297 if ((!compare) && (!got_finished)) {
00298 in_buff_full[i] = 0;
00299 continue;
00300 }
00301 }
00302
00303 if (strstr(in_buff[i],": DEBUG:" ) != NULL) inlevel=0;
00304 else if(strstr(in_buff[i],": NOTICE:" ) != NULL) inlevel = 1;
00305 else if(strstr(in_buff[i],": WARNING:" ) != NULL) inlevel = 2;
00306 else if(strstr(in_buff[i],": ERROR:" ) != NULL) inlevel = 3;
00307 else if(strstr(in_buff[i],": OPERATOR:") != NULL) inlevel = 4;
00308 else if(strstr(in_buff[i],": TERR:" ) != NULL) inlevel = 5;
00309 else if(strstr(in_buff[i],": CRITICAL:") != NULL) inlevel = 5;
00310 else inlevel = 5;
00311
00312 if (inlevel<level) {
00313 in_buff_full[i] = 0;
00314 continue;
00315 }
00316
00317 still_looking = 0;
00318 in_buff_full[i] = 1;
00319
00320 } while ((!eof_found) && still_looking );
00321
00322
00323
00324 }
00325
00326
00327 first_buff = -1;
00328 earliest = 100000;
00329 for (ib=0; ib<last_file; ib++) {
00330 if (in_buff_full[ib]) {
00331 if (earliest > rectime[ib]) {
00332 earliest = rectime[ib];
00333 first_buff = ib;
00334 }
00335 }
00336 }
00337
00338 if (first_buff < 0) continue;
00339
00340 if (monochrome) {
00341 #ifdef DEBUG
00342 printf("%d: %s",first_buff,in_buff[first_buff]);
00343 #else
00344 printf("%s",in_buff[first_buff]);
00345 #endif
00346 fflush(stdout);
00347 }
00348 else {
00349 switch (inlevel) {
00350 case 0:
00351 PRINT0;
00352 break;
00353 case 1:
00354 PRINT1;
00355 break;
00356 case 2:
00357 PRINT2;
00358 break;
00359 case 3:
00360 PRINT3;
00361 break;
00362 case 4:
00363 PRINT4;
00364 break;
00365 case 5:
00366 PRINT5;
00367 break;
00368 default:
00369 break;
00370 }
00371 fflush(stdout);
00372 }
00373
00374 in_buff_full[first_buff] = 0;
00375
00376
00377
00378
00379 if (got_finished) {
00380 printf("finish string encountered...exiting\n");
00381 exit(0);
00382 }
00383 if(!data_in) sleep(1) ;
00384
00385 }
00386
00387 return -1 ;
00388 }
00389
00390
00391 void parse_arguments(char **argv, int argc)
00392 {
00393 int i,j;
00394 time_t abstime;
00395 struct tm *wtime;
00396
00397 for (i=2; i<=argc; i++) {
00398 if (strncmp(argv[i-1],"-h",2)==0) {
00399 printusage();
00400 }
00401 }
00402 mins = 5;
00403 ngrep = 0;
00404 time(&mytime);
00405
00406 for (j=0,i=2; i<=argc; i++) {
00407 if (strncasecmp(argv[i-1],"-t",2)==0) {
00408 if (argc == i) printusage();
00409 if (strstr(argv[i],":") == NULL) {
00410 sscanf(argv[i],"%d",&mins);
00411 abstime = mytime - 60*mins;
00412 wtime = localtime(&abstime);
00413 req_hour = wtime->tm_hour;
00414 req_min = wtime->tm_min;
00415 }
00416 else {
00417 sscanf(argv[i],"%d:%d",&req_hour,&req_min);
00418 }
00419 time_requested = 1;
00420 printf("display records starting from %02d:%02d\n", req_hour, req_min);
00421 i++;
00422 }
00423 else if (strncasecmp(argv[i-1],"-n",2)==0) {
00424 if (argc == i) printusage();
00425 strcpy(level_str,argv[i++]);
00426 if (strncasecmp(level_str,"DEB",3)==0) level = 0;
00427 else if (strncasecmp(level_str,"NOT",3)==0) level = 1;
00428 else if (strncasecmp(level_str,"WARN",4)==0) level = 2;
00429 else if (strncasecmp(level_str,"ERR",3)==0) level = 3;
00430 else if (strncasecmp(level_str,"OPER",4)==0) level = 4;
00431 else if (strncasecmp(level_str,"CRIT",4)==0) level = 5;
00432 else if (strncasecmp(level_str,"TERR",4)==0) level = 5;
00433 else printusage();
00434 }
00435 else if (strncasecmp(argv[i-1],"-e",2)==0) {
00436
00437 scan_from_end = 1;
00438 printf("scanning from current end(s) of file\n");
00439 }
00440 else if (strncasecmp(argv[i-1],"-m",2)==0) {
00441
00442 monochrome = 1;
00443 printf("monochrome version - no escape sequences\n");
00444 }
00445 else if (strncasecmp(argv[i-1],"-s",2)==0) {
00446 if (argc == i) printusage();
00447 strcat(start,argv[i++]);
00448 }
00449 else if (strncasecmp(argv[i-1],"-f",2)==0) {
00450 if (argc == i) printusage();
00451 strcat(finish,argv[i++]);
00452 }
00453 else if (strncasecmp(argv[i-1],"-g",2)==0) {
00454 if (argc == i) printusage();
00455 if (ngrep==MAX_GREPSTRINGS) printusage();
00456 strcat(grep_string[ngrep++],argv[i++]);
00457 grep_string[ngrep][0] = 0;
00458 }
00459 else if (strncasecmp(argv[i-1],"-v",2)==0) {
00460 if (argc == i) printusage();
00461 strcat(suppress,argv[i++]);
00462 }
00463 else {
00464 strcpy(logfiles[j],argv[i-1]);
00465 if (strstr(logfiles[j],"/")==NULL) {
00466
00467 char temp[128];
00468 strcpy(temp, logfiles[j]);
00469 strcpy(logfiles[j],"/RTS/log/");
00470 strcat(logfiles[j],temp);
00471 }
00472 j++;
00473 }
00474 }
00475
00476 if (j>0) logfiles[j][0] = 0;
00477 triggered = (start[0]) ? 0:1;
00478
00479 printf("level=%d\n",level);
00480 if (start[0]) printf("start \"%s\"\n",start);
00481 if (finish[0]) printf("finish \"%s\"\n",finish);
00482 j=0;
00483 if (ngrep) {
00484 printf("strings required:\n");
00485 while (grep_string[j][0]) printf("\t\"%s\"\n",grep_string[j++]);
00486 }
00487 if (suppress[0]) printf("suppress \"%s\"\n",suppress);
00488
00489 }
00490
00491
00492
00493 void find_starting_point(int i, int start_time)
00494 {
00495 int ret, niter=0;
00496 char * fret;
00497 off_t fsize, fpos, lastpos, bytes_rem;
00498 int ltime;
00499 int req_hour, req_min;
00500
00501 req_hour = (start_time/3600+8)%24;
00502 req_min = (start_time%3600)/60;
00503 printf("find_starting_point(): file %s: start time requested %02d:%02d\n",
00504 logfiles[i], req_hour, req_min);
00505
00506 lastpos = fpos = ftello(files[i]);
00507
00508 ret = stat(logfiles[i],&statb) ;
00509 fsize = statb.st_size;
00510 bytes_rem = fsize - fpos;
00511
00512 while (bytes_rem > 10000) {
00513 fret = fgets(in_buff[i],sizeof(in_buff[i]),files[i]) ;
00514 if(fret == NULL) {
00515 if(errno) {
00516 perror(logfiles[i]) ;
00517 return;
00518 }
00519 fseeko(files[i], 0, SEEK_SET);
00520 break ;
00521 }
00522
00523
00524 fret = fgets(in_buff[i],sizeof(in_buff[i]),files[i]) ;
00525 if(fret == NULL) {
00526 if(errno) {
00527 perror(logfiles[i]) ;
00528 return;
00529 }
00530 fseeko(files[i], 0, SEEK_SET);
00531 break ;
00532 }
00533
00534 sscanf(in_buff[i],"%*s %d:%d:%d",&in_hour,&in_min,&in_sec);
00535
00536
00537
00538 ltime = in_sec + 60*in_min + 3600*((in_hour+16)%24);
00539
00540
00541
00542 if (ltime < start_time) {
00543 lastpos = ftello(files[i]);
00544 if (fsize - lastpos <= bytes_rem/2 ) break;
00545 fseeko(files[i], bytes_rem/2, SEEK_CUR);
00546 bytes_rem = bytes_rem/2;
00547 }
00548 else if (ltime > start_time) {
00549 if (ftello(files[i]) < bytes_rem/2 ) {
00550 fseeko(files[i], 0, SEEK_SET);
00551 break;
00552 }
00553 fseeko(files[i], -bytes_rem/2, SEEK_CUR);
00554 bytes_rem = bytes_rem/2;
00555 }
00556 niter++;
00557 }
00558
00559
00560
00561 if (ltime >= start_time) fseeko(files[i],lastpos,SEEK_SET);
00562
00563 printf(" starting %s at time %02d:%02d after %d iterns\n",
00564 logfiles[i], in_hour, in_min, niter);
00565
00566 return;
00567 }
00568
00569 void printusage() {
00570 printf("usage: logBrowser [-n ALARM_LEVEL] [-t time] [-s \"start string\"]
00571 \t[-f \"stop string\"] [-g \"grep string\"] [-v \"suppress string\"]
00572 \t[file1 [,file2,....]]
00573
00574 ALARM_LEVEL={DEBug,NOTice,WARNing,ERRor,OPERator,CRITical,TERR}
00575 specifies the lowest level to be printed. Values of ALARM_LEVEL
00576 are not case sensitive. Values may be abbreviated as indicated
00577 in upper case. If no alarm level specified all messages will be
00578 displayed.
00579
00580 Log files specified by filename[s] will be displayed. If none are
00581 specified, all log files will be shown. Default path is /RTS/log/.
00582
00583 -t\t max age (minutes) of message to be displayed.
00584 -t\t hour:min absolute time to start displaying messages.
00585 \tDefault value = all messages (beginning of file(s)).
00586 \tArguments containing ':' will be treated as absolute time
00587 \tusing 24 hour clock. logBrowser assumes that a file starts at 08:00
00588 \tand lasts no more than 24 hours. If a start string [-g] is specified,
00589 \tthe default time is beginning of file.
00590
00591 -s\tstart string: no lines will be shown until this string
00592 \tencountered. Quotes are required if whitespace is part of string.
00593
00594 -f\tstop string: program will print this string, then terminate.
00595 \tQuotes are required if whitespace is part of string.
00596
00597 -g\tgrep string: only lines containing (all of) these strings will
00598 \tbe displayed. Multiple [up to %d] grep strings may be specified.
00599 \tQuotes are required if whitespace is part of string. To specify
00600 \tadd'l strings use
00601
00602 \t\t-g string1 -g string2 -g \"string 3\".
00603
00604 -v\tsuppress string: lines containing this string will not
00605 \tbe displayed. Quotes are required if whitespace is part of string.
00606
00607 -e\tstart scanning at the end of file(s).
00608
00609 -m\tmonochrome version (no escape strings sent to terminal).
00610
00611
00612 HINT: In order to get the records interleaved in correct time order from
00613 more than one file, it is necessary to wait for a reocrd from each file
00614 which meets all of the qualifications (-g, for example). If this is not what
00615 you want, then open a separate logBrowser window for each file.\n\n",MAX_GREPSTRINGS);
00616
00617 exit(0);
00618 }