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