/*
                 UUTraf - UUCP transmission statistics

 	Genesis     : Sat Feb 15 14:11:09 1992
 	Last Change : Wed Feb 19 17:27:15 1992

	Developed and debugged with SAS/C Compiler V5.10a
	running under Kickstart 34.5, Workbench 34.20 and ARP 39.1
	on an european PAL-Amiga 2000 B Rev 4.3 with 3MB RAM.

	                        ___  _______
	Ralf S. Engelschall,    /__)(_  /_              rse@angle.muc.sub.org
	 Weblinger Weg 28,     / \____)(___           rse@cyvaned.muc.sub.org
	  8060 Dachau,        /
	   West Germany          ...!smurf.sub.org!brumuc!{angle,cyvaned}!rse
																			*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cus.h"
#include "defines.h"
#include "lbio.h"
#include "proto.h"

#define STATFILE "uuspool:xferstat"
#define LSYSFILE "uulib:l.sys"

#define LASTLN_UNRECOGNICED 0
#define LASTLN_FIRST 1
#define LASTLN_SECOND 2

static struct TotalStat {
	unsigned int Sites;
	unsigned int FilesRecv, FilesSent, Files;
	unsigned int SecondRecv, SecondSent, Second;
	unsigned int BytesRecv, BytesSent, Bytes;
} TotalStatStruct;

struct HostStat {
	char Hostname[10];
	unsigned int BytesRecv, BytesSent, Bytes;
	unsigned int SecondRecv, SecondSent;
	float AvCpsRecv, AvCpsSent;
	unsigned int FilesRecv, FilesSent;
};

static struct HostStat *HostStatList[ 50 * sizeof(struct HostStat *) ];

/*  d hostname dd-mm-yy hh:mm:ss > dd-mm-yy hh:mm:ss hh:mm:ss BR_CPS NE_CPS ppp%
    | p option bytes_i  bytes_o    fbytes_i fbytes_o fcnt_i fcnt_o

    < horga    23-10-91 07:38:06 > 23-10-91 07:51:04 (00:12:58)  1401   1169  83%
    | g 3   64  1000935    89605 #   909846        0 #   26    0
*/

static struct CurInput {
	char direction[3], hostname[10], startday[10], starttime[10], nothing1[3],
		 endday[10], endtime[10], xfertime[12], brcps[8], necps[8], ne2br[6];
	char nothing2[3], protocol[3], windows[3], packbytes[6],
		 bytesi[10], byteso[10], nothing3[3], fbytesi[10], fbyteso[10],
		 nothing4[3], fcnti[10], fcnto[10];
} CurInputStruct;

void calchoststat(void)
{
	int i;
	struct HostStat *HostStat;
	struct CurInput *CurInput = &CurInputStruct;

	i = 0;
	while (HostStatList[i] != NULL) {
		if (strcmp(CurInput->hostname, HostStatList[i]->Hostname) == 0) {
			break;
		}
		++i;
	}
	if (HostStatList[i] == NULL) {
		if (!inlsys(LSYSFILE, CurInput->hostname))
			return;
		if ((HostStat = (struct HostStat *)malloc(sizeof(struct HostStat))) == NULL)
			return;
		HostStatList[i] = HostStat;
		HostStatList[i+1] = NULL;
		memset(HostStat, NUL, sizeof(struct HostStat));
		strcpy(HostStat->Hostname, CurInput->hostname);
	}
	HostStat = HostStatList[i];

	HostStat->BytesRecv += atoi(CurInput->fbytesi);
	HostStat->BytesSent += atoi(CurInput->fbyteso);
	HostStat->Bytes = HostStat->BytesRecv + HostStat->BytesSent;

	if (atoi(CurInput->necps) != 0) {
		HostStat->SecondRecv += (int) (atoi(CurInput->fbytesi) / atoi(CurInput->necps));
		HostStat->SecondSent += (int) (atoi(CurInput->fbyteso) / atoi(CurInput->necps));
	}

	if (HostStat->SecondRecv != 0)
		HostStat->AvCpsRecv = (HostStat->BytesRecv / HostStat->SecondRecv);
	if (HostStat->SecondSent != 0)
		HostStat->AvCpsSent = (HostStat->BytesSent / HostStat->SecondSent);

	HostStat->FilesRecv += atoi(CurInput->fcnti);
	HostStat->FilesSent += atoi(CurInput->fcnto);

	return;
}


