[comp.sources.misc] submission for comp.sources.misc

jv@mh.nl.UUCP (Johan Vromans) (11/14/87)

Some time ago, someone posted somewhere a shell script to generate UUCP
reports from UUCP files. I don't know who, when and where, but I made the
script running on our systems. The script took too long to complete, so I
rewrote the script in C.
This program has not been adapted to SVR3 (not having such a system). It is
not perfect either.
I added some code to generate weekly reports (using SYSLOG.WEEK).

Take it for what it is worth -- it generates fine reports on our systems.

Whoever wrote the shell script deserves the honour - I only converted it.

Remarks and fixes are welcome.

--
Real-Name: Johan Vromans                 | jv@mh.nl via European backbone
Multihouse N.V., Gouda, The Netherlands  | uucp: ..{uunet!}mcvax!mh.nl!jv
"Its better to light a candle than to curse the darkness"

---------------- CUT HERE ----------------
/* uucpstat.c - to print the UUCP transaction statistics (aap 7/9/87)
 * for System V Release 2 or 3 formatted UUCP transaction files
 * Version 1.0
 *
 * This program will process the uucp transactions for each node and report
 * total transaction statistics. Processing is performed on the file $UUCP_LOG
 * which defaults to:
 * /usr/spool/uucp/SYSLOG (Rlse 2) or /usr/spool/uucp/.Admin/xferstats (Rlse 3).
 * Processing defaults to statistics for the current day. Options allow 
 * processing of all transactions found (usually the current week's 
 * transactions are maintained) or a specific day's transactions.  
 * Output is directed to standard output.
 *
 * INSTALLATION NOTES -
 *
 * uucp.stat is non-intrusive and should be installed with 755 permissions.
 * Set the variable: $RLSE_LVL to the System V major release level that
 * you are running prior to installation.
 *
 * syntax:           uucp.stat [<option>] 
 *
 *  where <option> is one or more of the following:
 *
 *                 -a     :  process all transactions found
 *                 -u     :  do not display user statistics
 *                 -n     :  do not display node statistics
 *                 -t     :  do not display total statistics
 *                 mm/dd  :  process transactions for month/day.
 *                           (do not use leading zeroes)
 *                 -h     :  display syntax only
 *                 -w     :  use logfile.WEEK, implies -a
 *                 -v     :  display program parameters
 *                 
 *   If no <option> is specified, process today's transactions only.
 */

#define PROG_VERSION	"1.0"  	/* Program Version number */
#define RLSE_LVL	2	/* major system V release level */

#include <stdio.h>
#define EOS	'\0'

#if RLSE_LVL == 2
char UUCP_log[] = "/usr/spool/uucp/SYSLOG\0\0\0\0\0\0\0";
#else
char UUCP_log[] = "/usr/spool/uucp/.Admin/xferstats";
#endif

int D_month;
int D_day;
int D_year;
char local_node[20];
char cur_node[20];
char cur_login[32];
char *wrkname;
int uulog;
char *my_name;

/* Print mode flags */
int PF_user = 1;
int PF_node = 1;
int PF_grand = 1;
int PF_param = 0;
int PF_weekly = 0;
int f_date = 1;			/* default is current day's */

int nrecs;
int user_xact;
long user_bytes;
int user_time;
int node_xact;
long node_bytes;
int node_time;
int tot_xact;
long tot_bytes;
int tot_time;

main (argc, argv)
int argc;
char *argv[];
{
    init (argc, argv);
    pre_process ();
    sort ();
    process ();
    return (0);
}

#include <sys/utsname.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>

