/*
 *	scan.c	1.0	18-Mar-91 EHK
 *	scan.c	1.01	09-Apr-91 EHK	Grrmmbbll, Ultrix syslog format
 *	scan.c	1.02	03-Jun-91 EHK	mod. algorithm to filter garbage better
 *	scan.c	1.03	10-Jun-91 EHK	memory faults; increase some buffers
 *	scan.c	1.03	03-Jan-92 EHK	fixed a sanity check; added KEY_NEWNEWS
 */

#include "nestor.h"

/*
 *---------------------------------------------------------------------------
 *	ScanLine	- scan input line for statistics
 *
 * The most common format of a syslog entry is:
 *		Apr  9 13:06:47 alchemy nntpd[21812]: hp4nl.nluug.nl connect
 * however Ultrix 4.1 uses another format:
 *		Apr  9 13:06:47 alchemy: 21812 nntpd: hp4nl.nluug.nl connect
 * which is pretty annoying I must say.
 * However, this can be handled generic at the cost of some speed
 * reducement. Oh well...
 *
 * Okay, the algorithm will be
 *	1) skip to ``.... service[pid]: '' or ``.... pid service: ''
 *	2) skip to first field (expected to be a hostname) after the syslog
 *	   overhead
 *	3) read hostname and keyword; skip past both in input buffer
 *	4) lookup the keyword -- if we find it, the info in front of it
 *	   is most likely a hostname. This is how we filter garbage...
 *	5) lookup hostname statistics entry; insert if not present
 *	6) handle the keyword-corresponding information
 *
 * Return value: -1 if failure (not a valid syslog entry); 0 if ok.
 *---------------------------------------------------------------------------
 */
int
ScanLine(line, service_match)
	char	*line,
		*service_match;
{
	register char	*cp;
	register nntp_t	*np;
	register int	key_lookup_result;
	char		hostname[BUFSIZ],
			keyword[BUFSIZ];

	if ( (cp = index(service_match, ':')) == NIL_CHAR )	/* -1-	*/
		return( -1 );

	cp += 2;						/* -2-	*/

	sscanf(cp, "%s %s", hostname, keyword);			/* -3-	*/
	cp += strlen(hostname) + strlen(keyword) + 2;

	if ( (key_lookup_result = FindKey(keyword)) == -1 )	/* -4-	*/
	{
		if ( verbose )
			fprintf(stderr, "Huh?!?!? --> %s", line);
		return( -1 );
	}

	if ( (np = (nntp_t *) LookUp(hostname)) == NIL_NNTP )	/* -5-	*/
		np = (nntp_t *) Insert(hostname);

	switch ( key_lookup_result )				/* -6-	*/
	{
	   case KEY_CONNECT:
		++np->recv_n_connect;
		break;
	   case KEY_IHAVE	:
		if ( sscanf(cp, "%*s%d%*s%d%*s%d", &i1, &i2, &i3) == 3 )
		{
			np->recv_a_acc += i1;
			np->recv_a_rej += i2;
			np->recv_a_fai += i3;
		}
		break;
	   case KEY_TIMES	:
		if ( sscanf(cp, "%*s%f%*s%f%*s%f", &f1, &f2, &f3) == 3 )
		{
			np->recv_u_cpu += f1;
			np->recv_s_cpu += f2;
			np->recv_r_cpu +=
				(f3 >= TWENTYFOUR_HOURS || f3 == 0.0) ? 1 : f3;
		}
		break;
	   case KEY_E_RLH	:
		++np->recv_n_hostfail;
		break;
	   case KEY_E_RNET	:
		++np->recv_n_netfail;
		break;
	   case KEY_GROUP	:	/* ignore, handle at KEY_EXIT	*/
	   	break;
	   case KEY_EXIT	:
	   	if ( sscanf(cp, "%d%*s%d", &i1, &i2) == 2 )
		{
			np->recv_rr_art += i1;
			np->recv_rr_grp += i2;
		}
		break;
	   case KEY_UNRECOG	:	/* what to do with this??	*/
	   	break;
	   case KEY_NEWNEWS	:	/* xfer told/took		*/
		if ( sscanf(cp, "%*s%d%*s%d", &i1, &i2) == 2 )
		{
			++np->xfer_n_connect;
			np->xfer_a_off += i1;
			np->xfer_a_acc += i2;
		}
	   	break;
	   case KEY_POST	:	/* succeeded, rejected, failed	*/
		switch ( *cp )
		{
			case 's'	:
				++np->recv_p_acc;
				break;
			case 'r'	:
				++np->recv_p_rej;
				break;
			case 'f'	:
				++np->recv_p_fai;
				break;
			default		:
				break;
		}
		break;

	   case KEY_STATS	:
		if ( sscanf(cp, "%d%*s%d%*s%d%*s%d", &i1, &i2, &i3, &i4) == 4 )
		{
			++np->xmit_n_connect;
			np->xmit_a_off += i1;
			np->xmit_a_acc += i2;
			np->xmit_a_rej += i3;
			np->xmit_a_fai += i4;
		}
		break;
	   case KEY_XMIT	:
		if ( sscanf(cp, "%*s%f%*s%f%*s%f", &f1, &f2, &f3) == 3 )
		{
			np->xmit_u_cpu += f1;
			np->xmit_s_cpu += f2;
			np->xmit_r_cpu +=
				(f3 >= TWENTYFOUR_HOURS || f3 == 0.0) ? 1 : f3;
		}
		break;
	   case KEY_E_XRH	:
		++np->xmit_n_hostfail;
		break;
	   case KEY_E_XNET	:
		++np->xmit_n_netfail;
		break;
	}

	return( 0 );
}