void calctotalstat(void)
{
	int i;
	struct TotalStat *TotalStat = &TotalStatStruct;

	memset(TotalStat, NUL, sizeof(struct TotalStat));
	i = 0;
	while (HostStatList[i] != NULL) {
		TotalStat->FilesSent  += HostStatList[i]->FilesSent;
		TotalStat->FilesRecv  += HostStatList[i]->FilesRecv;
		TotalStat->Files       = TotalStat->FilesSent + TotalStat->FilesRecv;
		TotalStat->SecondSent += HostStatList[i]->SecondSent;
		TotalStat->SecondRecv += HostStatList[i]->SecondRecv;
		TotalStat->Second      = TotalStat->SecondSent + TotalStat->SecondRecv;
		TotalStat->BytesSent  += HostStatList[i]->BytesSent;
		TotalStat->BytesRecv  += HostStatList[i]->BytesRecv;
		TotalStat->Bytes       = TotalStat->BytesSent + TotalStat->BytesRecv;
		++i;
	}
	TotalStat->Sites = i;

	return;
}


void printhoststat(void)
{
	int i = 0;
	char buf[100];
	struct HostStat *HostStat;

	printf( "\n"
			"Remote   -----------K-Bytes----------- ----Hours---- --Avg CPS-- --Files--\n"
			" Host         Recv      Sent     Total   Recv   Sent  Recv  Sent Recv Sent\n"
			"------   --------- --------- --------- ------ ------ ----- ----- ---- ----\n");
	while (HostStatList[i] != NULL) {
		HostStat = HostStatList[i];
		strncpy(buf, HostStat->Hostname, 9);
		buf[9]='\0';
		printf("%-9s", buf);
		sprintf(buf, "%5.1f", (double)HostStat->BytesRecv / 1000);
		printf("%9s ", buf);
		sprintf(buf, "%5.1f", (double)HostStat->BytesSent / 1000);
		printf("%9s ", buf);
		sprintf(buf, "%5.1f", (double)HostStat->Bytes / 1000);
		printf("%9s ", buf);
		sprintf(buf, "%5.1f", (double)HostStat->SecondRecv / 3600);
		printf("%6s ", buf);
		sprintf(buf, "%5.1f", (double)HostStat->SecondSent / 3600);
		printf("%6s ", buf);
		sprintf(buf, "%5.0f", HostStat->AvCpsRecv);
		printf("%5s ", buf);
		sprintf(buf, "%5.0f", HostStat->AvCpsSent);
		printf("%5s ", buf);
		printf("%4d ", HostStat->FilesRecv);
		printf("%4d\n", HostStat->FilesSent);
		++i;
	}

	return;
}

void printtotalstat(void)
{
	struct TotalStat *TotalStat = &TotalStatStruct;
	char buf[100];

	printf(	"\n"
			"                   -------------SUMMARY-------------\n"
			"                   Total active uucp sites:" );
	sprintf(buf,"%d", TotalStat->Sites);
	printf("%7s\n",buf);
	printf(	"                   Total files recv:  ");
	sprintf(buf,"%ld", TotalStat->FilesRecv);
	printf("%12s\n",buf);
	printf(	"                   Total files sent:  ");
	sprintf(buf,"%ld", TotalStat->FilesSent);
	printf("%12s\n",buf);
	printf(	"                   Total files:       ");
	sprintf(buf,"%ld", TotalStat->Files);
	printf("%12s\n",buf);
	printf(	"                   Total hours recv:    ");
	sprintf(buf,"%.1f", (double)TotalStat->SecondRecv / 3600);
	printf("%12s\n",buf);
	printf(	"                   Total hours sent:    ");
	sprintf(buf,"%.1f", (double)TotalStat->SecondSent / 3600);
	printf("%12s\n",buf);
	printf(	"                   Total hours:         ");
	sprintf(buf,"%.1f", (double)TotalStat->Second / 3600);
	printf("%12s\n",buf);
	printf(	"                   Total K-bytes recv:  ");
	sprintf(buf,"%.0f", (double)TotalStat->BytesRecv / 1000);
	printf("%10s\n",buf);
	printf(	"                   Total K-bytes sent:  ");
	sprintf(buf,"%.0f", (double)TotalStat->BytesSent / 1000);
	printf("%10s\n",buf);
	printf(	"                   Total K-bytes:       ");
	sprintf(buf,"%.0f", (double)TotalStat->Bytes / 1000);
	printf("%10s\n\n",buf);

	return;
}