init (argc, argv)
int argc;
char *argv[];
{
    extern char *optarg;
    extern int optind;
    struct utsname u;
    struct stat st;
    long time();
    int c;
    long now = time (&now);
    char *tempnam ();
    struct tm *lt;
    
    wrkname = tempnam (NULL, "UU");
    my_name = argv[0];
    uname (&u);
    strncpy (local_node, u.nodename, UTSLEN);
    local_node[UTSLEN] = '\0';
    lt = localtime (&now);
    D_day = lt->tm_mday;
    D_month = lt->tm_mon + 1;
    D_year = lt->tm_year;
    
    while ((c = getopt (argc, argv, "aunthwv")) != EOF) {
	switch (c) {
	case '?':
	case 'h':
	    fprintf (stderr, " syntax:  %s [<option>]\n", my_name);
	    fprintf (stderr,  "        where <option> is one or more of the following:\n");
	    fprintf (stderr,  "        -h     :  display syntax \n");
	    fprintf (stderr,  "        -a     :  process statistics for all days found \n");
	    fprintf (stderr,  "        -u     :  do not display user statistics\n");
	    fprintf (stderr,  "        -n     :  do not display node statistics\n");
	    fprintf (stderr,  "        -t     :  do not display total statistics\n");
	    fprintf (stderr,  "        -w	  :  display weekly stats\n");
	    fprintf (stderr,  "        mo/day :  process statistics for specific month/day\n");
	    fprintf (stderr,  "        -v     :  display program characteristics\n");
	    fprintf (stderr,  "        default is to process today's transactions only\n");
	    break;
	case 'u':
	    PF_user = 0;
	    break;
	case 'n':
	    PF_node = 0;
	    break;
	case 't':
	    PF_grand = 0;
	    break;
	case 'v':
	    PF_param = 1;
	    break;
	case 'a':
	    f_date = 0;
	    break;
#if RLSE_LVL == 2
	case 'w':
	    PF_weekly = 1;
	    f_date = 0;
	    strcat (UUCP_log, ".WEEK");
	    break;
#endif
	}
    }

    if (argc > optind) {
	c = atoi (argv[optind]);
	D_day = c % 100;
	D_month = c / 100;
	if (D_day == 0 || D_day > 31 || D_month == 0 || D_month > 12) {
	    fprintf (stderr, "%s: invalid date spec: %s\n",
		my_name, argv[optind]);
	}
	else
	    f_date = 1;
    }

    print_params ();

    if (((uulog = open (UUCP_log, 0)) < 0) ||
	(fstat (uulog, &st) < 0) ||
	(st.st_size == 0)) {
	fprintf (stderr, "File: %s unaccessible or empty\n", UUCP_log);
		exit (1);
    }
}

/* print routines */

/* Display Individual login User Stats */

printit (node, login, xact, bytes, time)
char *node, *login;
int xact, time;
long bytes;
{
    printf ("%-8s %-8s %6d %9ld %8d", node, login, xact, bytes, time);
    if (time != 0)
	printf ("%10d\n", bytes / time);
    else
	printf ("\n\n");
}

user_stats ()
{
    if (PF_user) {
	printit (cur_node, cur_login, user_xact, user_bytes, user_time);
    }
}

/* Display cur_node Statistics */

node_stats ()
{
    if (PF_node) {
	printit (cur_node, "TOTAL:", node_xact, node_bytes, node_time);
	printf ("\n");
    }
}

/* Display Grand Totals */

grand_totals ()
{
    if (PF_grand) {
        printf ("_________________________________________________________________\n\n");
	printit (local_node, "", tot_xact, tot_bytes, tot_time);
	printf ("\n");
   }
}

print_params ()
{
    if (PF_param) {
	printf ("[%s]  Version: %s   O/S Rlse Level: %d\n",
	    my_name, PROG_VERSION, RLSE_LVL);
	printf ("[%s]  Transaction File: %s\n", my_name, UUCP_log);
	printf ("[%s]  Print Flags:%s%s%s\n\n\n", my_name,
	    PF_user ? " User" : "",
	    PF_node ? " Node" : "",
	    PF_grand ? " Total" : "");
    }
}

/* Print header */

print_header ()
{
    long time();
    long now = time (&now);
    char *ctime ();
    char *cp = ctime (&now);
    static char *m_tab = "JanFebMarAprMayJunJulAugSepOctNovDec";
    cp[24] = '\0';

    if (PF_param)
	printf ("\n\n");

    printf ("\tUUCP Network Transaction Statistics\n");
    printf ("\tNode: %s  %s\n", local_node, cp);

    if (f_date)
	printf ("\t(Transactions of: %.3s %d 19%d)\n\n",
	    &m_tab[3*(D_month-1)], D_day, D_year);
    else
	printf ("\t(All Transactions)\n\n");

    printf ("Node     User       Xact     Bytes     Time      Rate (Bytes/Sec)\n");
    printf ("_________________________________________________________________\n\n");
}

