|
|
Power 6/32 Unix version 1.21
/* D.L.Buck and Associates, Inc. - 8/27/84
*
* COPYRIGHT NOTICE:
* Copyright c 8/27/84 - An unpublished work by
* D.L.Buck and Associates, Inc.
*
* PROPRIETARY RIGHTS NOTICE:
* All rights reserved. This document and program contains
* proprietary information of D.L.Buck and Associates,Inc.
* of San Jose, California, U.S.A., embodying confidential
* information, ideas, and expressions, no part of which
* may be reproduced, or transmitted in any form or by any
* means, electronic, mechanical, or otherwise, without
* the written permission of D.L.Buck and Associates, Inc.
*
* NAME
* bsclog - BISYNC batch audit trail utility
*
* SYNOPSIS
* bsclog hostname [-purge=dd] [-from=[yymmdd]hhmm] [-to=[yymmdd]hhmm]
* [-class=cccc] [-user=uuuu]
*
* DESCRIPTION
* bsclog selectively prints audit trail information gleaned from the
* AUDIT file, and purges old information to keep the AUDIT file within
* reasonable size limits.
*
* ALGORITHM
* 1. Process hostname
* a. check that it was specified, exit if not
* b. construct host's directory pathname
* c. change directory
* 2. Open primary audit file, AUDIT
* 3. Get options from command line
* 4. Sort and merge secondary audit files with primary audit file
* 5. If purge:
* a. create and open for writing temp purge file (holds results of purge)
* b. while AUDIT line doesn't meet save criteria, get another AUDIT
* line
* c. write lines to temp purge file
* d. close temp and audit files
* e. unlink audit file, link temp file to it (temp file becomes the new
* AUDIT file)
* 6. If report:
* a. set up report headers
* b. while there's another AUDIT entry line, read it and process entries:
* i. format entry date
* ii. check that entry meets sort criteria; continue reading if it
* doesn't
* iii. if at bottom of page, form feed and print headers
* iv. construct report line
* v. print report line
* 7. Remove any secondary audit files there may be
*
*/
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include "local.h"
#if defined BSD42
#include <sys/time.h>
#else
#include <time.h>
#endif
#ifndef lint
static char sccsid[] = "@(#)bsclog.c 1.10 REL";
#endif
char *strncat(), *strncpy(), *strcat(), *strcpy();
void exit();
#define YES 1
#define NO 0
#define PATH "/usr/spool/bscbatch/"
#define RCDLN 160
#define PAGELN 60
#define PAGEWIDTH 80
char line[RCDLN]; /* audit trail entry line */
char *months[] = {"nope","Jan ","Feb ","Mar ","Apr ","May ","Jun ","Jul ",
"Aug ","Sep ","Oct ","Nov ","Dec "};
char *fields = " Class | Date / Time | Message";
char *underline = "________________________________________";
char *blankfields = " | | ";
char *blanks = " ";
int age; /* age of audit entry; used with purge */
int purge_age; /* purge audit entries older than purge_age */
int leap; /* is this year a leap year? */
/* day_yr is used to compute the day of the year (1-365) of AUDIT entries.
and in turn is used to compute the age of the entry by subtracting it
from the current day of the year. day_yr[0] values are for non-leap
years. day_yr[1] values are for leap years. */
static int day_yr[2][13] = {
{0,0,32,60,90,120,151,180,211,242,272,303,333},
{0,0,32,61,91,121,152,181,212,243,273,304,334} };
long from[2]; /* beginning of time interval for sort */
long to[2] = /* end of time interval for sort */
{ 991231L, /* end of time is 12/31/99 */
2359L }; /* at 23:59 */
long time(); /* function returns current time */
long currtime; /* contains time time() returns */
struct tm *t,*localtime();
char class[8] = "CDEQRST"; /* contains class of AUDIT entries wanted */
char user[20] = "all"; /* contains user id of AUDIT entries wanted */
char header[3][PAGEWIDTH]; /* contains report header */
char fromdate[21] = /* formatted from: MMM DD, YYYY HH:MM */
"Earliest Audit Date";
char todate[21] = /* formatted to: MMM DD, YYYY HH:MM */
"Latest Audit Date";
FILE *fopen(); /* function opens a file */
FILE *audit; /* contains audit file path for open */
FILE *temp; /* contains purge temp file path for open */
main(argc,argv)
int argc;
char *argv[];
{
int i,j; /* friendly, neighborhood indices */
int purge = 0; /* flags whether or not this is a purge */
char pathname[50]; /* contains the directory pathname */
char hostname[20]; /* contains hostname */
long time(); /* function returns current time */
/* check whether the hostname was given (in 1st param if it was) */
if (argc < 2 || argv[1][0] == '-')
strcpy(hostname,"default");
else
strcpy(hostname,argv[1]);
/* process hostname */
strcpy(pathname,PATH);
strcat(pathname,hostname);
if (chdir(pathname) == -1) {
fprintf(stderr,
"bsclog: <%s> has no spool directory\n",
hostname);
exit(1);
}
/* open the primary audit file */
if ((audit=fopen("AUDIT","r")) == NULL) {
fprintf(stderr,"bsclog: <%s> has no AUDIT file\n",hostname);
exit(1);
}
/* get options from command line */
for (i=1;i<argc;++i) {
if (strncmp(argv[i],"-purge=",7) == 0) { /* process purge opt */
if (argc > 3) {
fprintf(stderr,
"bsclog: too many arguments for purge\n");
exit(1);
}
if (!isdigit(argv[i][7])) {
fprintf(stderr,
"bsclog: not a numeric value <%s>\n",argv[i]);
exit(1);
}
if ((purge_age=atoi(&argv[i][7])) == NULL)
purge_age = 0;
purge = YES;
break;
}
/* get time interval to select entries from */
if (strncmp(argv[i],"-from=",6) == 0) {
if (argv[i][6] < '0' || argv[i][6] > '9') {
fprintf(stderr,
"bsclog: not a numeric value (%s)\n",argv[i]);
exit(1);
}
/* format from date and time into MMM DD, YYYY HH:MM,
and into long numbers to use to determine whether or
not to print audit entries */
makedate(&argv[i][6],fromdate,from);
continue;
}
/* get time interval to select entries until */
if (strncmp(argv[i],"-to=",4) == 0) {
if (argv[i][4] < '0' || argv[i][4] > '9') {
fprintf(stderr,
"bsclog: not a numeric value (%s)\n",argv[i]);
exit(1);
}
/* format to date and time into MMM DD, YYYY HH:MM, and
into long numbers to use in determining whether or
or not to print audit entries */
makedate(&argv[i][4],todate,to);
continue;
}
/* get class(es) of entries to select */
if (strncmp(argv[i],"-class=",7) == 0) {
strcpy(class,&argv[i][7]);
/* insure that class types are upper case */
for (j=0;j<strlen(class);++j)
class[j] = toupper(class[j]);
continue;
}
/* get which user entries to select */
if (strncmp(argv[i],"-user=",6) == 0) {
strcpy(user,&argv[i][6]);
continue;
}
/* check for invalid parameter */
if (argv[i][0] == '-' || (i>=2 && argv[i][0] != '-')) {
fprintf(stderr,
"bsclog: unrecognized option <%s>\n",argv[i]);
exit(1);
}
}
/* merge the AUDIT files and sort in ascending date/time order.
the 'system' command submits commands to the shell. Here, it's
telling the shell to merge all files which begin with AUDIT
(AUDIT*) into the file AUDIT, skip the first blank-separated
field of each line, and do a numeric sort on the next one. */
system("sort -m +2.0n -3 -o AUDIT AUDIT*;rm -f AUDIT.*");
purge?do_purge():do_report(); /* if purge=YES, purge; else do audit */
/* trail report. */
}
do_purge()
{
/* create and open purge temp file */
if ((temp=fopen("TEMPUR","w")) == NULL) {
fprintf(stderr,"bsclog: can't create temporary file\n");
exit(1);
}
/* purge time - loop until reaching audit entries to be kept */
while(fgets(line,RCDLN,audit) != NULL) {
if (getage() > purge_age) continue;
fputs(line,temp);
}
fclose(audit);
fclose(temp);
/* unlink the purged audit file and link the temp file (has results of
purge) to AUDIT; unlink temp file to get rid of it */
unlink("AUDIT");
link("TEMPUR","AUDIT");
unlink("TEMPUR");
return;
}
/* print audit trail report */
int pagecount = 1;
int linecount = 0;
do_report()
{
char *index(); /* function returns a pointer to 1st occurance
of a given string */
char *lnptr; /* points to positions on AUDIT line read in */
char reportline[PAGEWIDTH]; /* report lines constructed here */
char last_class = ' '; /* class of last line printed (CDRST) */
char audate[21]; /* contains audit entry date */
char auduser[20]; /* contains audit entry user id */
char msgpart[PAGEWIDTH]; /* contains msg part of audit entry */
char tmp[PAGEWIDTH];
long date[2];
int i = 0;
int length; /* keep track of line length */
int counter; /* an index */
int center; /* used to center headers */
/* set up report headers; construct in temp header first to determine
length, then pad with blanks to center */
strcpy(header[0]," Audit Trail Report");
sprintf(tmp,"From: %s To: %s",fromdate,todate);
center = (PAGEWIDTH-strlen(tmp))/2;
strncpy(header[1],blanks,center);
strcat(header[1],tmp);
sprintf(tmp,"Classes: %s Users: %s ",class,user);
center = (PAGEWIDTH-strlen(tmp))/2;
strncpy(header[2],blanks,center);
strcat(header[2],tmp);
while(fgets(line,RCDLN,audit) != NULL) {
i = 0;
while(line[i] != ' ') {
auduser[i] = line[i];
i++;
}
auduser[i] = '\0';
makedate(&line[i+3],audate,date);
/* check that line meets sort criteria */
if ((strcmp(user,"all") == 0 || strcmp(user,auduser) == 0) &&
index(class,line[i+1]) != '\0' && ((date[0] >= from[0] &&
date[1] >= from[1] && date[0] < to[0]) ||
(date[0]== to[0] && (date[1] >= from[1] && date[1] <= to[1]))))
{
/* if at the end of a page, do a formfeed and
print header */
if (linecount == PAGELN || linecount == 0)
disp_header();
/* construct a report line */
/* copy class description onto report line */
if (line[i+1] != last_class) {
strcpy(reportline,blankfields);
fprintf(stdout,"%s\n",reportline);
if (++linecount >= PAGELN)
disp_header();
switch (line[i+1]) {
case 'C':{
strcpy(reportline," Connect |");
break; }
case 'D':{
strcpy(reportline," Disconnect|");
break;}
case 'E':{
strcpy(reportline," Error |");
break; }
case 'Q':{
strcpy(reportline," Queue |");
break; }
case 'R':{
strcpy(reportline," Receive |");
break;}
case 'S':{
strcpy(reportline," Send |");
break;}
case 'T':{
strcpy(reportline,"Statistics |");
break;}
}
}
else
strcpy(reportline," |");
/* cat date onto report line */
strcat(reportline,audate);
strcat(reportline,"| ");
/* cat message onto report line */
lnptr = &line[i+14];
strcpy(msgpart,lnptr);
if ((length=strlen(msgpart)) <= 45)
strncat(reportline,msgpart,length-1);
else
{/* break msgpart up into 2 lines & cat to reportline*/
strncat(reportline,msgpart,35);
lnptr = &msgpart[35];
break_apart: counter = 69;
while (*lnptr != ',' && *lnptr != ' ' &&
*lnptr != '\n' && *lnptr != '/' &&
counter < 78)
reportline[counter++] = *lnptr++;
if (*lnptr != '\n')
reportline[counter++] = *lnptr;
reportline[counter] = '\0';
if (*lnptr != '\n' && *lnptr != '\0') {
fprintf(stdout,"%s\n",reportline);
if (++linecount >= PAGELN)
disp_header();
++lnptr;
if (*lnptr == ' ')
++lnptr;
strcpy(reportline,blankfields);
if (strlen(lnptr) > 45) {
strncat(reportline,
lnptr,35);
lnptr += 35;
goto break_apart;
}
strncat(reportline,lnptr,
(strlen(lnptr)-1));
}
}
fprintf(stdout,"%s\n",reportline);
++linecount;
last_class = line[i+1];
}
}
if (linecount == 0) { /* nothing printed */
fprintf(stderr,
"bsclog: no data meets selection requirements\n");
}
}
/* get age of audit trail entry */
getage()
{
int i = 0; /* local index */
int j; /* local index */
int days; /* entry's day of the year (1-365) */
int today; /* today's day of the year (1-365) */
int year; /* year pulled out of entry */
int month; /* month pulled out of entry */
int day; /* day pulled out of entry */
char lndate[7]; /* the date that gets pulled out of the entry */
/* look for beginning of date field (user name lengths vary so ...) */
while (line[i] != ' ')
++i;
/* mmdd of entry starts 3 positions after user name */
for (j=0;j<6;++j)
lndate[j] = line[j+i+3];
lndate[6] = '\0';
day = atoi(&lndate[4]);
lndate[4] = '\0';
month = atoi(&lndate[2]);
lndate[2] = '\0';
year = atoi(&lndate[0]);
leap = year%4==0 && year%100 != 0 || year%400 == 0?YES:NO;
days = (day_yr[leap][month]) + day;
/* get current date and time */
gettime();
/* if year < current year, today is the number of days last year +
the number of days so far this year; otherwise, it's just the
number of days so far this year. */
today = (year<t->tm_year)? (day_yr[leap][12]+31)+t->tm_yday :(t->tm_yday+1);
age = today - days;
return(age);
}
/* return structure pointing to current time */
gettime()
{
currtime = time((long*)0);
t = localtime(&currtime);
}
/* convert string date and time values to MMM DD, YYYY HH:MM format and to
long format: YYMMDD and HHMM. */
makedate(strptr,formdate,longno)
char *strptr;
char formdate[18];
long longno[2];
{
int month;
int day;
int year;
int hours;
int minutes;
if (strlen(strptr) >= 10)
{ /* YYMMDDHHMM */
minutes = atoi(&strptr[8]);
strptr[8] = '\0';
hours = atoi(&strptr[6]);
strptr[6] = '\0';
day = atoi(&strptr[4]);
strptr[4] = '\0';
month = atoi(&strptr[2]);
strptr[2] = '\0';
year = atoi(&strptr[0]);
}
else if (strlen(strptr) == 4)
{ /* HHMM given; use current YYMMDD */
minutes = atoi(&strptr[2]);
strptr[2] = '\0';
hours = atoi(&strptr[0]);
/* set month, day, year to current date */
gettime();
month = (t->tm_mon) + 1;
day = t->tm_mday;
year = t->tm_year;
}
else /* invalid date/time format */
{
fprintf(stderr,
"bsclog: date-time format is YYMMDDHHMM or HHMM\n");
exit(1);
}
longno[0] = year * 10000L + month * 100L + day;
longno[1] = hours * 100L + minutes;
sprintf(formdate," %s%2d, 19%02d %2d:%02d ",
months[month],day,year,hours,minutes);
}
/* disp_header() - display report header if line count >= page length */
disp_header()
{
putc('\f',stdout);
fprintf(stdout,"%s\n%s\n%s page %d\n\n",
header[0],header[1],header[2],pagecount);
/* print field header and underline */
fprintf(stdout,"%s\n%s%s\n",
fields,underline,underline);
++pagecount;
linecount = 7;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.