New file rotormodule.c (by Lance Ellinghouse).
diff --git a/Modules/rotormodule.c b/Modules/rotormodule.c
new file mode 100644
index 0000000..2950a93
--- /dev/null
+++ b/Modules/rotormodule.c
@@ -0,0 +1,735 @@
+/***********************************************************
+Copyright 1992 by Lance Ellinghouse (lance@markv.com).
+
+Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
+Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* This creates an encryption and decryption engine I am calling
+   a rotor due to the original design was a harware rotor with
+   contacts used in Germany during WWII.
+
+Rotor Module:
+
+-  rotor.newrotor('key') -> rotorobject  (default of 6 rotors)
+-  rotor.newrotor('key', num_rotors) -> rotorobject
+
+Rotor Objects:
+
+-  ro.encrypt('string') -> encrypted string
+-  ro.decrypt('encrypted string') -> unencrypted string
+
+NOTE: you MUST use the SAME key in rotor.newrotor()
+      if you wish to decrypt an encrypted string.
+      Also, the encrypted string is NOT 0-127 ASCII. 
+      It is considered BINARY data.
+
+*/
+
+/* Rotor objects */
+
+#include "allobjects.h"
+#include "modsupport.h"
+#include <stdio.h>
+#include <math.h>
+
+typedef struct {
+	OB_HEAD
+	int seed[3];
+    	short key[5];
+	int  size;
+	int  size_mask;
+    	int  rotors;
+	unsigned char *e_rotor; /* [num_rotors][size] */
+	unsigned char *d_rotor; /* [num_rotors][size] */
+	unsigned char *positions; /* [num_rotors] */
+	unsigned char *advances; /* [num_rotors] */
+} rotorobject;
+
+extern typeobject Rotortype;	/* Really static, forward */
+
+#define is_rotorobject(v)		((v)->ob_type == &Rotortype)
+
+/*
+	This defines the necessary routines to manage rotor objects
+*/
+
+static void set_seed( r )
+rotorobject *r;
+{
+	r->seed[0] = r->key[0];
+	r->seed[1] = r->key[1];
+	r->seed[2] = r->key[2];
+}
+	
+/* Return the next random number in the range [0.0 .. 1.0) */
+static float r_random( r )
+rotorobject *r;
+{
+	int x, y, z;
+	float val, term;
+
+	x = r->seed[0];
+	y = r->seed[1];
+	z = r->seed[2];
+
+	x = 171 * (x % 177) - 2 * (x/177);
+	y = 172 * (y % 176) - 35 * (y/176);
+	z = 170 * (z % 178) - 63 * (z/178);
+	
+	if (x < 0) x = x + 30269;
+	if (y < 0) y = y + 30307;
+	if (z < 0) z = z + 30323;
+	
+	r->seed[0] = x;
+	r->seed[1] = y;
+	r->seed[2] = z;
+
+	term = (float)(
+			(((float)x)/(float)30269.0) + 
+			(((float)y)/(float)30307.0) + 
+			(((float)z)/(float)30323.0)
+			);
+	val = term - (float)floor((double)term);
+
+	if (val >= 1.0) val = 0.0;
+
+	return val;
+}
+
+static short r_rand(r,s)
+rotorobject *r;
+short s;
+{
+	short tmp = (short)((short)(r_random(r) * (float)s) % s);
+	return tmp;
+}
+
+static void set_key(r, key)
+rotorobject *r;
+char *key;
+{
+	int k1=995, k2=576, k3=767, k4=671, k5=463;
+	int i;
+	int len=strlen(key);
+	for (i=0;i<len;i++) {
+		k1 = (((k1<<3 | k1<<-13) + key[i]) & 65535);
+		k2 = (((k2<<3 | k2<<-13) ^ key[i]) & 65535);
+		k3 = (((k3<<3 | k3<<-13) - key[i]) & 65535);
+		k4 = ((key[i] - (k4<<3 | k4<<-13)) & 65535);
+		k5 = (((k5<<3 | k5<<-13) ^ ~key[i]) & 65535);
+	}
+	r->key[0] = (short)k1;
+	r->key[1] = (short)(k2|1);
+	r->key[2] = (short)k3;
+	r->key[3] = (short)k4;
+	r->key[4] = (short)k5;
+
+	set_seed(r);
+}
+
+/* These define the interface to a rotor object */
+static rotorobject *
+newrotorobject(num_rotors, key)
+	int num_rotors;
+	char *key;
+{
+	rotorobject *xp;
+	xp = NEWOBJ(rotorobject, &Rotortype);
+	if (xp == NULL)
+		return NULL;
+	set_key(xp,key);
+
+	xp->size = 256;
+	xp->size_mask = xp->size - 1;
+	xp->size_mask = 0;
+	xp->rotors = num_rotors;
+
+	xp->e_rotor   = (unsigned char *)malloc((num_rotors * (xp->size * sizeof(char))));
+	if (xp->e_rotor == (unsigned char *)NULL) {
+		err_nomem();
+		DEL(xp);
+		xp = (object *)NULL;
+		goto done;
+	}
+	xp->d_rotor   = (unsigned char *)malloc((num_rotors * (xp->size * sizeof(char))));
+	if (xp->d_rotor == (unsigned char *)NULL) {
+		err_nomem();
+		free(xp->e_rotor);
+		DEL(xp);
+		xp = (object *)NULL;
+		goto done;
+	}
+	xp->positions = (unsigned char *)malloc(num_rotors * sizeof(char));
+	if (xp->positions == (unsigned char *)NULL) {
+		err_nomem();
+		free(xp->e_rotor);
+		free(xp->d_rotor);
+		DEL(xp);
+		xp = (object *)NULL;
+		goto done;
+	}
+	xp->advances  = (unsigned char *)malloc(num_rotors * sizeof(char));
+	if (xp->advances == (unsigned char *)NULL) {
+		err_nomem();
+		free(xp->e_rotor);
+		free(xp->d_rotor);
+		free(xp->positions);
+		DEL(xp);
+		xp = (object *)NULL;
+		goto done;
+	}
+done:
+	return xp;
+}
+
+/* These routines impliment the rotor itself */
+
+/*  Here is a fairly sofisticated {en,de}cryption system.  It is bassed
+on the idea of a "rotor" machine.  A bunch of rotors, each with a
+different permutation of the alphabet, rotate around a different
+amount after encrypting one character.  The current state of the
+rotors is used to encrypt one character.
+
+  The code is smart enought to tell if your alphabet has a number of
+characters equal to a power of two.  If it does, it uses logical
+operations, if not it uses div and mod (both require a division).
+
+  You will need to make two changes to the code 1) convert to c, and
+customize for an alphabet of 255 chars 2) add a filter at the
+begining, and end, which subtracts one on the way in, and adds one on
+the way out.
+
+  You might wish to do some timing studies.  Another viable
+alternative is to "byte stuff" the encrypted data of a normal (perhaps
+this one) encryption routine.
+
+j'
+*/
+
+/*(defun RTR-make-id-rotor (rotor)
+  "Set ROTOR to the identity permutation"
+  (let ((j 0))
+    (while (< j RTR-size)
+      (aset rotor j j)
+      (setq j (+ 1 j)))
+    rotor))*/
+static void RTR_make_id_rotor(r, rtr)
+	rotorobject *r;
+	unsigned char *rtr;
+{
+	register int j;
+	register int size = r->size;
+	for (j=0;j<size;j++) {
+		rtr[j] = (unsigned char)j;
+	}
+}
+
+
+/*(defvar RTR-e-rotors 
+  (let ((rv (make-vector RTR-number-of-rotors 0))
+	(i 0)
+	tr)
+    (while (< i RTR-number-of-rotors)
+      (setq tr (make-vector RTR-size 0))
+      (RTR-make-id-rotor tr)
+      (aset rv i tr)
+      (setq i (+ 1 i)))
+    rv)
+  "The current set of encryption rotors")*/
+static void RTR_e_rotors(r)
+	rotorobject *r;
+{
+	int i;
+	for (i=0;i<r->rotors;i++) {
+		RTR_make_id_rotor(r,&(r->e_rotor[(i*r->size)]));
+	}
+}
+
+/*(defvar RTR-d-rotors 
+  (let ((rv (make-vector RTR-number-of-rotors 0))
+	(i 0)
+	tr)
+    (while (< i RTR-number-of-rotors)
+      (setq tr (make-vector RTR-size 0))
+      (setq j 0)
+      (while (< j RTR-size)
+	(aset tr j j)
+	(setq j (+ 1 j)))
+      (aset rv i tr)
+      (setq i (+ 1 i)))
+    rv)
+  "The current set of decryption rotors")*/
+static void RTR_d_rotors(r)
+	rotorobject *r;
+{
+	register int i, j;
+	for (i=0;i<r->rotors;i++) {
+		for (j=0;j<r->size;j++) {
+			r->d_rotor[((i*r->size)+j)] = (unsigned char)j;
+		}
+	}
+}
+
+/*(defvar RTR-positions (make-vector RTR-number-of-rotors 1)
+  "The positions of the rotors at this time")*/
+static void RTR_positions(r)
+	rotorobject *r;
+{
+	int i;
+	for (i=0;i<r->rotors;i++) {
+		r->positions[i] = 1;
+	}
+}
+
+/*(defvar RTR-advances (make-vector RTR-number-of-rotors 1)
+  "The number of positions to advance the rotors at a time")*/
+static void RTR_advances(r) 
+	rotorobject *r;
+{
+	int i;
+	for (i=0;i<r->rotors;i++) {
+		r->advances[i] = 1;
+	}
+}
+
+/*(defun RTR-permute-rotor (e d)
+  "Permute the E rotor, and make the D rotor its inverse"
+  ;; see Knuth for explaination of algorythm.
+  (RTR-make-id-rotor e)
+  (let ((i RTR-size)
+	q j)
+    (while (<= 2 i)
+      (setq q (fair16 i))		; a little tricky, decrement here
+      (setq i (- i 1))			; since we have origin 0 array's
+      (setq j (aref e q))
+      (aset e q (aref e i))
+      (aset e i j)
+      (aset d j i))
+    (aset e 0 (aref e 0))		; don't forget e[0] and d[0]
+    (aset d (aref e 0) 0)))*/
+static void RTR_permute_rotor(r, e, d)
+	rotorobject *r;
+	unsigned char *e;
+	unsigned char *d;
+{
+	short i = r->size;
+	short q;
+	unsigned char j;
+	RTR_make_id_rotor(r,e);
+	while (2 <= i) {
+		q = r_rand(r,i);
+		i--;
+		j = e[q];
+		e[q] = (unsigned char)e[i];
+		e[i] = (unsigned char)j;
+		d[j] = (unsigned char)i;
+	}
+	e[0] = (unsigned char)e[0];
+	d[(e[0])] = (unsigned char)0;
+}
+
+/*(defun RTR-init (key)
+  "Given KEY (a list of 5 16 bit numbers), initialize the rotor machine.
+Set the advancement, position, and permutation of the rotors"
+  (R16-set-state key)
+  (let (i)
+    (setq i 0)
+    (while (< i RTR-number-of-rotors)
+      (aset RTR-positions i (fair16 RTR-size))
+      (aset RTR-advances i (+ 1 (* 2 (fair16 (/ RTR-size 2)))))
+      (message "Initializing rotor %d..." i)
+      (RTR-permute-rotor (aref RTR-e-rotors i) (aref RTR-d-rotors i))
+      (setq i (+ 1 i)))))*/
+static void RTR_init(r)
+	rotorobject *r;
+{
+	int i;
+	set_seed(r);
+	RTR_positions(r);
+	RTR_advances(r);
+	RTR_e_rotors(r);
+	RTR_d_rotors(r);
+	for(i=0;i<r->rotors;i++) {
+		r->positions[i] = r_rand(r,r->size);
+		r->advances[i] = (1+(2*(r_rand(r,r->size/2))));
+		RTR_permute_rotor(r,&(r->e_rotor[(i*r->size)]),&(r->d_rotor[(i*r->size)]));
+	}
+}
+
+/*(defun RTR-advance ()
+  "Change the RTR-positions vector, using the RTR-advances vector"
+  (let ((i 0)
+	(temp 0))
+    (if RTR-size-mask
+	(while (< i RTR-number-of-rotors)
+	  (setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
+	  (aset RTR-positions i (logand temp RTR-size-mask))
+	  (if (and (>= temp RTR-size)
+		   (< i (- RTR-number-of-rotors 1))) 
+	      (aset RTR-positions (+ i 1)
+		    (+ 1 (aref RTR-positions (+ i 1)))))
+	  (setq i (+ i 1)))
+      (while (< i RTR-number-of-rotors)
+	(setq temp (+ (aref RTR-positions i) (aref RTR-advances i)))
+	(aset RTR-positions i (% temp RTR-size))
+	(if (and (>= temp RTR-size)
+		 (< i (- RTR-number-of-rotors 1))) 
+	    (aset RTR-positions (+ i 1)
+		  (+ 1 (aref RTR-positions (+ i 1)))))
+	(setq i (+ i 1))))))*/
+static void RTR_advance(r)
+	rotorobject *r;
+{
+	register int i=0, temp=0;
+	if (r->size_mask) {
+		while (i<r->rotors) {
+			temp = r->positions[i] + r->advances[i];
+			r->positions[i] = temp & r->size_mask;
+			if ((temp >= r->size) && (i < (r->rotors - 1))) {
+				r->positions[(i+1)] = 1 + r->positions[(i+1)];
+			}
+			i++;
+		}
+	} else {
+		while (i<r->rotors) {
+			temp = r->positions[i] + r->advances[i];
+			r->positions[i] = temp%r->size;
+			if ((temp >= r->size) && (i < (r->rotors - 1))) {
+				r->positions[(i+1)] = 1 + r->positions[(i+1)];
+			}
+			i++;
+		}
+	}
+}
+
+/*(defun RTR-e-char (p)
+  "Encrypt the character P with the current rotor machine"
+  (let ((i 0))
+    (if RTR-size-mask
+	(while (< i RTR-number-of-rotors)
+	  (setq p (aref (aref RTR-e-rotors i)
+			(logand (logxor (aref RTR-positions i)
+					p)
+				RTR-size-mask)))
+	  (setq i (+ 1 i)))
+      (while (< i RTR-number-of-rotors)
+	  (setq p (aref (aref RTR-e-rotors i)
+			(% (logxor (aref RTR-positions i)
+				   p)
+			   RTR-size)))
+	(setq i (+ 1 i))))
+    (RTR-advance)
+    p))*/
+static unsigned char RTR_e_char(r, p)
+	rotorobject *r;
+	unsigned char p;
+{
+	register int i=0;
+	register unsigned char tp=p;
+	if (r->size_mask) {
+		while (i < r->rotors) {
+			tp = r->e_rotor[(i*r->size)+(((r->positions[i] ^ tp) & r->size_mask))];
+			i++;
+		}
+	} else {
+		while (i < r->rotors) {
+			tp = r->e_rotor[(i*r->size)+(((r->positions[i] ^ tp) % r->size))];
+			i++;
+		}
+	}
+	RTR_advance(r);
+	return ((unsigned char)tp);
+}
+
+/*(defun RTR-d-char (c)
+  "Decrypt the character C with the current rotor machine"
+  (let ((i (- RTR-number-of-rotors 1)))
+    (if RTR-size-mask
+	(while (<= 0 i)
+	  (setq c (logand (logxor (aref RTR-positions i)
+				  (aref (aref RTR-d-rotors i)
+					c))
+			  RTR-size-mask))
+	  (setq i (- i 1)))
+	(while (<= 0 i)
+	  (setq c (% (logxor (aref RTR-positions i)
+			     (aref (aref RTR-d-rotors i)
+				   c))
+		     RTR-size))
+	  (setq i (- i 1))))
+    (RTR-advance)
+    c))*/
+static unsigned char RTR_d_char(r, c)
+	rotorobject *r;
+	unsigned char c;
+{
+	register int i=r->rotors - 1;
+	register unsigned char tc=c;
+	if (r->size_mask) {
+		while (0 <= i) {
+			tc = (r->positions[i] ^ r->d_rotor[(i*r->size)+tc]) & r->size_mask;
+			i--;
+		}
+	} else {
+		while (0 <= i) {
+			tc = (r->positions[i] ^ r->d_rotor[(i*r->size)+tc]) % r->size;
+			i--;
+		}
+	}
+	RTR_advance(r);
+	return(tc);
+}
+
+/*(defun RTR-e-region (beg end key)
+  "Perform a rotor encryption of the region from BEG to END by KEY"
+  (save-excursion
+    (let ((tenth (/ (- end beg) 10)))
+      (RTR-init key)
+      (goto-char beg)
+      ;; ### make it stop evry 10% or so to tell us
+      (while (< (point) end)
+	(let ((fc (following-char)))
+	  (insert-char (RTR-e-char fc) 1)
+	  (delete-char 1))))))*/
+static void RTR_e_region(r, beg, len)
+	rotorobject *r;
+	unsigned char *beg;
+	int len;
+{
+	register int i;
+	RTR_init(r);
+	for (i=0;i<len;i++) {
+		beg[i]=RTR_e_char(r,beg[i]);
+	}
+}
+
+/*(defun RTR-d-region (beg end key)
+  "Perform a rotor decryption of the region from BEG to END by KEY"
+  (save-excursion
+    (progn
+      (RTR-init key)
+      (goto-char beg)
+      (while (< (point) end)
+	(let ((fc (following-char)))
+	  (insert-char (RTR-d-char fc) 1)
+	  (delete-char 1))))))*/
+void static RTR_d_region(r, beg, len)
+	rotorobject *r;
+	unsigned char *beg;
+	int len;
+{
+	register int i;
+	RTR_init(r);
+	for (i=0;i<len;i++) {
+		beg[i]=RTR_d_char(r,beg[i]);
+	}
+}
+
+
+/*(defun RTR-key-string-to-ints (key)
+  "Convert a string into a list of 4 numbers"
+  (let ((k1 995)
+	(k2 576)
+	(k3 767)
+	(k4 671)
+	(k5 463)
+	(i 0))
+    (while (< i (length key))
+      (setq k1 (logand (+      (logior (lsh k1 3) (lsh k1 -13)) (aref key i)) 65535))
+      (setq k2 (logand (logxor (logior (lsh k2 3) (lsh k2 -13)) (aref key i)) 65535))
+      (setq k3 (logand (-      (logior (lsh k3 3) (lsh k3 -13)) (aref key i)) 65535))
+      (setq k4 (logand (-      (aref key i) (logior (lsh k4 3) (lsh k4 -13))) 65535))
+      (setq k5 (logand (logxor (logior (lsh k5 3) (lsh k5 -13)) (lognot (aref key i))) 65535))
+      (setq i (+ i 1)))
+    (list k1 (logior 1 k2) k3 k4 k5)))*/
+/* This is done in set_key() above */
+
+/*(defun encrypt-region (beg end key)
+  "Interactivly encrypt the region"
+  (interactive "r\nsKey:")
+  (RTR-e-region beg end (RTR-key-string-to-ints key)))*/
+static void encrypt_region(r, region, len)
+	rotorobject *r;
+	unsigned char *region;
+	int len;
+{
+	RTR_e_region(r,region,len);
+}
+
+/*(defun decrypt-region (beg end key)
+  "Interactivly decrypt the region"
+  (interactive "r\nsKey:")
+  (RTR-d-region beg end (RTR-key-string-to-ints key)))*/
+static void decrypt_region(r, region, len)
+	rotorobject *r;
+	unsigned char *region;
+	int len;
+{
+	RTR_d_region(r,region,len);
+}
+
+/* Rotor methods */
+
+static void
+rotor_dealloc(xp)
+	rotorobject *xp;
+{
+	free(xp->e_rotor);
+	free(xp->d_rotor);
+	free(xp->positions);
+	free(xp->advances);
+	DEL(xp);
+}
+
+static object *
+rotor_encrypt(self, args)
+	rotorobject *self;
+	object *args;
+{
+	char *string = (char *)NULL;
+	int len = 0;
+	object *rtn = (object *)NULL;
+	char *tmp;
+
+	if (!getargs(args,"s#",&string, &len))
+		return NULL;
+	if (!(tmp = (char *)malloc(len+5))) {
+		err_nomem();
+		return NULL;
+	}
+	memset(tmp,'\0',len+1);
+	memcpy(tmp,string,len);
+	RTR_e_region(self,tmp,len);
+	rtn = newsizedstringobject(tmp,len);
+	free(tmp);
+	return(rtn);
+}
+
+static object *
+rotor_decrypt(self, args)
+	rotorobject *self;
+	object *args;
+{
+	char *string = (char *)NULL;
+	int len = 0;
+	object *rtn = (object *)NULL;
+	char *tmp;
+
+	if (!getargs(args,"s#",&string, &len))
+		return NULL;
+	if (!(tmp = (char *)malloc(len+5))) {
+		err_nomem();
+		return NULL;
+	}
+	memset(tmp,'\0',len+1);
+	memcpy(tmp,string,len);
+	RTR_d_region(self,tmp,len);
+	rtn = newsizedstringobject(tmp,len);
+	free(tmp);
+	return(rtn);
+}
+
+static object *
+rotor_setkey(self, args)
+	rotorobject *self;
+	object *args;
+{
+	char *key;
+	char *string;
+
+	if (getargs(args,"s",&string))
+		set_key(self,string);
+	INCREF(None);
+	return None;
+}
+
+static struct methodlist rotor_methods[] = {
+	{"encrypt",	rotor_encrypt},
+	{"decrypt",	rotor_decrypt},
+	{"setkey",	rotor_setkey},
+	{NULL,		NULL}		/* sentinel */
+};
+
+
+/* Return a rotor object's named attribute. */
+static object *
+rotor_getattr(s, name)
+	rotorobject *s;
+	char *name;
+{
+	return findmethod(rotor_methods, (object *) s, name);
+}
+
+static typeobject Rotortype = {
+	OB_HEAD_INIT(&Typetype)
+	0,			/*ob_size*/
+	"rotor",			/*tp_name*/
+	sizeof(rotorobject),	/*tp_size*/
+	0,			/*tp_itemsize*/
+	/* methods */
+	rotor_dealloc,	/*tp_dealloc*/
+	0,		/*tp_print*/
+	rotor_getattr,		/*tp_getattr*/
+	0,		/*tp_setattr*/
+	0,		/*tp_compare*/
+	0,		/*tp_repr*/
+};
+
+
+object *rotor_rotor(self, args)
+object *args;
+{
+	char *string;
+	rotorobject *r;
+	int len;
+	int num_rotors;
+
+	if (getargs(args,"s#", &string, &len)) {
+		num_rotors = 6;
+	} else {
+		err_clear();
+		if (!getargs(args,"(s#i)", &string, &len, &num_rotors))
+			return NULL;
+	}
+	r = newrotorobject(num_rotors, string);
+	return (object *)r;
+}
+
+static struct methodlist rotor_rotor_methods[] = {
+	{"newrotor",		rotor_rotor},
+	{NULL,			NULL}		 /* Sentinel */
+};
+
+
+/* Initialize this module.
+   This is called when the first 'import rotor' is done,
+   via a table in config.c, if config.c is compiled with USE_ROTOR
+   defined. */
+
+void
+initrotor()
+{
+	object *m;
+
+	m = initmodule("rotor", rotor_rotor_methods);
+}