|
|
1.1 ! root 1: /* D.L.Buck and Associates, Inc. - 8/27/84 ! 2: * ! 3: * COPYRIGHT NOTICE: ! 4: * Copyright c 8/27/84 - An unpublished work by ! 5: * D.L.Buck and Associates, Inc. ! 6: * ! 7: * PROPRIETARY RIGHTS NOTICE: ! 8: * All rights reserved. This document and program contains ! 9: * proprietary information of D.L.Buck and Associates,Inc. ! 10: * of San Jose, California, U.S.A., embodying confidential ! 11: * information, ideas, and expressions, no part of which ! 12: * may be reproduced, or transmitted in any form or by any ! 13: * means, electronic, mechanical, or otherwise, without ! 14: * the written permission of D.L.Buck and Associates, Inc. ! 15: * ! 16: * NAME ! 17: * bsclog - BISYNC batch audit trail utility ! 18: * ! 19: * SYNOPSIS ! 20: * bsclog hostname [-purge=dd] [-from=[yymmdd]hhmm] [-to=[yymmdd]hhmm] ! 21: * [-class=cccc] [-user=uuuu] ! 22: * ! 23: * DESCRIPTION ! 24: * bsclog selectively prints audit trail information gleaned from the ! 25: * AUDIT file, and purges old information to keep the AUDIT file within ! 26: * reasonable size limits. ! 27: * ! 28: * ALGORITHM ! 29: * 1. Process hostname ! 30: * a. check that it was specified, exit if not ! 31: * b. construct host's directory pathname ! 32: * c. change directory ! 33: * 2. Open primary audit file, AUDIT ! 34: * 3. Get options from command line ! 35: * 4. Sort and merge secondary audit files with primary audit file ! 36: * 5. If purge: ! 37: * a. create and open for writing temp purge file (holds results of purge) ! 38: * b. while AUDIT line doesn't meet save criteria, get another AUDIT ! 39: * line ! 40: * c. write lines to temp purge file ! 41: * d. close temp and audit files ! 42: * e. unlink audit file, link temp file to it (temp file becomes the new ! 43: * AUDIT file) ! 44: * 6. If report: ! 45: * a. set up report headers ! 46: * b. while there's another AUDIT entry line, read it and process entries: ! 47: * i. format entry date ! 48: * ii. check that entry meets sort criteria; continue reading if it ! 49: * doesn't ! 50: * iii. if at bottom of page, form feed and print headers ! 51: * iv. construct report line ! 52: * v. print report line ! 53: * 7. Remove any secondary audit files there may be ! 54: * ! 55: */ ! 56: ! 57: #include <sys/types.h> ! 58: #include <sys/dir.h> ! 59: #include <sys/stat.h> ! 60: #include <stdio.h> ! 61: #include <ctype.h> ! 62: #include "local.h" ! 63: #if defined BSD42 ! 64: #include <sys/time.h> ! 65: #else ! 66: #include <time.h> ! 67: #endif ! 68: ! 69: #ifndef lint ! 70: static char sccsid[] = "@(#)bsclog.c 1.10 REL"; ! 71: #endif ! 72: char *strncat(), *strncpy(), *strcat(), *strcpy(); ! 73: void exit(); ! 74: ! 75: #define YES 1 ! 76: #define NO 0 ! 77: #define PATH "/usr/spool/bscbatch/" ! 78: #define RCDLN 160 ! 79: #define PAGELN 60 ! 80: #define PAGEWIDTH 80 ! 81: ! 82: char line[RCDLN]; /* audit trail entry line */ ! 83: char *months[] = {"nope","Jan ","Feb ","Mar ","Apr ","May ","Jun ","Jul ", ! 84: "Aug ","Sep ","Oct ","Nov ","Dec "}; ! 85: ! 86: char *fields = " Class | Date / Time | Message"; ! 87: char *underline = "________________________________________"; ! 88: char *blankfields = " | | "; ! 89: char *blanks = " "; ! 90: ! 91: int age; /* age of audit entry; used with purge */ ! 92: int purge_age; /* purge audit entries older than purge_age */ ! 93: int leap; /* is this year a leap year? */ ! 94: ! 95: /* day_yr is used to compute the day of the year (1-365) of AUDIT entries. ! 96: and in turn is used to compute the age of the entry by subtracting it ! 97: from the current day of the year. day_yr[0] values are for non-leap ! 98: years. day_yr[1] values are for leap years. */ ! 99: static int day_yr[2][13] = { ! 100: {0,0,32,60,90,120,151,180,211,242,272,303,333}, ! 101: {0,0,32,61,91,121,152,181,212,243,273,304,334} }; ! 102: ! 103: long from[2]; /* beginning of time interval for sort */ ! 104: long to[2] = /* end of time interval for sort */ ! 105: { 991231L, /* end of time is 12/31/99 */ ! 106: 2359L }; /* at 23:59 */ ! 107: ! 108: long time(); /* function returns current time */ ! 109: long currtime; /* contains time time() returns */ ! 110: struct tm *t,*localtime(); ! 111: ! 112: char class[8] = "CDEQRST"; /* contains class of AUDIT entries wanted */ ! 113: char user[20] = "all"; /* contains user id of AUDIT entries wanted */ ! 114: char header[3][PAGEWIDTH]; /* contains report header */ ! 115: char fromdate[21] = /* formatted from: MMM DD, YYYY HH:MM */ ! 116: "Earliest Audit Date"; ! 117: char todate[21] = /* formatted to: MMM DD, YYYY HH:MM */ ! 118: "Latest Audit Date"; ! 119: ! 120: FILE *fopen(); /* function opens a file */ ! 121: FILE *audit; /* contains audit file path for open */ ! 122: FILE *temp; /* contains purge temp file path for open */ ! 123: ! 124: main(argc,argv) ! 125: int argc; ! 126: char *argv[]; ! 127: { ! 128: int i,j; /* friendly, neighborhood indices */ ! 129: int purge = 0; /* flags whether or not this is a purge */ ! 130: ! 131: char pathname[50]; /* contains the directory pathname */ ! 132: char hostname[20]; /* contains hostname */ ! 133: ! 134: long time(); /* function returns current time */ ! 135: ! 136: /* check whether the hostname was given (in 1st param if it was) */ ! 137: if (argc < 2 || argv[1][0] == '-') ! 138: strcpy(hostname,"default"); ! 139: else ! 140: strcpy(hostname,argv[1]); ! 141: ! 142: /* process hostname */ ! 143: strcpy(pathname,PATH); ! 144: strcat(pathname,hostname); ! 145: ! 146: if (chdir(pathname) == -1) { ! 147: fprintf(stderr, ! 148: "bsclog: <%s> has no spool directory\n", ! 149: hostname); ! 150: exit(1); ! 151: } ! 152: ! 153: /* open the primary audit file */ ! 154: if ((audit=fopen("AUDIT","r")) == NULL) { ! 155: fprintf(stderr,"bsclog: <%s> has no AUDIT file\n",hostname); ! 156: exit(1); ! 157: } ! 158: ! 159: /* get options from command line */ ! 160: for (i=1;i<argc;++i) { ! 161: if (strncmp(argv[i],"-purge=",7) == 0) { /* process purge opt */ ! 162: if (argc > 3) { ! 163: fprintf(stderr, ! 164: "bsclog: too many arguments for purge\n"); ! 165: exit(1); ! 166: } ! 167: ! 168: if (!isdigit(argv[i][7])) { ! 169: fprintf(stderr, ! 170: "bsclog: not a numeric value <%s>\n",argv[i]); ! 171: exit(1); ! 172: } ! 173: if ((purge_age=atoi(&argv[i][7])) == NULL) ! 174: purge_age = 0; ! 175: purge = YES; ! 176: break; ! 177: } ! 178: ! 179: /* get time interval to select entries from */ ! 180: if (strncmp(argv[i],"-from=",6) == 0) { ! 181: if (argv[i][6] < '0' || argv[i][6] > '9') { ! 182: fprintf(stderr, ! 183: "bsclog: not a numeric value (%s)\n",argv[i]); ! 184: exit(1); ! 185: } ! 186: ! 187: /* format from date and time into MMM DD, YYYY HH:MM, ! 188: and into long numbers to use to determine whether or ! 189: not to print audit entries */ ! 190: makedate(&argv[i][6],fromdate,from); ! 191: ! 192: continue; ! 193: } ! 194: ! 195: /* get time interval to select entries until */ ! 196: if (strncmp(argv[i],"-to=",4) == 0) { ! 197: if (argv[i][4] < '0' || argv[i][4] > '9') { ! 198: fprintf(stderr, ! 199: "bsclog: not a numeric value (%s)\n",argv[i]); ! 200: exit(1); ! 201: } ! 202: ! 203: /* format to date and time into MMM DD, YYYY HH:MM, and ! 204: into long numbers to use in determining whether or ! 205: or not to print audit entries */ ! 206: makedate(&argv[i][4],todate,to); ! 207: ! 208: continue; ! 209: } ! 210: ! 211: /* get class(es) of entries to select */ ! 212: if (strncmp(argv[i],"-class=",7) == 0) { ! 213: strcpy(class,&argv[i][7]); ! 214: ! 215: /* insure that class types are upper case */ ! 216: for (j=0;j<strlen(class);++j) ! 217: class[j] = toupper(class[j]); ! 218: ! 219: continue; ! 220: } ! 221: ! 222: /* get which user entries to select */ ! 223: if (strncmp(argv[i],"-user=",6) == 0) { ! 224: strcpy(user,&argv[i][6]); ! 225: continue; ! 226: } ! 227: ! 228: /* check for invalid parameter */ ! 229: if (argv[i][0] == '-' || (i>=2 && argv[i][0] != '-')) { ! 230: fprintf(stderr, ! 231: "bsclog: unrecognized option <%s>\n",argv[i]); ! 232: exit(1); ! 233: } ! 234: ! 235: } ! 236: ! 237: /* merge the AUDIT files and sort in ascending date/time order. ! 238: the 'system' command submits commands to the shell. Here, it's ! 239: telling the shell to merge all files which begin with AUDIT ! 240: (AUDIT*) into the file AUDIT, skip the first blank-separated ! 241: field of each line, and do a numeric sort on the next one. */ ! 242: ! 243: system("sort -m +2.0n -3 -o AUDIT AUDIT*;rm -f AUDIT.*"); ! 244: ! 245: purge?do_purge():do_report(); /* if purge=YES, purge; else do audit */ ! 246: /* trail report. */ ! 247: } ! 248: ! 249: do_purge() ! 250: { ! 251: /* create and open purge temp file */ ! 252: if ((temp=fopen("TEMPUR","w")) == NULL) { ! 253: fprintf(stderr,"bsclog: can't create temporary file\n"); ! 254: exit(1); ! 255: } ! 256: ! 257: /* purge time - loop until reaching audit entries to be kept */ ! 258: while(fgets(line,RCDLN,audit) != NULL) { ! 259: if (getage() > purge_age) continue; ! 260: ! 261: fputs(line,temp); ! 262: } ! 263: fclose(audit); ! 264: fclose(temp); ! 265: ! 266: /* unlink the purged audit file and link the temp file (has results of ! 267: purge) to AUDIT; unlink temp file to get rid of it */ ! 268: ! 269: unlink("AUDIT"); ! 270: link("TEMPUR","AUDIT"); ! 271: unlink("TEMPUR"); ! 272: ! 273: return; ! 274: } ! 275: ! 276: /* print audit trail report */ ! 277: int pagecount = 1; ! 278: int linecount = 0; ! 279: do_report() ! 280: { ! 281: char *index(); /* function returns a pointer to 1st occurance ! 282: of a given string */ ! 283: char *lnptr; /* points to positions on AUDIT line read in */ ! 284: char reportline[PAGEWIDTH]; /* report lines constructed here */ ! 285: char last_class = ' '; /* class of last line printed (CDRST) */ ! 286: char audate[21]; /* contains audit entry date */ ! 287: char auduser[20]; /* contains audit entry user id */ ! 288: char msgpart[PAGEWIDTH]; /* contains msg part of audit entry */ ! 289: char tmp[PAGEWIDTH]; ! 290: ! 291: long date[2]; ! 292: int i = 0; ! 293: int length; /* keep track of line length */ ! 294: int counter; /* an index */ ! 295: int center; /* used to center headers */ ! 296: /* set up report headers; construct in temp header first to determine ! 297: length, then pad with blanks to center */ ! 298: strcpy(header[0]," Audit Trail Report"); ! 299: ! 300: sprintf(tmp,"From: %s To: %s",fromdate,todate); ! 301: center = (PAGEWIDTH-strlen(tmp))/2; ! 302: strncpy(header[1],blanks,center); ! 303: strcat(header[1],tmp); ! 304: ! 305: sprintf(tmp,"Classes: %s Users: %s ",class,user); ! 306: center = (PAGEWIDTH-strlen(tmp))/2; ! 307: strncpy(header[2],blanks,center); ! 308: strcat(header[2],tmp); ! 309: ! 310: while(fgets(line,RCDLN,audit) != NULL) { ! 311: i = 0; ! 312: while(line[i] != ' ') { ! 313: auduser[i] = line[i]; ! 314: i++; ! 315: } ! 316: auduser[i] = '\0'; ! 317: ! 318: makedate(&line[i+3],audate,date); ! 319: ! 320: /* check that line meets sort criteria */ ! 321: if ((strcmp(user,"all") == 0 || strcmp(user,auduser) == 0) && ! 322: index(class,line[i+1]) != '\0' && ((date[0] >= from[0] && ! 323: date[1] >= from[1] && date[0] < to[0]) || ! 324: (date[0]== to[0] && (date[1] >= from[1] && date[1] <= to[1])))) ! 325: { ! 326: /* if at the end of a page, do a formfeed and ! 327: print header */ ! 328: if (linecount == PAGELN || linecount == 0) ! 329: disp_header(); ! 330: ! 331: /* construct a report line */ ! 332: /* copy class description onto report line */ ! 333: if (line[i+1] != last_class) { ! 334: strcpy(reportline,blankfields); ! 335: fprintf(stdout,"%s\n",reportline); ! 336: if (++linecount >= PAGELN) ! 337: disp_header(); ! 338: switch (line[i+1]) { ! 339: case 'C':{ ! 340: strcpy(reportline," Connect |"); ! 341: break; } ! 342: case 'D':{ ! 343: strcpy(reportline," Disconnect|"); ! 344: break;} ! 345: case 'E':{ ! 346: strcpy(reportline," Error |"); ! 347: break; } ! 348: case 'Q':{ ! 349: strcpy(reportline," Queue |"); ! 350: break; } ! 351: case 'R':{ ! 352: strcpy(reportline," Receive |"); ! 353: break;} ! 354: case 'S':{ ! 355: strcpy(reportline," Send |"); ! 356: break;} ! 357: case 'T':{ ! 358: strcpy(reportline,"Statistics |"); ! 359: break;} ! 360: } ! 361: } ! 362: else ! 363: strcpy(reportline," |"); ! 364: ! 365: /* cat date onto report line */ ! 366: strcat(reportline,audate); ! 367: strcat(reportline,"| "); ! 368: ! 369: /* cat message onto report line */ ! 370: lnptr = &line[i+14]; ! 371: strcpy(msgpart,lnptr); ! 372: if ((length=strlen(msgpart)) <= 45) ! 373: strncat(reportline,msgpart,length-1); ! 374: else ! 375: {/* break msgpart up into 2 lines & cat to reportline*/ ! 376: strncat(reportline,msgpart,35); ! 377: lnptr = &msgpart[35]; ! 378: break_apart: counter = 69; ! 379: while (*lnptr != ',' && *lnptr != ' ' && ! 380: *lnptr != '\n' && *lnptr != '/' && ! 381: counter < 78) ! 382: reportline[counter++] = *lnptr++; ! 383: ! 384: if (*lnptr != '\n') ! 385: reportline[counter++] = *lnptr; ! 386: reportline[counter] = '\0'; ! 387: if (*lnptr != '\n' && *lnptr != '\0') { ! 388: fprintf(stdout,"%s\n",reportline); ! 389: if (++linecount >= PAGELN) ! 390: disp_header(); ! 391: ++lnptr; ! 392: if (*lnptr == ' ') ! 393: ++lnptr; ! 394: strcpy(reportline,blankfields); ! 395: if (strlen(lnptr) > 45) { ! 396: strncat(reportline, ! 397: lnptr,35); ! 398: lnptr += 35; ! 399: goto break_apart; ! 400: } ! 401: ! 402: strncat(reportline,lnptr, ! 403: (strlen(lnptr)-1)); ! 404: } ! 405: } ! 406: fprintf(stdout,"%s\n",reportline); ! 407: ++linecount; ! 408: last_class = line[i+1]; ! 409: } ! 410: } ! 411: ! 412: if (linecount == 0) { /* nothing printed */ ! 413: fprintf(stderr, ! 414: "bsclog: no data meets selection requirements\n"); ! 415: } ! 416: } ! 417: ! 418: /* get age of audit trail entry */ ! 419: getage() ! 420: { ! 421: int i = 0; /* local index */ ! 422: int j; /* local index */ ! 423: int days; /* entry's day of the year (1-365) */ ! 424: int today; /* today's day of the year (1-365) */ ! 425: int year; /* year pulled out of entry */ ! 426: int month; /* month pulled out of entry */ ! 427: int day; /* day pulled out of entry */ ! 428: char lndate[7]; /* the date that gets pulled out of the entry */ ! 429: ! 430: /* look for beginning of date field (user name lengths vary so ...) */ ! 431: while (line[i] != ' ') ! 432: ++i; ! 433: ! 434: /* mmdd of entry starts 3 positions after user name */ ! 435: for (j=0;j<6;++j) ! 436: lndate[j] = line[j+i+3]; ! 437: lndate[6] = '\0'; ! 438: day = atoi(&lndate[4]); ! 439: lndate[4] = '\0'; ! 440: month = atoi(&lndate[2]); ! 441: lndate[2] = '\0'; ! 442: year = atoi(&lndate[0]); ! 443: ! 444: leap = year%4==0 && year%100 != 0 || year%400 == 0?YES:NO; ! 445: days = (day_yr[leap][month]) + day; ! 446: ! 447: /* get current date and time */ ! 448: gettime(); ! 449: ! 450: /* if year < current year, today is the number of days last year + ! 451: the number of days so far this year; otherwise, it's just the ! 452: number of days so far this year. */ ! 453: today = (year<t->tm_year)? (day_yr[leap][12]+31)+t->tm_yday :(t->tm_yday+1); ! 454: ! 455: age = today - days; ! 456: return(age); ! 457: } ! 458: /* return structure pointing to current time */ ! 459: gettime() ! 460: { ! 461: currtime = time((long*)0); ! 462: t = localtime(&currtime); ! 463: } ! 464: ! 465: /* convert string date and time values to MMM DD, YYYY HH:MM format and to ! 466: long format: YYMMDD and HHMM. */ ! 467: makedate(strptr,formdate,longno) ! 468: char *strptr; ! 469: char formdate[18]; ! 470: long longno[2]; ! 471: { ! 472: int month; ! 473: int day; ! 474: int year; ! 475: int hours; ! 476: int minutes; ! 477: ! 478: if (strlen(strptr) >= 10) ! 479: { /* YYMMDDHHMM */ ! 480: minutes = atoi(&strptr[8]); ! 481: strptr[8] = '\0'; ! 482: hours = atoi(&strptr[6]); ! 483: strptr[6] = '\0'; ! 484: day = atoi(&strptr[4]); ! 485: strptr[4] = '\0'; ! 486: month = atoi(&strptr[2]); ! 487: strptr[2] = '\0'; ! 488: year = atoi(&strptr[0]); ! 489: } ! 490: else if (strlen(strptr) == 4) ! 491: { /* HHMM given; use current YYMMDD */ ! 492: minutes = atoi(&strptr[2]); ! 493: strptr[2] = '\0'; ! 494: hours = atoi(&strptr[0]); ! 495: ! 496: /* set month, day, year to current date */ ! 497: gettime(); ! 498: month = (t->tm_mon) + 1; ! 499: day = t->tm_mday; ! 500: year = t->tm_year; ! 501: } ! 502: else /* invalid date/time format */ ! 503: { ! 504: fprintf(stderr, ! 505: "bsclog: date-time format is YYMMDDHHMM or HHMM\n"); ! 506: exit(1); ! 507: } ! 508: ! 509: longno[0] = year * 10000L + month * 100L + day; ! 510: longno[1] = hours * 100L + minutes; ! 511: ! 512: sprintf(formdate," %s%2d, 19%02d %2d:%02d ", ! 513: months[month],day,year,hours,minutes); ! 514: } ! 515: ! 516: /* disp_header() - display report header if line count >= page length */ ! 517: disp_header() ! 518: { ! 519: putc('\f',stdout); ! 520: fprintf(stdout,"%s\n%s\n%s page %d\n\n", ! 521: header[0],header[1],header[2],pagecount); ! 522: ! 523: /* print field header and underline */ ! 524: fprintf(stdout,"%s\n%s%s\n", ! 525: fields,underline,underline); ! 526: ! 527: ++pagecount; ! 528: linecount = 7; ! 529: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.