|
|
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.