/*
 * duplicate crypt.s in a readable language
 */

/*)BUILD
*/

static int wheeldiv[] {
	32,18,10,6,4
};
static int shift[] {
	0000001,0000002,0000004,0000010,0000020,0000040,
	0000100,0000200,0000400,0001000,0002000,0004000,
	0010000,0020000,0040000,0100000,0000001,0000002
};
static char word[32];

char *
crypt(ukey)
char *ukey;      	/* pointer to user's string (max 63 chars)	*/
{      
	char *s, *k;
	int *w, *d, *c, r, t;

	char key[128];
	int wheelcode[128],cagecode[128],cage[128],wheel[128];

	/*
	 * copy the users key into new space and add junk if necessary
	 */
	k = key;  s = ukey;
	*k++ = 004;  *k++ = 034;
	while ((k < &key[64]) && (*k++ = *s++)) ;
	--k; s = key;
	while (k < &key[128])  *k++ = k[-1] ^ *s++;

	/*
	 * establish wheel codes and cage codes
	 */
	w = wheelcode; c = cagecode;  t = 256;
	while (w < &wheelcode[128])
	{       r = 0;  *w = 0;  d = wheeldiv;
		*c = 0;
		while (d < &wheeldiv[5])
		{       r = (r + (t % *d++)) & ~040;
			*w |= shift[r/2];
			if (d < &wheeldiv[3]) 
				*c |= shift[r/2+2];
		}
		w++;  c++;  t -= 2;
	}
	/*
	 * make the internal settings of the machine.
	 * both the lugs on the 128 cage bars and the lugs
	 * on the 16 wheels are set from the expanded key
	 */

	k = key;  c = cage;  w = wheel;
	while (k < &key[128])
	{       t = *k++ & 0177;
		*c++ = cagecode[t];
		*w++ = wheelcode[t];
	}

	/*
	 * now spin the cage against the wheel to produce output
	 */

	k = word;  w = &wheel[64];
	while (k < &word[8]) {
		c = cage;  r = 0;  t = *--w;
		while (c < &cage[128]) {
			if ((*c++ & t))
				r++;
		}
		/*
		 * we now have a piece of output from current wheel
		 * it needs to be folded to remove lingering hopes of
		 * inverting the function
		 */
		r = r % 62 + '0';
		if (r > '9') {
			r += ('A'-'9'-1);
			if (r > 'Z')
				r += ('a'-'Z'-1);
		}
		*k++ = r;
	}

	return(word);
}

main()          /* special purpose routine: test on one password */
{
	register char c, *s;
	char str[20];
	for (;;)
	{       printf("password: ");
		for (s=str; (c=getchar()) != '\n';) *s++ = c;
		*s = 0;
		printf("crypt(%s)=%s\n",str,crypt(str));
	}
}