/* phase 2 - pre-processing of UUCP_log file

 * by making one pass at the UUCP_log file and extracting just the
 * fields for cur_node & username, byte count and transaction time,
 * then sorting them by node and login, we can process the sub-totals
 * and totals synchronously and process more quickly then by mutiple passes. 
 */
pre_process ()
{
    char buf [BUFSIZ];
    char *cp;
    FILE *uu = fdopen (uulog, "r");
    FILE *wrkfile = fopen (wrkname, "w");
    int mtmp, dtmp;
    int etime;
    long bytes;

    if (PF_param)
	printf ("Selecting ...\n");
    nrecs = 0;
    while ((cp = fgets (buf, BUFSIZ, uu)) != NULL) {
	while (*cp == ' ') cp++;
	if (*cp == '[') continue;
	if (sscanf (cp, "%[^!]!%s %*s (%d/%d%*s %*s %*s %*s %ld / %d",
	    cur_node, cur_login, &mtmp, &dtmp, &bytes, &etime) != 6) {
	    fprintf (stderr, "** fmt ** %s", buf);
	    continue;
	}

	/* if a date option was specified then extract only the records */
	/* for that date */
	if (f_date) {
	    if (mtmp != D_month || dtmp != D_day)
		continue;
	}

#if RLSE_LVL == 3
	      # Rlse 3 xaction log file has time as fractional number
#endif
	fprintf (wrkfile, "%s %s %ld %d\n", cur_node, cur_login, bytes, etime);
	nrecs++;
    }
    fclose (wrkfile);
    fclose (uu);
}

/* now sort the stream in order of node login bytes time */
sort ()
{
    char buf [BUFSIZ];

    if (PF_param)
	printf ("Sorting %d records ...\n", nrecs);
    sprintf (buf, "sort -o %s %s", wrkname, wrkname);
    system (buf);
}

/* phase 3 - process each transaction record and calculate/display stats */

process ()
{
    FILE *wrkfile = fopen (wrkname, "r");
    char buf [BUFSIZ];
    char node [64];
    char login [64];
    long bytes;
    int etime;

    *node = *cur_node = EOS;
    *login = *cur_login = EOS;
    tot_xact = tot_bytes = tot_time = 0;
    user_xact = user_bytes = user_time = 0;
    node_xact = node_bytes = node_time = 0;

    print_header ();
    while (fgets (buf, BUFSIZ, wrkfile) != NULL) {
	sscanf (buf, "%s %s %ld %d", node, login, &bytes, &etime);

	if  (!strcmp (node, cur_node) || *node == EOS) {
	/* first entry or same node as previous entry */

	    if (!strcmp (login, cur_login) || *login == EOS) {
		/* first entry or same cur_login as previous entry */
		user_xact++;
		user_bytes += bytes;
		user_time += etime;
	    }
	    else {
		/* cur_login is different than previous login. */
		/* print current user's summaries. */
		if (*cur_login)
		    user_stats ();

		/* init counters for new cur_login */
		user_xact = 1;
		user_bytes = bytes;
		user_time = etime;
		strcpy (cur_login, login);
	    }

	    /* update node statistics */
	    node_xact++;
	    node_bytes += bytes;
	    node_time += etime;
	    strcpy (cur_node, node);
	}
	else {
	    /* node name is different than previous entry */
	    /* print previous user and cur_node totals */
	    if (*cur_node) {
		user_stats ();
		node_stats ();
	    }

	    /* init counters for new cur_node */
	    strcpy (cur_node, node);
	    strcpy (cur_login, login);
	    user_xact = 1;
	    user_bytes = bytes;
	    user_time = etime;
	    node_xact = 1;
	    node_bytes = bytes;
	    node_time = etime;
	}

	/* update grand totals */
	tot_xact++;
	tot_bytes += bytes;
	tot_time += etime;
    }
    if (*cur_node) {
	user_stats ();
	node_stats ();
	grand_totals ();
    }
    else
	printf ("No transactions found\n");

    fclose (wrkfile);
    unlink (wrkname);
}