[net.bugs.4bsd] Bug /etc/ac

webs@umcp-cs.UUCP (11/03/83)

Bug in  /etc/ac.  The index function for ut_line values is incorrect.
The following cases are not handled correctly:
1.  ttyn	If more than one ttyn are concurrently signed on their index
		value COLLIDES as TSIZE-1.

2.  ttyXX	The ranges calculated for any combination of leading alpha
		(upper or lower case) followed by anything generates collisions

		e.g.  'Ax'  give numbers 170 - 179 for A0 - A9,   
                                         187 - 222 for AA - AZ,
                                         219 - 244 for Aa - Az.

                      'Bx'  give numbers 180 - 189 for B0 - B9,
                                         197 - 232 for BA - BZ,
                                         229 - 254 for Bz - Bz.

                      Collisions occur within the 'Ax' group (AZ & Ad) &
                                 across groups (B7 & AA).


I tested the index function change for two months worth of /usr/adm/wtmp data.
Results:  Revised version allocated an additional  2102.44 hours.
		(old 15098.77 hours, new:  17201.21 hours)

If your system only uses format  ttynn  where single number have leading zero
the current /etc/ac will work just fine. If you use alphas, or ttyn formats
the revision is for you.

There are other approaches to fix /etc/ac.  If anyone inserts a table to 
search for line values or some other method, I'd be interested in seeing your
code, maybe run a comparison?



The following fix will properly allocate index values for any case that uses
digits, non-blank alpha characters.  

CAUTION:  This case does NOT handle non-printable or printable special char-
	  acters, (e.g. * & ^ % $ # @ ! " ? / > < . , etc.)

1.  change TSIZE:  from #define TSIZE nnnn	to:  #define  TSIZE 3900

2.  replace line:
  		i = (ibuf.ut_line[3]-'0')*10 + (ibuf.ut_line[4]-'0');
    with:
		i = ttyindx(ibuf.ut_line[3], ibuf.ut_line[4]);

3.  compile ttyindx.c as supplied below.

	/*----------------------------------------------------------------*/
	/*  FUNCTION:  ttyindx	PURPOSE:  Generate index for ttyXX values */
	/*								  */
	/*  AUTHOR:  Leigh S. Weber	DATE:  October 25, 1983		  */
	/*  INSTITUTION:  Computer Science Department,			  */
	/*		  University of Maryland			  */
	/*		  College Park, MD  20742			  */
	/*								  */
	/*  REASON:  Fix hash function for /etc/ac connect time accounting*/
	/*		program.					  */
	/*----------------------------------------------------------------*/


#include <stdio.h>
#include <ctype.h>

int base, factor, dig, i;

char   c;


ttyindx(a, b)
int  a, b;
{


	/*  generate numeric index from ttyXX values  
	 *  
	 *  cases:  
	 *  1.  Single digit    values:   0 -   9 inclusive
	 *  2.  double digit	values:  10 -  99 inclusive
	 *  3.  Digit, char     values: 100 - 619 inclusive
	 *		0A ==> 100   0B ==> 101  0a ==> 126 0z ==> 151
	 *              1A ==> 152   1B ==> 153  1a ==> 178 1z ==> 203
	 *		....
	 *		9A ==> 568   9B ==> 569  9a ==> 594 9z ==> 619
	 *  4.  Alpha, Digit or Alpha
	 *		Ordering by second char, lowest digit 0, highest z
	 *    A0 ==> 620 A1 ==> 621 A  ==> 630 AA ==> 631 Aa ==> 657 Az ==> 682
	 *    B0 ==> 683 B1 ==> 684 B  ==> 693 BA ==> 694 Ba ==> 720 Bz ==> 745
	 *	....
	 *    Z0 ==>2195 Z1 ==>2196 Z  ==>2205 ZA ==>2206 Za ==>2232 Zz ==>3895
	 *    a0 ==>2258 a1 ==>2259 a  ==>2268 aA ==>2269 aa ==>2295 az ==>2320
	 *	....
	 *    z0 ==>3833 z1 ==>3834 z  ==>3843 zA ==>3844 za ==>3870 zz ==>3895
	 *
	 *  NOTE:  Only digits and non-blank characters are valid symbols
	 *		ALL other combinations will kick out
	 *
	 *  NOTE 2:  Although not natural, Alpha NULL is placed between Alpha 9
	 *		and Alpha 'A'.  Please make a note of it
	 *---------------------------------------------------------------*/

	c = a;

	if (isdigit(c))
	    {	dig = 1;		/* set FIRST is DIGIT	*/
		i= c - '0';}		/* atoi conversion	*/
	else
	    { if (isalpha(c) && !isspace(c))
		   {	base = 620;	/* alpha range group	*/
			factor = 63;	/* range		*/
			dig = 0;	/* first NOT a digit	*/
			i = c- 'A' - (islower(c)?6:0);
					/* account for non alpha */
		   }
		else
		   {	dig = 5;	/* set bad character	*/
			goto BADTTY;
		   }
	    }	/* end else of isdigit(c) */
	
	c = b;  /* 2nd char processing */

	if (c != '\0')  /* not end of string */
	     {   if (isalnum(c) && !isspace(c))
		     { if(dig)		/* first char digit */
			    {	factor = (isalpha(c)? 52 : 10);
				base   = (isalpha(c)? 89 :  0);
			    }
			i = i * factor + base + c - '0'
				+ (isupper(c)? -6: 0)
				+ (islower(c)? -12: 0);
		      }
		  else
		      { dig = 5;
			goto BADTTY;
		      }
	     }	/* end if-then c != '\0'	*/
	else  /* single character */
		 i = (dig? i: i*factor + base +10);


#ifdef DEBUG
		if(dig != 5) printf(" %c%c==>%4d", a,b,i);
#endif DEBUG
		
	return(i);
		
BADTTY:	if(dig ==5){printf("\nbad tty %c%c\t", a, b); dig=0;}

}	/* end of ttyindx , index generating function	*/
-- 
  
Name:    Leigh Weber
UUCP:    {seismo,allegra,brl-bmd}!umcp-cs!webs
CSNET:   webs@umcp-cs
ARPA:    webs.umcp-cs@CSNet-Relay