[unix-pc.sources] Yet another version of traffic.

andy@rbdc.UUCP (Andy Pitts) (02/25/89)

Well here is another version of traffic.  A few weeks ago Lenny Tropiano
posted a copy of traffic to the net.  This is a fine program and
I found it very useful, but it lacked some features I wanted.
So here is a version I wrote with some added features.

1) Traffic now produces its output in alphabetical order,
2) This version uses b-trees that are allocated as needed so
	there is no arbitrary maximum number of systems compiled
	into the code.
3) There are command line options to produce the report from the
	current xerstats (/usr/lib/uucp/.Admin/xferstats) or
	the old stats (/usr/lib/uucp/.Old/xferstats.
4) Any number of file names can be included on the command line.
	This makes it possible to collect daily xferstats files
	and generate a report for several days.
5) Totals have been added to most of the columns.


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  traffic.c
# Wrapped by andy@rbdc on Sat Feb 25 06:13:27 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'traffic.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'traffic.c'\"
else
echo shar: Extracting \"'traffic.c'\" \(6495 characters\)
sed "s/^X//" >'traffic.c' <<'END_OF_FILE'
X/*
X * traffic.c
X *
X * Usage: traffic [-o] [xferstat_file]
X *
X * "traffic reads the file /usr/spool/uucp/.Admin/xfrestats
X * and produces a summary of uucp connectivity.
X *
X * "traffic -o" reads the file /usr/spool/uucp/.Old/xferstats
X *
X * "It is ONLY for System 5 Unix sites running Basic Networking Utilitys.
X * A list of optional filenames may be given instead of .Old/xferstats.
X *
X * To compile: cc -O traffic.c -o traffic
X * --HISTORY--
X * original version:
X * Greg Hackney hack@merkin.cactus.org
X * 12/10/88
X *
X * Modified to allow reverse sorting on traffic usage (time), total line,
X * and the HH:MM format for the time fields
X * Lenny Tropiano ICUS Software Systems (lenny@icus.islp.ny.us)
X * 12/26/88
X *
X * Re-written to use b-trees and produce alphbitical listings,  use
X * multiple optional files, and provide totals.
X * Andy Pitts  (andy@rbdc.UUCP)
X * 2/23/89
X */
X#include <string.h>
X#include <stdio.h>
X#include <string.h>
X
X#include <stdio.h>
X
X#define OLDSTATS "/usr/spool/uucp/.Old/xferstats" /*BNU style xfer file*/
X#define NEWSTATS "/usr/spool/uucp/.Admin/xferstats" /*BNU style xfer file*/
X
X#define TO_KB(x)  ((float) x) / 1000.0
X#define TO_HR(x)  x / 3600
X#define TO_MIN(x) (x % 3600) / 60
X#define TO_SEC(x) (x % 3600) % 60
X#define ADV_CPS(x, y) ((y != 0) ? (float)x / (float)y : 0.0)
X
X#define OUT	"->"  /*uucp flow direction indicator*/
X#define IN	"<-"  /*uucp flow direction indicator*/
X
Xstruct data {
X	char *sysname;		/* name of remote system */
X	long recv;		/* num of bytes rec'd from remote system */
X	long recv_time; 	/* total seconds spent in receive */
X	int recv_cnt;		/* total number of files received */
X	long xmit;		/* num of bytes sent to remote system */
X	long xmit_time; 	/* total seconds spent in transmit */
X	int xmit_cnt;		/* total number of files sent */
X	struct data *left;	/* pointer to left subtree */
X	struct data *right;	/* pointer to right subtree */
X	};
X
X	long total_recv = 0, total_xmit = 0, total_x = 0;
X	long total_recv_time = 0, total_xmit_time = 0;
X	int total_recv_cnt = 0, total_xmit_cnt = 0;
X	struct data *runstats(), *maketree();
X	void printit(), exit();
X	char *malloc();
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	struct data *root;
X	int c, n;
X	extern int optind;
X	extern char *optarg;
X	char *file;
X
X	n = 1;
X	while((c = getopt(argc, argv, "o")) != EOF)
X		switch(c){
X		case 'o':
X			n = 0;
X			break;
X		case '?':
X			(void)fprintf(stderr, "Usage: traffic [-o] [files]\n");
X			exit(1);
X			break;
X		}
X	(void)printf("\n");
X
X	root = (struct data *)NULL;
X	if(optind < argc)
X		for(; optind < argc; optind++){
X			root = runstats(argv[optind], root);
X			(void)printf("%s:\n", argv[optind]);
X		}
X	else {
X		if(n)
X			file = NEWSTATS;
X		else
X			file = OLDSTATS;
X
X		root = runstats(file, root);
X		(void)printf("%s:\n", file);
X	}
X		(void) printf("\
XRemote    K-Bytes  K-Bytes  K-Bytes    Hours    Hours  AvCps AvCps    #    #\n\
XSiteName     Recv     Xmit    Total     Recv     Xmit   Recv  Xmit Recv Xmit\n\
X--------  -------  -------  ------- -------- --------  ----- ----- ---- ----\n");
X		printit(root);
X		(void) printf("\
X--------  -------  -------  ------- -------- --------               ---- ----\n\
X%-8.8s %8.2lf %8.2lf %8.2lf %2d:%.2d:%.2d %2d:%.2d:%.2d               %4d %4d\n"
X			,"Total", TO_KB(total_recv), TO_KB(total_xmit),
X			TO_KB(total_x), TO_HR(total_recv_time),
X			TO_MIN(total_recv_time), TO_SEC(total_recv_time),
X			TO_HR(total_xmit_time), TO_MIN(total_xmit_time),
X			TO_SEC(total_xmit_time),total_recv_cnt,total_xmit_cnt);
X	return(0);
X}
X
Xstruct data *
Xrunstats(file, r)
Xchar *file;
Xstruct data *r;
X{
X	FILE *fp;
X
X	if((fp = fopen(file, "r")) == (FILE *)NULL){
X		(void)fprintf(stderr, "%s not found.\n", file);
X		exit(1);
X	}
X	r = maketree(fp, r);
X	(void)fclose(fp);
X	return(r);
X}
X
Xstruct data *
Xmaketree(fp, root)
XFILE *fp;
Xstruct data *root;
X{
X	struct data *tree();
X	char buf[512], flow[5], sys[20];
X	long bytes, sec;
X	int out;
X
X	while(fgets(buf, sizeof(buf), fp) != NULL){
X		(void)sscanf(buf, "%[^!] %*s %*s %*s %*s %*s %s %ld / %ld %*s",
X			sys, flow, &bytes, &sec);
X
X		if(strcmp(flow, OUT) == 0)
X			out = 1;
X		else if(strcmp(flow, IN) == 0)
X			out = 0;
X		else
X			continue;	/* bad record */
X
X		root = tree(root, sys, out, bytes, sec);
X	}
X	return(root);
X}
X
Xstruct data *
Xtree(root, sys, out, bytes, sec)
Xstruct data *root;
Xchar *sys;
Xint out;
Xlong bytes, sec;
X{
X	struct data *allocnode();
X	char *mvstring();
X	int cond;
X
X	if(root == (struct data *)NULL){
X		root = allocnode();		/* make node for new system */
X		root->sysname = mvstring(sys);
X		if(out){
X			root->xmit = bytes;
X			root->xmit_time = sec;
X			root->xmit_cnt = 1;
X			root->recv = 0;
X			root->recv_time = 0;
X			root->recv_cnt = 0;
X		}else{
X			root->xmit = 0;
X			root->xmit_time = 0;
X			root->xmit_cnt = 0;
X			root->recv = bytes;
X			root->recv_time = sec;
X			root->recv_cnt = 1;
X		}
X		root->left = root->right = (struct data *)NULL;
X	}else	if(cond = strcmp(sys, root->sysname) == 0){
X		/* repeated system */
X		if(out){
X			root->xmit += bytes;
X			root->xmit_time += sec;
X			root->xmit_cnt++;
X		}else{
X			root->recv += bytes;
X			root->recv_time += sec;
X			root->recv_cnt++;
X		}
X	}else if(cond < 0)	/* lower name goes in left subtree */
X		root->left = tree(root->left, sys, out, bytes, sec);
X	else			/* greater name goes in right subtree */
X		root->right = tree(root->right, sys, out, bytes, sec);
X	return(root);
X}
X
Xstruct data *
Xallocnode()
X{
X	struct data *p;
X
X	p = (struct data *) malloc ((unsigned int) sizeof(struct data));
X	if(p == (struct data *)NULL){
X		(void)fprintf(stderr, "Malloc error\n");
X		exit(1);
X	}
X	return(p);
X}
X
Xvoid
Xprintit(r)
Xstruct data *r;
X{
X	if(r != (struct data *)NULL){
X		printit(r->left);
X
X		(void) printf("%-8.8s %8.2lf %8.2lf %8.2lf %2d:%.2d:%.2d \
X%2d:%.2d:%.2d %6.1lf %6.1lf %4d %4d\n",
X			r->sysname, TO_KB(r->recv), TO_KB(r->xmit),
X			TO_KB((r->recv +r->xmit)), TO_HR(r->recv_time),
X			TO_MIN(r->recv_time), TO_SEC(r->recv_time),
X			TO_HR(r->xmit_time), TO_MIN(r->xmit_time), 
X			TO_SEC(r->xmit_time), ADV_CPS(r->recv, r->recv_time),
X			ADV_CPS(r->xmit, r->xmit_time), r->recv_cnt,
X			r->xmit_cnt);
X
X		total_recv += r->recv;
X		total_xmit += r->xmit;
X		total_x += (r->recv + r->xmit);
X		total_recv_time += r->recv_time;
X		total_xmit_time += r->xmit_time;
X		total_recv_cnt += r->recv_cnt;
X		total_xmit_cnt += r->xmit_cnt;
X
X		printit(r->right);
X	}
X}
X
X
Xchar *
Xmvstring(s)
Xchar *s;
X{
X	char *p;
X	p = malloc((unsigned int) (strlen(s) +1));
X	if(p == NULL){
X		(void) printf(stderr, "Strdup malloc error\n");
X		exit(1);
X	}
X	(void)strcpy(p, s);
X	return(p);
X}
END_OF_FILE
if test 6495 -ne `wc -c <'traffic.c'`; then
    echo shar: \"'traffic.c'\" unpacked with wrong size!
fi
# end of 'traffic.c'
fi
echo shar: End of shell archive.
exit 0
-- 
Andy Pitts andy@rbdc.UUCP  : "The giant Gorf was hit in  one eye  by a stone,
bakerst!rbdc!andy          : and that eye  turned  inward  so  that it looked
kd4nc!gladys!rbdc!andy     : into his mind and he died of what he saw there."
pacbell!gladys!rbdc!andy   :   --_The Forgotten Beast of Eld_, McKillip--