File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / usr / src / usr.bin / bsc / cmd / batch / bsclog.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:26:12 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v121, HEAD
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;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.