int main(int argc, char *argv[])
{
	FILE *fpStat = NULL;
	char *cpStat = STATFILE;
	char *cpStatbuf = NULL;
	int wStat;
	LB *lbStat = NULL;
	int rc;
	char caLn[128];
	int	wLastLn = LASTLN_UNRECOGNICED;
	char *cp;
	struct CurInput *CurInput = &CurInputStruct;

	if ((fpStat = fopen(cpStat, "r")) == NULL)
		CU(DOSRC_FAIL);
	if (fseek(fpStat, 0L, SEEK_END) == -1L)
		CU(DOSRC_FAIL);
	if ((wStat = ftell(fpStat)) == -1L)
		CU(DOSRC_FAIL);
	if (fseek(fpStat, 0L, SEEK_SET) == -1L)
		CU(DOSRC_FAIL);
	if ((cpStatbuf = (char *)malloc(wStat)) == NULL)
		CU(DOSRC_FAIL);
	if ((fread(cpStatbuf, wStat, 1, fpStat) != 1) && ferror(fpStat))
		CU(DOSRC_FAIL);
	if ((lbStat = lbopen(cpStatbuf, cpStatbuf + wStat - 1)) == NULL)
		CU(DOSRC_FAIL);
	if (lbseek(lbStat, 0, LBSEEK_SET) == NULL)
		CU(DOSRC_FAIL);

	HostStatList[0] = NULL;

	do {
		memcpy(caLn, lbStat->lb_cpLnCur, lbStat->lb_wLnCur);
		*(caLn + lbStat->lb_wLnCur) = NUL;

		if (*(lbStat->lb_cpLnCur) == '#')
			continue;

		if (wLastLn == LASTLN_UNRECOGNICED
			 && (	*(lbStat->lb_cpLnCur) == '<'
				||	*(lbStat->lb_cpLnCur) == '>'
				||	*(lbStat->lb_cpLnCur) == '=' ) ) {

			cp = stpblk(caLn);
			cp = stpblk(stptok(cp, CurInput->direction, sizeof(CurInput->direction), " \t"));
			cp = stpblk(stptok(cp, CurInput->hostname , sizeof(CurInput->hostname) , " \t"));
			cp = stpblk(stptok(cp, CurInput->startday , sizeof(CurInput->startday) , " \t"));
			cp = stpblk(stptok(cp, CurInput->starttime, sizeof(CurInput->starttime), " \t"));
			cp = stpblk(stptok(cp, CurInput->nothing1 , sizeof(CurInput->nothing1) , " \t"));
			cp = stpblk(stptok(cp, CurInput->endday   , sizeof(CurInput->endday)   , " \t"));
			cp = stpblk(stptok(cp, CurInput->endtime  , sizeof(CurInput->endtime)  , " \t"));
			cp = stpblk(stptok(cp, CurInput->xfertime , sizeof(CurInput->xfertime) , " \t"));
			cp = stpblk(stptok(cp, CurInput->brcps    , sizeof(CurInput->brcps)    , " \t"));
			cp = stpblk(stptok(cp, CurInput->necps    , sizeof(CurInput->necps)    , " \t"));
			cp = stpblk(stptok(cp, CurInput->ne2br    , sizeof(CurInput->ne2br)    , " \t"));

			wLastLn = LASTLN_FIRST;
			continue;
		}

		if (wLastLn == LASTLN_FIRST && *(lbStat->lb_cpLnCur) == '|') {

			cp = stpblk(caLn);
			cp = stpblk(stptok(cp, CurInput->nothing2 , sizeof(CurInput->nothing2) , " \t"));
			cp = stpblk(stptok(cp, CurInput->protocol , sizeof(CurInput->protocol) , " \t"));
			cp = stpblk(stptok(cp, CurInput->windows  , sizeof(CurInput->windows)  , " \t"));
			cp = stpblk(stptok(cp, CurInput->packbytes, sizeof(CurInput->packbytes), " \t"));
			cp = stpblk(stptok(cp, CurInput->bytesi   , sizeof(CurInput->bytesi)   , " \t"));
			cp = stpblk(stptok(cp, CurInput->byteso   , sizeof(CurInput->byteso)   , " \t"));
			cp = stpblk(stptok(cp, CurInput->nothing3 , sizeof(CurInput->nothing2) , " \t"));
			cp = stpblk(stptok(cp, CurInput->fbytesi  , sizeof(CurInput->fbytesi)  , " \t"));
			cp = stpblk(stptok(cp, CurInput->fbyteso  , sizeof(CurInput->fbyteso)  , " \t"));
			cp = stpblk(stptok(cp, CurInput->nothing4 , sizeof(CurInput->nothing2) , " \t"));
			cp = stpblk(stptok(cp, CurInput->fcnti    , sizeof(CurInput->fcnti)    , " \t"));
			cp = stpblk(stptok(cp, CurInput->fcnto    , sizeof(CurInput->fcnto)    , " \t"));

			(void) calchoststat();
			wLastLn = LASTLN_UNRECOGNICED;
			continue;
		}

		printf("skipping unrecogniced line\n");

	} while(lbseek(lbStat, 1, LBSEEK_CUR));

	(void) calctotalstat();

	(void) printhoststat();
	(void) printtotalstat();

	rc = DOSRC_SUCCESS;

CUS:
	if (lbStat)
		lbfree(lbStat);
	if (cpStat)
		free(cpStatbuf);
	if (fpStat)
		fclose(fpStat);
	return rc;
}

