[comp.sources.unix] v10i002: Crypt Breaker's Workbench, Part02/11

rs@uunet.UUCP (06/18/87)

Submitted by: Robert W. Baldwin <BALDWIN@XX.LCS.MIT.EDU>
Mod.sources: Volume 10, Issue 2
archive-name: cbw/Part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 11)."
# Contents:  bdriver.c cipher.h edriver.c gblock.c mss-bigram-old.stats
#   perm.c start.c terminal.h test2.txt webster.c windowlib.c
# Wrapped by rs@uunet on Wed Jun 17 18:17:05 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f bdriver.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"bdriver.c\"
else
echo shar: Extracting \"bdriver.c\" \(3896 characters\)
sed "s/^X//" >bdriver.c <<'END_OF_bdriver.c'
X/*
X * Test driver for BIGRAM character guessing stuff.
X */
X
X#include	<stdio.h>
X#include	<math.h>
X#include	"window.h"
X#include	"specs.h"
X#include	"cipher.h"
X
X
X#define NDOBLOCKS	2		/* Number of blocks to do. */
X#define	DEBUG		FALSE
X
Xecinfo	myecinfo;
X
Xchar	plainbuf[BLOCKSIZE+1];
Xfloat	accept_level;
Xfloat	prob_cutoff;
X
Xextern	ec_best(), ec_dplain(), ec_dscipher();
Xextern	ec_dnext(), ec_dsizetab(), ec_dperm(), ec_dpmap();
Xextern	ec_init(), ec_best(), ec_cscore();
Xextern	lp_init(), lp_best_char(), lp_cscore(), lp_accept(), lp_best_pos();
Xextern	lp_dclasses();
X
Xextern	char	mcbuf[];
Xextern	char	*fname;			/* Used by fillcbuf. */
X/* Test routine for equiv class info. */
Xmain(argc, argv)
Xint		argc;
Xchar	*argv[];
X{
X	ecinfo	*eci;
X	FILE	*inp;
X	FILE	*sout, *sin;
X	int		i, blknum;
X	int		maxblock;
X	long	filelength;
X	char	infile[100];
X	char	inplain[100];
X	char	*plain = ".txt";
X	char	*code = ".cipher";
X	char	*p, *q;
X
X	sout = stdout;		/* For use within debugger, dbx. */
X	sin = stdin;
X
X	if (argc != 4)  {
X		printf("Usage: %s input_file_root acceptance_level prob_cutoff\n",
X				argv[0]);
X		exit(0);
X		}
X
X	p = inplain;
X	q = argv[1];
X	while (*p++ = *q++);
X	--p;
X	q = plain;
X	while (*p++ = *q++);
X
X	p = infile;
X	q = argv[1];
X	while (*p++ = *q++);
X	--p;
X	q = code;
X	while (*p++ = *q++);
X
X	if (sscanf(argv[2], "%f", &accept_level) != 1)  {
X		printf("Could not parse the acceptance level from %s.\n", argv[2]);
X		exit(0);
X		}
X
X	if (sscanf(argv[3], "%f", &prob_cutoff) != 1)  {
X		printf("Could not parse the probability cutoff from %s.\n", argv[2]);
X		exit(0);
X		}
X
X	printf("\t\tEquivalence Class Guessing\n\n");
X	printf("Filename = %s.  Acceptance level = %4.2f\n",infile,accept_level);
X
X	printf("Loading statistics ...");
X	printf(" 1");
X	load_1stats_from("mss.stats");
X	printf(" 2");
X	load_2stats_from("mss-bigram.stats");
X	printf(" done.\n");
X
X	eci = &myecinfo;
X
X	if ((inp = fopen(infile, "r")) == NULL) {
X		printf("\nCannot open %s for reading.\n", infile);
X		exit(0);
X		}
X	fseek(inp, 0L, 2);
X	filelength = ftell(inp);
X	fclose(inp);
X
X	maxblock = filelength / BLOCKSIZE;
X	if (maxblock > (NDOBLOCKS-1))  maxblock = (NDOBLOCKS-1);
X
X	for (blknum = 0 ; blknum <= maxblock ; blknum++) {
X		do_lp_block(eci, blknum, infile, inplain);
X		}
X}
X
X
X/* Do a block using the letter pair statistics.
X */
Xdo_lp_block(eci, blknum, cfile, plainfile)
Xreg		ecinfo	*eci;
Xint		blknum;
Xchar	*cfile, *plainfile;
X{
X	int		i;
Xreg	int		c;
X	int		ntried;
X	int		naccepted, nwrong;
Xreg	int		classpos;
X	int		charcount;
X	int		*permp, repeat;
X
X	cipherfile = cfile;
X	fillcbuf(blknum, mcbuf);
X	cipherfile = plainfile;
X	fillcbuf(blknum, plainbuf);
X
X	lp_init(mcbuf, refperm(blknum), eci);
X
Xfor(repeat = 0 ; repeat < 3 ; repeat++)  {
X	naccepted = 0;
X	nwrong = 0;
X	ntried = 0;
X
X	for (ntried = 0 ; ntried < BLOCKSIZE ; ntried++)  {
X		classpos = lp_best_pos(eci, 2);
X		if (classpos == NONE)
X			break;
X		c = lp_best_char(eci, classpos,
X						accept_level - ((repeat == 0) ? 0.0 : 0.0),
X						prob_cutoff);
X		if (c != NONE) {
X			lp_accept(eci, classpos, c);
X			naccepted++;
X#if DEBUG
X			printf("ACCEPTED");
X#endif
X			if (plainbuf[classpos] != c)  {
X				nwrong++;
X#if DEBUG
X				printf(" -- INCORRECT");
X#endif
X				}
X#if DEBUG
X			printf("\n");
X#endif
X			}
X		}
X
X/*	decode(eci->ciphertext, eci->plaintext, eci->perm);
X*/
X
X	for (i = 0 ; i < eci->nclasses ; i++)  {
X		eci->classlist[i].changed = TRUE;
X		}
X
X
X	charcount = 0;
X 	for (i = 0 ; i < BLOCKSIZE ; i++)  {
X		if (eci->plaintext[i] != NONE)  charcount++;
X		}
X
X	printf("\n\nPlaintext for block %d using %d wires", blknum, naccepted);
X	printf(" (%d wrong)", nwrong);
X	printf(" yields %d characters.", charcount);
X	printf("\nThere were %d classes and %d guess tries.",eci->nclasses,ntried);
X	printf("\n\n");
X	ec_dplain(stdout, eci);
X	}
X
X	permp = refperm(blknum);
X	for (i = 0 ; i < BLOCKSIZE ; i++)  {
X		permp[i] = eci->perm[i];
X		}
X}
X
X
Xkey	u_getkey()
X{
X}
X
Xkeyer	topktab[] ={{0, NULL}};
X
X
Xchar	*quitcmd()
X{
X}
END_OF_bdriver.c
if test 3896 -ne `wc -c <bdriver.c`; then
    echo shar: \"bdriver.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cipher.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cipher.h\"
else
echo shar: Extracting \"cipher.h\" \(3531 characters\)
sed "s/^X//" >cipher.h <<'END_OF_cipher.h'
X
X/*
X * Declarations for the information about a block.
X */
X
X
X#define	SZMAX	 100	/* Number of classes in ecinfo table. */
X#define	NCLASSES 256	/* Max number of classes of characters in a block. */
X
X
X/* Macros */
X
X/* Iterate of the positions in a class.
X * class is the index of one of the members of an equivalence class.
X * pos is a loop variable assigned to the positions in a class
X * starting with the value of class.
X * Both eci->next and firstflag must be bound in the calling environment.
X * firstflag is just an integer used as a flag, so it does not need to be
X * initialized.  eci->next must be a table of next pointers for this block.
X */
X#define	for_pos_in_class(pos, class)  \
X		for ((pos=class)&(firstflag=TRUE) ; \
X			 firstflag || pos != class ; \
X			 (firstflag=FALSE)&(pos = eci->next[pos]))
X
X
X/* Return TRUE if given wiring conflicts with the wiring
X * in the given permutation.
X */
X#define	perm_conflict(perm,x,y) \
X		( ! perm_no_conflict(perm,x,y))
X
X#define perm_no_conflict(perm,x,y) \
X		(   (x != y) \
X		 && (   ((perm)[x] == NONE  &&  (perm)[y] == NONE) \
X		     || ((perm)[x] == y     &&  (perm)[y] == x)  ))
X
X
X/* Structure Declarations */
X
X
X/* Used for tables of unique permutation wirings. */
X#define	perment	struct xperment
Xperment {
X		int	x;		/* Sorted so x < y. */
X		int	y;		/* x can be NONE. */
X		};
X
X#define	clinfo	struct	clinfox
Xclinfo	{
X		short	nchars;		/* Number of chars in class. */
X		short	npairs;		/* Cur num of chars next to ones in this class. */
X		short	used;		/* True if class has an accepted value. */
X		short	changed;	/* True if best value might have changed. */
X		short	firstpos;	/* Position of first char of this class. */
X		};
X
X#define	adjinfo	struct	adjinfox
Xadjinfo	{
X		short	left;		/* Index of class to the left (or NONE). */
X		short	right;		/* Index of class to the right (or NONE). */
X		};
X
X
X#define	ecsize	struct ecsizex
Xecsize	{
X		int	size;		/* Size of class. */
X		int	firstpos;	/* Index of first member. */
X		};
X
X
X#define	ecinfo	struct	ecinfox
Xecinfo	{
X		/* Index of next free spot in sizelist. */
X		int	sizelast;
X		
X		/* Minimum size of class to put in sizelist. */
X		int	sizemin;
X		
X		/* Table of all the classes sorted largest first. */
X		ecsize	sizelist[SZMAX+1];
X		
X		/* Original ciphertext. */
X		char	ciphertext[BLOCKSIZE+1];
X		
X		/* Cipher chars shifted by  their index. */
X		int	scipher[BLOCKSIZE+1];
X		
X		/* Next[i] is a circular list of the positions of all the */
X		/* members of the class that contains ith cipher char. */
X		int	next[BLOCKSIZE+1];
X		
X		/* Position of first member of the class influenced by perm[i]. */
X		int	permmap[BLOCKSIZE+1];
X		/* Decipher permutation. A  -1 indicated unknown wiring. */
X		
X		/* This is cumulative. */
X		int	perm[BLOCKSIZE+1];
X		
X		/* Cumulative chars deciphered. */
X		int	plaintext[BLOCKSIZE+1];
X		
X		/* Index in classlist to put net class. */
X		int	nclasses;
X		
X		/* List of classes of characters. */
X		clinfo	classlist[NCLASSES];
X		
X		/* Table mapping positions into their class list index. */
X		short	posclass[BLOCKSIZE+1];
X		};
X
X
X/* The gsinfo structure is used to hold information about both
X * guessed at characters and known characters.  Both are needed to
X * compute scores based on letter pairs.
X */
X
X#define	gsinfo	struct	gsinfox
Xgsinfo	{
X		/* Ptr to a plaintext block of accepted chars. */
X		int	*cknown;
X		
X		/* Ptr to a plaintext block of guessed at chars. */
X		int	*cguessed;
X		
X		/* Vector of positions within cguessed that have characters. */
X		/* The list is terminated by -1. */
X		int	cpos[SZMAX+1];
X		};
X
END_OF_cipher.h
if test 3531 -ne `wc -c <cipher.h`; then
    echo shar: \"cipher.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f edriver.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"edriver.c\"
else
echo shar: Extracting \"edriver.c\" \(3139 characters\)
sed "s/^X//" >edriver.c <<'END_OF_edriver.c'
X/*
X * Test driver for equivalence class stuff.
X */
X
X#include	<stdio.h>
X#include	<math.h>
X#include	"window.h"
X#include	"specs.h"
X#include	"cipher.h"
X
X
Xecinfo	myecinfo;
X
Xchar	plainbuf[BLOCKSIZE+1];
Xfloat	accept_level;
X
Xextern	ec_best(), ec_dplain(), ec_dscipher();
Xextern	ec_dnext(), ec_dsizetab(), ec_dperm(), ec_dpmap();
Xextern	ec_init(), ec_best(), ec_cscore();
X
Xextern	char	mcbuf[];
Xextern	char	*fname;			/* Used by fillcbuf. */
X/* Test routine for equiv class info. */
Xmain(argc, argv)
Xint		argc;
Xchar	*argv[];
X{
X	ecinfo	*eci;
X	FILE	*inp;
X	int		i, blknum;
X	int		maxblock;
X	long	filelength;
X	char	infile[100];
X	char	inplain[100];
X	char	*plain = ".txt";
X	char	*code = ".cipher";
X	char	*p, *q;
X
X	if (argc != 3)  {
X		printf("Usage: %s input_file_root acceptance_level\n", argv[0]);
X		exit(0);
X		}
X
X	p = inplain;
X	q = argv[1];
X	while (*p++ = *q++);
X	--p;
X	q = plain;
X	while (*p++ = *q++);
X
X	p = infile;
X	q = argv[1];
X	while (*p++ = *q++);
X	--p;
X	q = code;
X	while (*p++ = *q++);
X
X	if (sscanf(argv[2], "%f", &accept_level) != 1)  {
X		printf("Could not parse the acceptance level from %s.\n", argv[2]);
X		exit(0);
X		}
X
X	load_1stats_from("mss.stats");
X	eci = &myecinfo;
X
X	if ((inp = fopen(infile, "r")) == NULL) {
X		printf("\nCannot open %s for reading.\n", infile);
X		exit(0);
X		}
X	fseek(inp, 0L, 2);
X	filelength = ftell(inp);
X	fclose(inp);
X
X	maxblock = filelength / BLOCKSIZE;
X	if (maxblock > 19)  maxblock = 19;
X
X	printf("\t\tEquivalence Class Guessing\n\n");
X	printf("Filename = %s.  Acceptance level = %4.2f\n",infile,accept_level);
X	for (blknum = 0 ; blknum <= maxblock ; blknum++) {
X		do_block(eci, blknum, infile, inplain);
X		}
X}
X
X
Xdo_block(eci, blknum, cipherfile, plainfile)
Xecinfo	*eci;
Xint		blknum;
Xchar	*cipherfile, *plainfile;
X{
X	int		i,c,x,y;
X	int		naccepted, nwrong;
X	int		classpos;
X	int		charcount;
X
X	fname = cipherfile;
X	fillcbuf(blknum, mcbuf);
X	fname = plainfile;
X	fillcbuf(blknum, plainbuf);
X
X	ec_init(mcbuf, refperm(blknum), eci);
X
X	naccepted = 0;
X	nwrong = 0;
X
X	for (i = 0 ; i < eci->sizelast ; i++)  {
X		classpos = eci->sizelist[i].firstpos;
X		c = ec_best(eci, classpos, accept_level);
X		if (c != NONE) {
X			x = eci->scipher[classpos];
X			y = MODMASK & (c + classpos);
X			if (eci->perm[x] == NONE  &&  eci->perm[y] == NONE) {
X				naccepted++;
X				eci->perm[x] = y;
X				eci->perm[y] = x;
X/*				printf("ACCEPTING best guess of %d wired to %d.\n",
X						x, y);
X*/				if ((MODMASK & plainbuf[classpos]) != c) {
X					nwrong++;
X/*					printf("*** WRONG ***  First char should be %c.\n",
X							plainbuf[classpos]);
X*/					}
X				}
X			else if (eci->perm[x] == y) {
X/*				printf("CONFIRMING guess of %d wired to %d.\n",
X						x, y);
X*/				}
X			else {
X/*				printf("CONFLICTING guess of %d wired to %d.\n",
X						x, y);
X*/				}
X			}
X		}
X
X	decode(eci->ciphertext, eci->plaintext, eci->perm);
X
X	charcount = 0;
X	for (i = 0 ; i < BLOCKSIZE ; i++)  {
X		if (eci->plaintext[i] != NONE)  charcount++;
X		}
X
X	printf("\n\nPlaintext for block %d using %d wires", blknum, naccepted);
X	printf(" (%d wrong)", nwrong);
X	printf(" yields %d characters.\n\n", charcount);
X	ec_dplain(stdout, eci);
X}
X
Xkey	u_getkey()
X{
X}
X
Xkeyer	topktab[] ={{0, NULL}};
END_OF_edriver.c
if test 3139 -ne `wc -c <edriver.c`; then
    echo shar: \"edriver.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gblock.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gblock.c\"
else
echo shar: Extracting \"gblock.c\" \(4009 characters\)
sed "s/^X//" >gblock.c <<'END_OF_gblock.c'
X/*
X * Guess block and its label.
X *
X * Robert W. Baldwin, December 1984.
X */
X
X
X#include	<stdio.h>
X#include	"window.h"
X#include	"terminal.h"
X#include	"layout.h"
X#include	"specs.h"
X#include	"cipher.h"		/* RWB */
X#include	"autotri.h"
X
X
X
X/* Private buffers for plaintext guessing. */
X
Xchar	gcbuf[BLOCKSIZE+1];
Xint		gpbuf[BLOCKSIZE+1];
Xint		gperm[BLOCKSIZE+1];
Xecinfo	gecinfo;			/* RWB */
X
Xextern	atrinfo	gatrinfo;
Xextern	char	mcbuf[];
X
X/* Window for the guess block label. */
X
Xdispline	gblline1 = {
X		GBLROW,1,		/* Origin. */
X		1,GBWIDTH,		/* Height and width. */
X		1,1,			/* Initial (relative) cursor pos. */
X		NULL,			/* No private data. */
X		wl_setcur,		/* Firstime = restore cursor pos. */
X		wl_noop,		/* Lasttime = do nothing. */
X		wl_dldraw,		/* Default dispaly line draw routine */
X		dokey,			/* Default keystroke handler. */
X		arwktab,		/* Basic arrow keystroke handler. */
X		1,GBWIDTH,		/* Min and Max col for cursor line */
X};
X
Xdispline	*gbllines[] = {		/* List of display lines for the label. */
X			&gblline1,
X			NULL,
X			};
X
Xtwindow		gblabel = {
X			GBLROW,1,		/* Origin. */
X			1,GBWIDTH,		/* Height and width. */
X			1,1,			/* Initial (relative) cursor position */
X			NULL,			/* No private data. */
X			wl_setcur,		/* Firstime = restore cursor position. */
X			wl_noop,		/* Lasttime = do nothing. */
X			wl_twdraw,		/* Simple draw routine. */
X			dokey,			/* Default keystroke handler. */
X			arwktab,		/* Basic arrow keystroke handler. */
X			gbllines,
X			};
X
X
X/* Window for the guess block. */
X
Xgwindow	gbstore = {
X		GBSROW,1,		/* Origin. */
X		GBHEIGHT,GBWIDTH,	/* Height and width. */
X		1,1,			/* Initial cursor position */
X		NULL,			/* Private data. */
X		wl_setcur,		/* Firstime = accept cursor pos. */
X		wl_noop,		/* Lasttime = do nothing. */
X		wl_outline,		/* Simple draw routine. */
X		dokey,			/* Default keystroke handler. */
X		arwktab,		/* Keystroke table. */
X};
X
X
X
X/* Initialize the guess block label, and return a ptr to it.
X */
Xgwindow	*(igblabel())
X{
X	displine	*line;
X
X	line = gblabel.dlines[0];
X	setadline(line, GBLTEXT);
X	return ((gwindow *) &gblabel);
X}
X
X
X/* Set the label to indicate the given string.
X * Redisplay the label.
X */
Xgblset(label, str)
Xtwindow	*label;
Xchar	*str;
X{
X	int		row,col;
X	displine	*line;
X
X	row = rowcursor();
X	col = colcursor();
X
X	line = label->dlines[0];
X	setadline(line, str);
X	(*(line->wredraw))(line);
X
X	setcursor(row, col);
X}
X
X
X
X/* Initialize the guess block storage, and return a ptr to it.
X * Start with the Trigram guessing window.
X */
Xgwindow	*(igbstore())
X{
X	extern	atrdraw();
X	extern	atr_init();
X	atrinfo	*atri;
X
X	atri = &gatrinfo;
X	atr_init(mcbuf, refperm(dbsgetblk(&dbstore)), atri);
X	gbsswitch(&gbstore, ((char *) atri), arwktab, wl_setcur, wl_noop, atrdraw);
X	return (&gbstore);
X}
X
X
X/* Switch the guessing window to the desired functionality
X * by changing the keytable, private data pointer, firsttime,
X * and lasttime function routines.
X */
Xgbsswitch(gbs, private, keytable, firsttime, lasttime, draw)
Xgwindow	*gbs;
Xchar	*private;
Xkeyer	keytable[];
Xint		(*firsttime)(), (*lasttime)();
Xint		(*draw)();
X{
X	gbs->wprivate = private;
X	gbs->wkeyprocs = keytable;
X	gbs->wfirst = firsttime;
X	gbs->wlast = lasttime;
X	gbs->wredraw = draw;
X}
X
X
X/* Convert block position to relative row/column coordinate.
X */
Xint	gbspos2row(pos)
Xint	pos;
X{
X	return(1 + (pos/LINELEN));
X}
X
X
X/* Convert block position to relative row/column coordinate.
X */
Xint	gbspos2col(pos)
Xint	pos;
X{
X	return(1 + (pos%LINELEN));
X}
X
X
X/* Clear out the guess block marking all character positions as unknown.
X */
Xgbsclear(gbs)
Xgwindow	*gbs;
X{
X	int			i;
X	int			row, col;
X
X	row = 1;
X	col = 1;
X
X	for (i = 0 ; i < BLOCKSIZE ; i++)  {
X		if (i%LINELEN == 0) {
X			wl_setcur(gbs, gbspos2row(i), gbspos2col(i));
X			}
X		plnchars(1, char2sym(NONE));
X		}
X
X	for (i = gbspos2row(BLOCKSIZE) ; i <= GBHEIGHT ; i++) {
X		wl_setcur(gbs, i, 1);
X		plnchars(LINELEN, ' ');
X		}
X
X	for (i = 1 ; i <= GBHEIGHT ; i++) {
X		wl_setcur(gbs, i, LINELEN+1);
X		plnchars(gbs->wwidth - LINELEN, ' ');
X		}
X
X	wl_setcur(gbs, row, col);
X}
END_OF_gblock.c
if test 4009 -ne `wc -c <gblock.c`; then
    echo shar: \"gblock.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mss-bigram-old.stats -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mss-bigram-old.stats\"
else
echo shar: Extracting \"mss-bigram-old.stats\" \(4489 characters\)
sed "s/^X//" >mss-bigram-old.stats <<'END_OF_mss-bigram-old.stats'
X62719
X
X1 \000\001\002\003\004\005\006\007\177\b\v\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037
X203 ({[<
X1019 Pp
X167 Xx
X328 >)}]
X48 Qq
X746 Yy
X211 @*+|~^=#$%&
X2655 Rr
X45 Zz
X3008 Ss
X879 .,:;?!
X4092 Tt
X647 _-
X1320 Uu
X456 Vv
X22 \\/
X833 Ww
X2143 0123456789
X13592 \t\n\p\r 
X249 '`"
X3498 Aa
X795 Bb
X1498 Cc
X1695 Dd
X5672 Ee
X850 Ff
X1041 Gg
X2144 Hh
X3114 Ii
X83 Jj
X246 Kk
X2034 Ll
X1223 Mm
X2860 Nn
X3302 Oo
X***
X386 TI
X656 \t0
X277 RO
X262 ME
X595 \tI
X414 ED
X5 G>
X26 FA
X40 YS
X234 H\t
X37 HT
X14 (P
X54 D.
X53 AP
X44 PU
X22 .>
X31 DG
X4 OX
X16 @S
X12 SL
X4 UF
X1 _Z
X31 'S
X5 >@
X2 _A
X1 IQ
X1 W'
X311 VE
X388 AR
X10 G'
X390 ND
X478 IS
X71 CL
X184 DI
X23 M.
X62 BO
X12 OA
X39 EF
X9 (R
X72 \tK
X2 .@
X5 E_
X1 \\L
X13 .'
X1 0S
X2 @U
X4 'U
X2 SN
X1 _C
X1 GY
X10 Q\t
X1 \t\000
X20 (T
X494 AT
X262 A\t
X269 \tM
X236 LL
X136 RS
X55 FE
X11 NF
X96 MI
X4 YW
X64 SP
X70 OC
X2 PY
X6 Y>
X13 Z\t
X1 KO
X2 M0
X52 XA
X5 EH
X2 IU
X1 P'
X4 'W
X2 TM
X3 '>
X4 .B
X4 HX
X1 @W
X13 (\t
X1 @>
X13 (V
X78 AV
X87 VI
X434 TO
X59 RU
X667 \tO
X3 >_
X129 UL
X41 BS
X296 HA
X9 0>
X1 PB
X6 HZ
X2 V0
X5 SR
X7 @@
X2 Y@
X3 F.
X9 OE
X2 XC
X2 DM
X3 Y'
X1 '@
X1 @'
X9 J\t
X1 @Y
X1 \\P
X1 >F
X22 @B
X86 FI
X355 ST
X1130 S\t
X64 CR
X176 WH
X139 UN
X70 BU
X139 EL
X77 DO
X69 MM
X10 PD
X4 HC
X16 XE
X6 O.
X35 OG
X8 LP
X9 KS
X11 R>
X14 RW
X6 0'
X6 _0
X3 (X
X2 'B
X2 AX
X27 \tQ
X1 I'
X5 YB
X125 MO
X556 \tS
X1033 HE
X160 CT
X467 EN
X109 TS
X40 OI
X74 GH
X74 UP
X98 RY
X18 IB
X4 B>
X12 (A
X48 C\t
X3 P_
X8 R'
X2 ZA
X12 NL
X13 'D
X1 _K
X1 SV
X1 @D
X7 0B
X7 \\\t
X18 RB
X47 EP
X109 ID
X298 L\t
X73 BY
X195 \tU
X17 NN
X151 AC
X54 TU
X4 _M
X125 UR
X21 H.
X3 Y_
X29 WL
X30 PH
X6 (C
X59 DS
X35 LT
X12 OK
X3 'F
X16 VO
X10 XI
X5 JA
X1 @F
X7 0D
X1 @_
X21 T>
X713 ER
X93 RD
X35 MS
X53 SA
X537 \tW
X144 FO
X273 HI
X52 TW
X149 UT
X215 OM
X56 DU
X64 IF
X27 WN
X5 @H
X28 GL
X2 H0
X5 0_
X6 I_
X6 NP
X45 U\t
X4 LV
X6 _O
X27 (E
X13 ZE
X5 K'
X1 BB
X1 KY
X3 'H
X2 AE
X7 0F
X12 \t>
X189 \t@
X30 JE
X109 \t'
X147 AG
X1892 E\t
X43 OO
X245 PL
X41 GN
X58 SC
X115 ET
X257 CA
X70 \tY
X2 \\A
X8 R_
X5 A.
X9 RF
X1 S\\
X4 D>
X56 MU
X2 Z.
X36 TY
X12 T'
X3 DW
X1 KB
X1 NR
X6 'J
X1 @J
X3 WP
X1 _Q
X17 M>
X4 J.
X575 N\t
X396 SE
X23 (I
X274 LA
X423 \tB
X357 NT
X50 AI
X74 EV
X17 CC
X15 DY
X34 WR
X3 RH
X5 (0
X16 _S
X5 FS
X5 XO
X14 D'
X5 HM
X2 ZI
X5 'L
X1 YL
X1 B_
X1 UX
X1 @L
X1 TB
X1 \\C
X36 AK
X112 EX
X286 >\t
X293 \tD
X64 OS
X141 IL
X135 HO
X178 S.
X33 FU
X61 W\t
X135 CE
X98 UA
X55 PP
X64 GR
X15 BH
X15 YN
X5 M'
X1 _U
X11 NV
X5 'N
X6 LC
X1 U(
X2 MY
X4 @N
X2 K_
X5 E(
X778 IN
X790 .\t
X203 SI
X303 \tF
X166 PR
X70 UC
X270 EA
X149 AM
X271 G\t
X13 BJ
X326 OU
X410 LE
X13 T_
X32 DD
X36 MB
X17 RL
X3 C.
X1 KH
X1 JK
X4 (M
X169 \t_
X9 'P
X1 GT
X5 S0
X1 EZ
X2 TF
X2 .T
X4 YP
X3 _W
X128 _>
X1 @P
X21 N(
X1274 TH
X21 L.
X102 NA
X148 EC
X55 UE
X154 OW
X99 BL
X3 _Y
X29 PT
X3 HS
X62 CI
X6 FY
X240 \tH
X25 IP
X13 ZO
X1 DF
X57 RN
X43 P\t
X37 D_
X6 (O
X10 SK
X6 C0
X9 NZ
X1 'R
X4 O>
X1 _@
X1 @R
X445 Y\t
X43 \tJ
X22 'T
X88 '\t
X2 DH
X99 IR
X204 LI
X132 EE
X52 UG
X53 CK
X109 NC
X5 _B
X3 X>
X83 WA
X13 JO
X10 SM
X13 YT
X32 HU
X1 M_
X38 @\t
X7 RP
X1 MF
X1 KL
X1 U.
X1 @T
X1 N\\
X63 EG
X341 \tL
X149 SO
X614 0\t
X288 AS
X39 GA
X188 NE
X124 E.
X363 IT
X68 OB
X30 RR
X47 TL
X55 KN
X35 I\t
X22 G(
X8 (S
X43 UI
X2 'V
X4 MH
X1 CM
X2 H>
X38 QU
X2 X@
X11 LK
X2 XY
X1 @V
X1 \\M
X1 W\\
X12 HY
X105 PA
X168 WE
X332 CO
X476 R\t
X80 OD
X59 IV
X47 EI
X459 NG
X131 \tN
X61 N.
X93 RT
X30 AU
X4 _F
X9 DL
X37 FF
X14 BR
X4 SQ
X2 H'
X1 (U
X372 __
X1 @X
X384 \tP
X342 OF
X202 GE
X33 >.
X131 SS
X145 LO
X21 JU
X118 NI
X63 UM
X2 HB
X12 IX
X7 AW
X1 ML
X2 .E
X2 _H
X17 TP
X27 B\t
X5 P\\
X2 PC
X5 @(
X3 W.
X2 O_
X13 RV
X11 (W
X3 DN
X4 BT
X4 'A
X1 EK
X3 CQ
X1 @A
X1 @Z
X148 TR
X221 \tR
X36 G.
X153 AY
X48 I(
X155 PE
X6 GG
X142 WI
X189 EM
X73 SU
X4 X_
X73 K\t
X27 IA
X2 Y\\
X26 ..
X4 @C
X7 CS
X18 IZ
X25 NK
X20 OH
X4 YC
X3 'C
X3 (Y
X2 MN
X1 ('
X2 BV
X7 0A
X1 @\\
X2 UO
X1 \\S
X1 \000\t
X3271 \t\t
X85 GI
X1646 \tT
X17 .0
X17 OJ
X701 T\t
X22 @E
X57 EO
X204 RA
X78 YE
X235 IC
X125 AB
X93 LS
X11 S>
X154 MP
X56 CU
X57 DR
X43 TT
X6 P.
X6 (B
X16 FL
X5 'E
X7 SW
X2 H_
X1 _L
X4 NM
X1 .I
X7 0C
X47 BA
X713 D\t
X125 \tV
X56 Y.
X3 _N
X134 NO
X198 US
X44 SY
X112 OL
X94 IE
X122 AD
X19 S'
X85 RC
X2 \\W
X24 LU
X13 PI
X7 (D
X1 C>
X9 EQ
X19 '.
X1 'G
X2 YG
X1 @G
X7 0E
X1 R\\
X1 @.
X497 ON
X31 0.
X631 RE
X465 ES
X94 IG
X49 @I
X17 YI
X143 M\t
X92 WO
X26 \tX
X3 _P
X5 I.
X3 (F
X5 '0
X3 KA
X7 CY
X5 @0
X4 A_
X5 LW
X8 AF
X2 DV
X6 'I
X4 L>
X2 C'
X2 TX
X2 NQ
X229 BE
X1432 00
X62 OP
X205 TA
X165 NS
X1047 \tA
X77 \t(
X151 LY
X61 R.
X42 FR
X18 RG
X20 GO
X3 T(
X2 (H
X1 HL
X1 U>
X5 EU
X30 _R
X10 L'
X1 II
X1 'K
X16 V\t
X1 VT
X2 @K
X9 \tZ
X9 @M
X65 KE
X56 DA
X91 PO
X21 D(
X483 \tC
X414 OR
X377 F\t
X51 E>
X7 SF
X177 RI
X29 NU
X13 WS
X21 TC
X20 FT
X29 EW
X3 AJ
X3 0K
X6 _T
X6 \\D
X43 _\t
X1 YM
X14 IK
X28 XP
X9 HN
X1 'M
X1 B.
X6 \t\\
X1 S_
X1 T\\
X184 MA
X446 TE
X179 IM
X114 OT
X79 SH
X335 AL
X513 O\t
X91 LD
X240 \tE
X43 UB
X92 BI
X33 EY
X3 D\\
X8 N>
X4 _V
X7 K.
X4 C_
X27 GS
X4 (L
X6 DC
X5 RK
X14 E'
X45 YO
X2 'O
X2 @O
X12 XT
X62 T.
X254 DE
X208 IO
X209 CH
X132 \tG
X606 AN
X33 NY
X7 EB
X67 OV
X29 HR
X31 X\t
X46 RM
X13 PS
X23 VA
X22 KI
X3 LF
X5 MC
X109 GU
X2 (N
X27 UD
X12 N'
X26 \t.
X1 L_
X1 @Q
END_OF_mss-bigram-old.stats
if test 4489 -ne `wc -c <mss-bigram-old.stats`; then
    echo shar: \"mss-bigram-old.stats\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f perm.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"perm.c\"
else
echo shar: Extracting \"perm.c\" \(4673 characters\)
sed "s/^X//" >perm.c <<'END_OF_perm.c'
X/*
X * Abstraction for the table of cipher text blocks and
X * their decoded permutations so far.
X *
X * Robert W. Baldwin, December 1984.
X */
X
X
X#include	<stdio.h>
X#include	"window.h"
X#include	"specs.h"
X
X
X#define	NPERLINE	10		/* How many values per line in save file. */
X#define	FROMSTART	0		/* For fseek call, how offset measured. */
X
X
X/* Input file name for permutations. */
Xchar	*permfile;
X
X
X/* Global state. */
Xint		permchgflg = FALSE;	/* True if perms changed since last save. */
Xint		*permtab[NPERMS];	/* Table of saved permutations or null. */
Xint		perminit = FALSE;	/* Initialization flag. */
X
X
X/* Allocate and clear a permutation.
X */
Xint	*permalloc()
X{
X	int		i;
X	int		*perm;
X
X	perm = ((int *) malloc((BLOCKSIZE+1)*sizeof(int)));
X	if (perm == NULL)  {
X		printf("\nNo room to allocate permutation.\n");
X		exit(0);
X		}
X
X	for (i = 0 ; i < BLOCKSIZE ; i++)  {
X		perm[i] = -1;
X		}
X
X	return(perm);
X}
X
X
X/* Return a pointer (for read or write use) to the permutation
X * for the given block number.
X * Return NULL if the block number is bad.
X */
Xint	*refperm(blocknum)
Xint	blocknum;
X{
X	int		i;
X
X	if ((blocknum < 0) || (NPERMS <= blocknum))  return(NULL);
X
X	if (!perminit) {
X		perminit = TRUE;
X		for (i = 0 ; i < NPERMS ; i++)  permtab[i] = NULL;
X		}
X
X	if (permtab[blocknum] == NULL)  {
X		permtab[blocknum] = permalloc();
X		}
X
X	return(permtab[blocknum]);
X}
X
X
X/* Save all the permutations in a file.
X * This can be invoked as a command.
X * For now, the are no arguments, the filename is fixed.
X * Return NULL if successful, else error mesage.
X * First the Zee matrix is dumped, then the permutations.
X * Each block is separated by a newline character.
X * Individual numbers are separated by blanks.
X */
Xchar	*permsave(str)
Xchar	*str;
X{
X	FILE	*fd;
X	int		i;
X
X	if ((fd = fopen(permfile, "w")) == NULL)  {
X		sprintf(statmsg, "Could not open %s to write permutations.", permfile);
X		return(statmsg);
X		}
X
X	storezee(fd);
X	
X	for (i = 0 ; i < NPERMS ; i++) {
X		writeperm(fd, refperm(i));
X		}
X
X	fclose(fd);
X	permchgflg = FALSE;
X	return(NULL);
X}
X
X
X/* Restore all the permutations by reading them from a file.
X * This can be invoked as a command.
X * For now, the are no arguments, the filename is fixed.
X * Return NULL if successful, else ptr to error message.
X * Also call dblock to update its display.
X */
Xchar	*permload(str)
Xchar	*str;
X{
X	FILE	*fd;
X	int		i;
X
X	if ((fd = fopen(permfile, "r")) == NULL)  {
X		sprintf(statmsg, "Could not open %s to read permutations.", permfile);
X		return(statmsg);
X		}
X
X	loadzee(fd);
X
X	for (i = 0 ; i < NPERMS ; i++) {
X		readperm(fd, refperm(i));
X		}
X
X	fclose(fd);
X	permchgflg = FALSE;
X
X	dbssetblk(&dbstore, dbsgetblk(&dbstore));	/* Update perm and cbuf. */
X
X	return(NULL);
X
X}
X
X
X
X/* Compute a permutation raised to some power.
X */
Xexpperm(srcperm, dstperm, power)
Xint	*srcperm, *dstperm;
Xint	power;
X{
X	int		i, k, v;
X
X	for (i = 0 ; i < BLOCKSIZE ; i++) {
X		v = i;
X		for (k = 0 ; k < power ; k++) {
X			v = srcperm[v];
X			if (v == -1)  break;
X			}
X		dstperm[i] = v;
X		}
X}
X
X
X/* Computer product of two permutations.
X */
Xmultperm(left, right, result)
Xint		*left;
Xint		*right;
Xint		*result;
X{
X	int		i, v;
X
X	for (i = 0 ; i < BLOCKSIZE ; i++) {
X		v = right[i];
X		if (v != -1)  v = left[v];
X		result[i] = v;
X		}
X}
X
X
X/* Write a permutation onto the given stream.
X */
Xwriteperm(fd, perm)
XFILE	*fd;
Xint		perm[];
X{
X	int		j;
X
X	for (j = 0 ; j < BLOCKSIZE ; j++)  {
X		fprintf(fd, "%3d ", perm[j]);
X		if ((j+1)%NPERLINE == 0)  fprintf(fd,"\n");
X		}
X
X	fprintf(fd,"\n");
X}
X
X
X
X/* Copy a permutation to another buffer.
X */
Xcopyperm(src, dst)
Xint		src[];
Xint		dst[];
X{
X	int		j;
X
X	for (j = 0 ; j < BLOCKSIZE ; j++)  {
X		dst[j] = src[j];
X		}
X}
X
X
X/* Read a permutation from the given stream into the given buffer.
X */
Xreadperm(fd, perm)
XFILE	*fd;
Xint		perm[];
X{
X	int		j;
X
X	for (j = 0 ; j < BLOCKSIZE ; j++)  {
X		fscanf(fd, "%3d", &perm[j]);
X		}
X
X	fscanf(fd,"\n");
X}
X
X
X/* Return a count of the number of values in the permutation that
X * are not equal to -1.
X * Max value is 256.
X */
Xint	permcount(perm)
Xint		perm[];
X{
X	int		i;
X	int		count;
X
X	count = 0;
X	for (i = 0 ; i < BLOCKSIZE ; i++)  {
X		if (perm[i] != -1)  count++;
X		}
X	return(count);
X}
X
X
X/* Return a count of the number of wires in a symetric permutation.
X * Return -1 if the permutation is not its own inverse or 
X * if it has fixed points.
X * Max value is 128.
X */
Xint	permwcount(perm)
Xint		perm[];
X{
X	int		i,v;
X	int		count;
X
X	count = 0;
X	for (i = 0 ; i < BLOCKSIZE ; i++)  {
X		v = perm[i];
X		if (v == -1) continue;
X		if (perm[v] != i)  return(-1);		/* Not self inverse. */
X		if (v == i)        return(-1);		/* Has fixed point. */
X		if (i < v)   continue;				/* Count first instance. */
X		count++;
X		}
X	return(count);
X}
END_OF_perm.c
if test 4673 -ne `wc -c <perm.c`; then
    echo shar: \"perm.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f start.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"start.c\"
else
echo shar: Extracting \"start.c\" \(4797 characters\)
sed "s/^X//" >start.c <<'END_OF_start.c'
X/*
X * Start up module for the crypt breaking editor.
X * Much of the global behavior of the program is set here.
X *
X * Robert W. Baldwin, December 1984.
X *
X * Bob Baldwin, 10/86:
X *  Added cmd to jump to user window.
X *  Handle C-Z to suspend CBW and abort commands.
X */
X
X
X#include	<stdio.h>
X#include	<signal.h>
X#include	<setjmp.h>
X#include	"window.h"
X#include	"terminal.h"
X#include	"layout.h"
X#include	"specs.h"
X
X
X/* Shell variable names. */
X#define	LETTERSTATS	"LETTERSTATS"
X#define	BIGRAMSTATS	"BIGRAMSTATS"
X#define	TRIGRAMSTATS	"TRIGRAMSTATS"
X
X#define	QUITMSG	"Permutations not saved.  Type 'y' if you want to quit."
X
X
X/* Keystroke behavior that is the same in all windows.
X */
Xextern		alldraw(), jumpcmd();
Xextern	char	*getenv();
X
Xkeyer	topktab[] = {
X		{CREFRESH, alldraw},
X		{CJUMPCMD, jumpcmd},
X		{0, NULL},
X		};
X
X
X/* Table of all top-level windows.  Terminated by NULL.
X */
Xgwindow		*wtable[WINDNUM+1];
Xchar		cfilebuf[100];
Xchar		pfilebuf[100];
X
X/* Saved stack state for suspending the program.
X */
Xjmp_buf		saved_stack;
X
X
Xmain(argc, argv)
Xint		argc;
Xchar	*argv[];
X{
X	extern	stop_handler();
X	extern	kill_handler();
X	char	*q, *pp, *pc;
X
X	if (argc < 2)  {
X		printf("Usage: %s FileNameRoot\n", argv[0]);
X		printf("\tThe extensions .cipher and .perm will be used.");
X		printf("\n\tThe shell variables");
X		printf(" %s, %s, %s,", LETTERSTATS, TRIGRAMSTATS, BIGRAMSTATS);
X		printf("\n\tand TERM must be defined.");
X		printf("\n\tThe shell variables");
X		printf(" %s and %s", GRAPHICSVAR, KEYMAPVAR);
X		printf(" may be defined.");
X		printf("\n");
X		exit(0);
X		}
X	q = argv[1];
X	pc = cipherfile = cfilebuf;
X	pp = permfile = pfilebuf;
X	while (*pp++ = *pc++ = *q++);
X	pp--;
X	pc--;
X	q = ".cipher";
X	while (*pc++ = *q++);
X	q = ".perm";
X	while (*pp++ = *q++); 
X
X	load_tables();
X
X	set_term();
X	signal(SIGTSTP, stop_handler);
X	signal(SIGINT, kill_handler);
X
X	initwindows();
X
X	/* Control returns here when program restarted after C-Z. */
X 	setjmp(saved_stack);
X
X	alldraw();
X	usrstatus(&user, "Ready.");
X	usrfirst(&user, 1, 1);		/* Start in user window. */
X	
X	wl_driver(wtable);
X	done(0);			/* Fell off windows, we're done. */
X}
X
X
X/* Handle C-Z signal (suspend program).
X * Restore screen and exit.
X * On restart, setup screen, redraw screen, and abort to top loop.
X */
Xstop_handler()
X{
X	setcursor(MAXHEIGHT, 1);
X	fflush(stdout);
X	unset_term();
X	
X	kill(getpid(), SIGSTOP);
X
X	/* Return here when/if program restarted. */
X	/* Note that the signal mask is restored by longjmp. */
X	set_term();
X	longjmp(saved_stack, 0);
X}
X
X
X/* Handle C-C signal (kill program).
X * Restore screen and exit.
X */
Xkill_handler()
X{
X	setcursor(MAXHEIGHT, 1);
X	printf("\n");
X	fflush(stdout);
X	unset_term();
X	
X	kill(getpid(), SIGKILL);
X}
X
X
X/* Load stat tables.
X */
Xload_tables()
X{
X	printf("\n\nLoading letter statistics ...");
X	fflush(stdout);
X	if ((letterstats = getenv(LETTERSTATS)) == NULL)  {
X		printf("The shell variable %s is not defined.\n", LETTERSTATS);
X		exit(0);
X		}
X	load_1stats_from(letterstats);
X	printf(" done.\n");
X
X	printf("\n\nLoading bigram statistics ...");
X	fflush(stdout);
X	if ((bigramstats = getenv(BIGRAMSTATS)) == NULL)  {
X		printf("The shell variable %s is not defined.\n", BIGRAMSTATS);
X		exit(0);
X		}
X	load_2stats_from(bigramstats);
X	printf(" done.\n");
X
X	printf("\n\nLoading trigram statistics ...");
X	fflush(stdout);
X	if ((trigramstats = getenv(TRIGRAMSTATS)) == NULL)  {
X		printf("The shell variable %s is not defined.\n",TRIGRAMSTATS);
X		exit(0);
X		}
X	load_tri_from(trigramstats);
X	printf(" done.\n");
X	
X	permchgflg = FALSE;
X}
X
X
X/* Quit command
X * This is the prefered way to leave the program.
X */
Xchar *quitcmd(arg)
Xchar	*arg;
X{
X	char	c;
X
X	if (permchgflg)  {
X		usrstatus(&user, QUITMSG);
X		c = getchar();
X		if (!(c == 'y'  ||  c == 'Y'))
X		  	return(NULL);
X		}
X	done(0);
X}
X
X
X/* Exit the program after cleaning up the terminal.
X */
Xdone(status)
Xint	status;
X{
X	unset_term();
X	printf("\n");
X	exit(status);
X}
X
X
X/* (re)Draw all the windows.
X */
Xalldraw()
X{
X	wl_refresh(wtable);
X}
X
X
X/* Jump to the command window.
X * Tell the current window, that it is losing the cursor, and
X * then tell the user window that it's got the cursor.
X */
Xjumpcmd(w)
Xgwindow	*w;
X{
X	(*(w->wlast))(w);
X	usrfirst(&user, 1, 1);		/* Given row, col ignored. */
X}
X
X
X/* Fill in the window table.
X */
Xinitwindows()
X{
X	int	i;
X
X	i = 0;
X	wtable[i++] = iuser();
X	wtable[i++] = ibanner();
X	wtable[i++] = idblabel();
X	wtable[i++] = idbstore();
X	wtable[i++] = igblabel();
X	wtable[i++] = igbstore();
X	wtable[i++] = iwebster();
X
X	if (i != WINDNUM)  {
X		disperr("inittables: WINDNUM value is wrong");
X		setcursor(2,1);
X		exit(0);
X		}
X
X	wtable[i] = ((gwindow *) NULL);
X}
X
X
X/* Get keystroke routine.
X * Responsible for clearing the status area before every keystroke.
X */
Xkey	u_getkey()
X{
X	key	k;
X
X	k = getcmd();
X	usrstatus(&user, "");
X
X	return(k);
X}
END_OF_start.c
if test 4797 -ne `wc -c <start.c`; then
    echo shar: \"start.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f terminal.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"terminal.h\"
else
echo shar: Extracting \"terminal.h\" \(4892 characters\)
sed "s/^X//" >terminal.h <<'END_OF_terminal.h'
X/*
X * Definitions for terminals (symbols, graphics, keystroke, commands).
X *
X * Author: Bob Baldwin, October 1986.
X */
X
X
X/* Names of shell variables for keystroke map and symbol map.
X */
X#define	GRAPHICSVAR	"GRAPHICSMAP"
X#define	KEYMAPVAR	"KEYMAP"
X
X
X/* Screen control strings from termcap entry.
X */
Xextern	char	*term_is;		/* Terminal initializaion string. */
Xextern	char	*erase_eol;		/* Erase to end of line. */
Xextern	char	*erase_eos;		/* Erase to end of screen. */
Xextern	char	*erase_scr;		/* Erase whole screen. */
Xextern	char	*cm;			/* Cursor motion. */
Xextern	char	*start_alt;		/* Start graphics mode. */
Xextern	char	*end_alt;		/* End graphics mode. */
Xextern	char	*start_so;		/* Start standout mode. */
Xextern	char	*end_so;		/* End standout mode. */
Xextern	char	*start_kp;		/* Start send keypad escapes. */
Xextern	char	*end_kp;		/* End send keypad escapes. */
X
X/* Keymap strings from termcap file.
X */
Xextern	char	*term_f1;		/* The f1 key. */
Xextern	char	*term_f2;		/* The f2 key. */
Xextern	char	*term_f3;		/* The f3 key. */
Xextern	char	*term_f4;		/* The f4 key. */
Xextern	char	*term_up;		/* Up arrow. */
Xextern	char	*term_down;		/* Down arrow. */
Xextern	char	*term_left;		/* Left arrow. */
Xextern	char	*term_right;		/* Right arrow. */
X
X
X/* Flag values
X */
X#define	CHARM		0377		/* Mask for 8 bit chars. */
X#define SYMBOL		128		/* OR'ed with symbol codes. */
X#define	SYMBOLM		(SYMBOL - 1)	/* Mask for symbol codes. */
X
X
X/* Symbol codes.
X * These can be used as array indices if the SYMBOL bit is stripped.
X */
X#define	STAB		(0 | SYMBOL)	/* Tab character. */
X#define	SNOTASCII	(1 | SYMBOL)	/* Byte with high bit set. */
X#define	SLINEFEED	(2 | SYMBOL)	/* Linefeed character. */
X#define	SCARETURN	(3 | SYMBOL)	/* Return character. */
X#define	SFORMFEED	(4 | SYMBOL)	/* Formfeed character. */
X#define	SCONTCODE	(5 | SYMBOL)	/* Other control characters. */
X#define	SUNKNOWN	(6 | SYMBOL)	/* Character decryption unknown. */
X#define	SUNDERLINE	(7 | SYMBOL)	/* Pseudo underline symbol, it */
X    					/* highlights char on prev line. */
X#define	SVERTBAR	(8 | SYMBOL)	/* Vertical bar. */
X#define	SHORZBAR	(9 | SYMBOL)	/* Horizontal bar. */
X#define	SLLCORNER	(10 | SYMBOL)	/* Lower-left corner. */
X#define	NSYMC		 11		/* Number of symbol codes. */
X
X
X/* Default graphics settings, in the format of the shell variable.
X * Extra spaces, tabs and colons are for testing.
X * Entries are separated by spaces, tabs, or colons, and
X * terminated by colon or NULL.
X */
X#define	VARSEP		"\t \n:"
X#define	VARTERM		":"
X#define	GVARMODES	"NGS"		/* From s_mode values */
X#define	DGRAPHICS	"tb=\\St:na=\\SX: lf=\\Sn:cr=\\Sr:	:\
X 			 ff=\\Sf:cc=\\SC:uk=\\S :::ul=\\N^:\
X 			 hb=\\N-:vb=\\N|:ll=\\N`"
X
X
X/* Structure of symbol to graphics table.
X * The s_seq strings are allocated from the heap during init.
X * The table graphtab is indexed by the symbol code.
X */
X#define	SMNORMAL	'N'	/* Values for s_mode. */
X#define	SMGRAPHIC	'G'
X#define	SMSTANDOUT	'S'
X#define	symgraph	struct symgraphx
Xsymgraph	{
X	int	s_mode;			/* Symbol display mode. */
X	char	*s_seq;			/* Chars to send in that mode. */
X};
X
X
X/* Command codes.
X * These are not intended to be used as array indices.
X * Note problem with CNONE.
X */
X#define	CMDSHIFT	8		/* Commands in high byte. */
X#define	CMDMASK		0377		/* Mask to get cmd code. */
X#define	CNONE		0		/* Not a command. */
X#define	CGO_UP		1		/* Sames as jogcursor() arg. */
X#define	CGO_DOWN	2
X#define	CGO_LEFT	3
X#define CGO_RIGHT	4
X#define	CREFRESH	5		/* Refresh screen. */
X#define	CUNDO		6		/* Undo guess. */
X#define	CCLRLINE	7		/* Clear whole line. */
X#define	CWRDSRCH	8		/* Search for word. */
X#define	CDELF		9		/* Delete forward. */
X#define	CDELB		10		/* Delete backward. */
X#define	CPREVBLOCK	11		/* Goto previous block. */
X#define CNEXTBLOCK	12		/* Goto next block. */
X#define	CNEXTGUESS	12		/* Next guess. */
X#define CNEXTARG	12		/* Goto next arg in template. */
X#define	CACCEPT		13		/* Accept guess. */
X#define	CEXECUTE	14		/* Execute a command. */
X#define	CRETURN		14		/* Insert a return char. */
X#define	CINSERT		15		/* Insert the arg char. */
X#define	CTRYALL		16		/* Try all chars here. */
X#define	CJUMPCMD	17		/* Jump to cmd line. */
X
X
X/* See cmdnames[] for a list of the field labels in the default keymap.
X */
X#define	DKEYMAP		"ta=\024:up=\020:do=\016:le=\002:ri=\006:\
X 			 re=\014:un=\007:cl=\025:ws=\027:\
X 			 df=\\004:db=\177:jc=\030:ex=\\n:\
X 			 pr=\022:ne=\023:ac=\001"
X
X
X/* Structure of key command table.
X * The c_seq strings are allocated from the heap during init.
X */
X#define	keycmd	struct keycmdx
Xkeycmd	{
X	int	c_code;			/* Command code. */
X	char	*c_seq;			/* Chars in keystroke. */
X};
X
X
X/* Structure for parsing shell variables in a format like termcap.
X * The last entry in a table of these has label == NULL.
X */
X#define	labelv	struct	labelvx
Xlabelv	{
X	char	*label;		/* Label string. */
X	int	value;		/* Arbitrary value for label. */
X};
X
X
X#define	DIGITS	"0123456789"
END_OF_terminal.h
if test 4892 -ne `wc -c <terminal.h`; then
    echo shar: \"terminal.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f test2.txt -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"test2.txt\"
else
echo shar: Extracting \"test2.txt\" \(4316 characters\)
sed "s/^X//" >test2.txt <<'END_OF_test2.txt'
Xtherefore, each IPC message from an Eject to the Eden kernel, and vice
Xversa, involves at least a Unix process switch and copying the IPC
Xmessage into and out of the Unix kernel.
X
XThe first versions of Eden required 14 IPC messages to be sent per
Xlocal invocation.  A local invocation occurs when the invoking Eject
Xand the target Eject reside on the same physical machine.
XWhat was 2-process kernel's role in this setup?
X
XThe 2-process Eden kernel was finally replaced by a 1-process Eden
Xkernel, immediately reducing the number of messages required for an
Xinvocation by eliminating the IPC messages between the two kernel
Xprocesses.
X
XThe final reduction in IPC messages sent per invocation occurred
Xduring the summer of 1984.  Two more IPC messages were eliminated.
XOne of the messages eliminated was the IPC message from the Eden
Xkernel to the invoking Eject that communicated the {\it invocation
Xhandle} assigned to that particular call.  It was replaced by a scheme
Xwhere the invoking Eject was allowed to generate its own {\it local
Xinvocation handle} to communicate with the Eden kernel, and the Eden
Xkernel would generate its own unique handle in order to communicate
Xwith another Eden kernel or the target Eject.  The Eden kernel
Xguarantees that the reply message to an invocation will be stamped
Xwith the invoking Eject-generated handle.  The other IPC message
Xeliminated was the status message from the Eden kernel to the target
XEject confirming the kernel's approval of the reply message (format,
Xor contents if capabilities were contained in the reply).  The more
Xlogical scheme of notifying the invoking Eject of the failure status
Xof the reply, or the actual reply if the status was success, is now
Xbeing used.  The result of all these improvements is shown in figure
X\ref{oldfig}.  (See section \ref{oldexp} for an explanation of figure
X\ref{oldfig}.)
X
X\section{Related Work}\label{introrel}
X
XNelson's thesis thoroughly examines remote procedure calls.  He
Xstudies a number of implementations, and proposes a design for
XEmmisary(?), a new RPC mechanism with excellent transparency and
Xexceptional performance.  To attain exceptional performance, Nelson
Xgives a list of "lessons" that an RPC mechanism must have.  The
Xlessons are summarized here for the reader:
X
X\begin{itemize}
X\end{itemize}
X
XIn designing an RPC mechanism, it is convenient to use a layer model.
XHowever, strict adherance to the layer model often results in poor
Ximplementations.  There is a prohibitive cost associated with highly
Xmodular implementations that cannot be tolerated in RPC
Ximplementations.  In proposing a solution to the asynchrony
Xproblem, Cooper\cite{soft} advocates "soft layering".  The idea of soft
Xlayering may be applied to any naturally layered system whose layers
Xmust work well together.
X
X\section{Structure of Thesis}\label{introstruct}
X
XChapter \ref{old} examines the deficiencies of the current Eden
Xinvocation mechanism.  The reader is taken on a tour through the
Xprocess of initiating an invocation and receiving its reply, and
Xreceiving a new invocation and replying to the invocation.
X
XChapter \ref{new} proposes restructuring the dispatcher module for
Xsynchronous invocations (by far the most heavily used form of
Xcommunication within Eden) and breaking down the "hard layering" that
Xcurrently exists between the various layers that support invocations,
Xfrom the Eject's point of view, in order to obtain significant
Xperformance gains.
X
X\chapter{A Closer Look at the Eden Invocation Mechanism}\label{old}
X
X\section{The Dispatcher -- Interface and Internals}\label{olddis}
X
X\section{Flow of Data -- CIP, Stub, and ESCII}\label{olddat}
X
X\section{Summary}\label{oldsum}
X
X\chapter{An Alternative Synchronous Invocation Mechanism}\label{new}
X
X\section{Assumptions and Limitations}\label{newass}
X
X\section{The Dispatcher -- Interface and Internals}\label{newdis}
X
X\section{A Word About Buffer Management}\label{newbuf}
X
X\section{Flow of Data -- CIP, Stub, and ESCII}\label{newdat}
X
X\section{Results and Timings}\label{newres}
X
X\section{Summary}\label{newsum}
X
X\chapter{Conclusions and Further Work}\label{concl}
X
X\section{Lessons Re-learned}\label{conles}
X
X\section{Soft Layering}\label{conlay}
X
X\section{Modularization and Interfaces}\label{conmod}
X
X\section{Further Work}\label{confur}
X
X\end{document}
X
END_OF_test2.txt
if test 4316 -ne `wc -c <test2.txt`; then
    echo shar: \"test2.txt\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f webster.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"webster.c\"
else
echo shar: Extracting \"webster.c\" \(4720 characters\)
sed "s/^X//" >webster.c <<'END_OF_webster.c'
X/*
X * Pattern matching on words in a dictionary.
X * Patterns are entered as command arguments and results are
X * displayed in this window.
X *
X * Robert W. Baldwin, December 1984.
X */
X
X
X#include	<stdio.h>
X#include	"window.h"
X#include	"terminal.h"
X#include	"layout.h"
X#include	"specs.h"
X
X
X#define	DICTNAME	"/usr/dict/words"
X#define	DICTVAR		"DICTIONARY"	/* Name of shell var. */
X#define	WEBHELP		"Word match is invoked using the 'lookup' command"
X#define	TOPINDEX	2
X#define	BOTINDEX	(WEBHEIGHT-2)
X
Xextern	int	wordsim();	/* Defined below. */
Xextern		web_first();	/* Defined below. */
X
X/* Strings for outlining the window.
X */
Xchar	*webhead = "| Word Match";
Xchar	*webpane = "|";
Xchar	*webbot  = "`-------------------------";
X
X/* Window for the list of matches. */
X
Xdispline webaline[WEBHEIGHT];		/* Display lines for the history. */
Xdispline *weblines[WEBHEIGHT+1];	/* Pointers to them plus NULL. */
X
Xtwindow  webster = {
X		WEBROW,WEBCOL,		/* Origin. */
X		WEBHEIGHT,WEBWIDTH,	/* Height and width. */
X		1,1,			/* Initial (relative) cursor pos. */
X		NULL,			/* No private data. */
X		web_first,		/* Firstime = accept cursor pos. */
X		wl_noop,		/* Lasttime = do nothing. */
X		wl_twdraw,		/* Default draw routine. */
X		dokey,			/* Default keystroke handler. */
X		arwktab,		/* Basic arrow keystroke handler. */
X		weblines,
X};
X
X
X
X/* Make a window with a title and partial outline.
X */
Xgwindow *(iwebster())
X{
X	int		i;
X	displine	*line;
X
X	webgraphics(webhead);
X	webgraphics(webpane);
X	webgraphics(webbot);
X
X	for (i = 0 ; i < WEBHEIGHT ; i++)  {
X		line = &webaline[i];
X		line->worg_row = webster.worg_row + i;
X		line->worg_col = webster.worg_col;
X		line->wheight = 1;
X		line->wwidth = webster.wwidth;
X		line->wcur_row = 1;
X		line->wcur_col = 1;
X		line->wfirst = wl_noop;
X		line->wlast = wl_noop;
X		line->wredraw = wl_dldraw;
X		line->wkey = dokey;
X		line->wkeyprocs = arwktab;
X		line->dl_min_col = 2;
X		line->dl_max_col = webster.wwidth;
X		setadline(line, webpane);
X		webster.dlines[i] = line;
X		}
X	webster.dlines[i] = NULL;
X
X	line = &webaline[0];
X	setadline(line, webhead);
X	line = &webaline[i - 1];
X	setadline(line, webbot);	/* Truncates to fit. */
X	return((gwindow *) &webster);
X}
X
X
X/* Convert a default graphic chars to fancy graphics chars
X * in the given string.
X */
Xwebgraphics(str)
Xchar	*str;
X{
X	for ( ; *str != NULL ; str++)  {
X		switch (*str)  {
X		  default:
X			break;
X
X		  case '|':
X			*str = SVERTBAR;
X			break;
X
X		  case '-':
X			*str = SHORZBAR;
X			break;
X
X		  case '`':
X			*str = SLLCORNER;
X			break;
X		}
X	}
X}
X
X
X/* Command to lookup word pattern in dictionary.
X * The pattern contains letters and dots.  The dots match any character.
X */
Xchar *webmatch(args)
Xchar	*args;
X{
X	char	*p, *w;		/* Pattern and word pointers. */
X	char	patbuf[MAXWIDTH+1];
X	char	wordbuf[MAXWIDTH+1];
X	int	i;
X	char	*bufptr;
X	int	row,col;
X	FILE	*fd;
X	displine *line;
X	int	nextline;	/* Index of next line to put result. */
X	char	*dictfile;
X	extern	char	*getenv();
X
X	row = rowcursor();
X	col = colcursor();
X
X	if ((i = sscanf(args,"%*[^:]: %s", patbuf)) != 1) {
X		sprintf(statmsg, "Error, got %d args not 1. From: %s", i,args);
X		return(statmsg);	/* Beware: this returns a pointer to the stack. */
X		}
X	line = webster.dlines[TOPINDEX-1];
X	dlsetvar(line, patbuf);
X
X	for (nextline = TOPINDEX ; nextline <= BOTINDEX ; nextline++) {
X		line = webster.dlines[nextline];
X		dlsetvar(line, "");
X		}
X	wl_draw(&webster);
X	setcursor(row, col);
X	fflush(stdout);
X
X	dictfile = getenv(DICTVAR);
X	if (dictfile == NULL)
X	  	dictfile = DICTNAME;
X
X	if ((fd = fopen(dictfile, "r")) == NULL)  {
X		sprintf(statmsg, "Could not open %s to read dictionary.",
X			dictfile);
X		return(statmsg);
X		}
X
X	for (nextline = TOPINDEX ; nextline <= BOTINDEX ; nextline++) {
X		line = webster.dlines[nextline];
X		while (TRUE) {
X			bufptr = fgets(wordbuf, MAXWIDTH+1, fd);
X			if (bufptr != wordbuf) {
X				wordbuf[0] = '\000';
X				goto alldone;
X				}
X			if (wordsim(patbuf, wordbuf)) break;
X			}
X		for (w=wordbuf ; *w != '\n' ; w++) {}
X		*w = '\000';
X		dlsetvar(line, wordbuf);
X		wl_draw(line);
X		setcursor(row, col);
X		fflush(stdout);
X		}
X
Xalldone:
X	fclose(fd);
X
X	return(NULL);
X}
X
X
X/* Return TRUE if the pattern matches the word
X */
Xint	wordsim(pattern, word)
Xchar	*pattern;
Xchar	*word;
X{
X	for ( ; *pattern != 0 && *word != 0 ; ((int)pattern++)|((int)word++)) {
X		if (*word == '\n')
X		  	return(FALSE);
X		if (*pattern == '.')
X		  	continue;
X		if (*pattern != *word)
X		  	return(FALSE);
X		}
X	if (*pattern == 0 && *word == '\n')
X	  	return(TRUE); /* Same length */
X	return(FALSE);
X}
X
X
X/* Called when cursor enters the window.
X * Clears the help message and accepts the cursor position.
X */
Xweb_first(w, row, col)
Xgwindow	*w;
Xint		row, col;
X{
X	wl_setcur(w, row, col);
X	usrhelp(&user, WEBHELP);
X}
END_OF_webster.c
if test 4720 -ne `wc -c <webster.c`; then
    echo shar: \"webster.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f windowlib.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"windowlib.c\"
else
echo shar: Extracting \"windowlib.c\" \(4375 characters\)
sed "s/^X//" >windowlib.c <<'END_OF_windowlib.c'
X/*
X * Library of window routines.
X *
X * Robert W. Baldwin, December 1984.
X */
X
X#include	<stdio.h>
X#include	"window.h"
X#include	"specs.h"
X
X
X/* The external topktab must be filled in by the application.
X * It specifies the keystroke behavior that is the same in
X * all windows.  For example, the refresh function can be handled here.
X * It should be terminated by a keychar == 0, not -1, so the
X * active window will get a chance to handle the key.
X */
Xextern	keyer	topktab[];
X
X
X/* This external must be a routine that gets and returns
X * a keystroke (integer) without taking any arguments.
X */
Xextern	key		u_getkey();
X
X
X
X/* This is the main loop that runs the window system.
X * It returns if the cursor is not in any of the windows in wtab.
X */
Xwl_driver(wtab)
Xgwindow		*wtab[];		/* Ptr to null terminated list of windows. */
X{
Xgwindow		**pw, *w;
Xint			lrow, lcol;		/* Cursor location relative to window. */
Xkey			k;
X
Xwhile (TRUE)  {
X	for (pw = wtab ; TRUE ; pw++)  {
X		w = *pw;
X		if (w == NULL)  return;
X		if (wl_hascur(w))  break;
X		}
X
X	lrow = rowcursor() - w->worg_row + 1;
X	lcol = colcursor() - w->worg_col + 1;
X	(*(w->wfirst))(w, lrow, lcol);
X
X	while (wl_hascur(w))  {
X		k = u_getkey();
X		if (!ddokey(w, k, topktab)) {
X			(*(w->wkey))(w, k);
X			}
X		}
X
X	(*(w->wlast))(w);
X	}
X}
X
X
X
X/* Refresh all windows.
X * Do not move the cursor.
X */
Xwl_refresh(wtab)
Xgwindow		*wtab[];		/* Ptr to null terminated list of windows. */
X{
X	gwindow		**pw, *w;
X	int			row, col;		/* Initial global cursor location. */
X
X	row = rowcursor();
X	col = colcursor();
X
X	for (pw = wtab ; TRUE ; pw++)  {
X		w = *pw;
X		if (w == NULL)  break;
X		wl_draw(w);
X		}
X	setcursor(row, col);
X}
X
X
X
X/* Restore the cursor the the position saved in the window structure.
X * Can also be used to set the cursor by first setting the cursor coords
X * in the window data structure.
X */
Xwl_rcursor(w)
Xgwindow	*w;			/* Pointer to basic window data. */
X{
X	int	grow,gcol;	/* Global cursor locations. */
X
X	grow = w->wcur_row + w->worg_row - 1;
X	gcol = w->wcur_col + w->worg_col - 1;
X	setcursor(grow,gcol);
X	if (!wl_hascur(w))  disperr("wl_rcursor arguments out-of-bounds.");
X}
X
X
X
X/* Set the cursor to the given coordinates within a window.
X * That is, set it relative to the window's origin.
X * It displays an error if the cursor leaves the window.
X */
Xwl_setcur(w, row, col)
Xgwindow	*w;			/* Pointer to basic window data. */
Xint		row, col;	/* Local coordinates. */
X{
X	int	grow,gcol;	/* Global cursor locations. */
X
X	w->wcur_row = row;
X	w->wcur_col = col;
X	grow = w->worg_row + row - 1;
X	gcol = w->worg_col + col - 1;
X	setcursor(grow,gcol);
X	if (!wl_hascur(w))  disperr("wl_setcur arguments out-of-bounds.");
X}
X
X
X/* No-op window routine.
X */
Xwl_noop()
X{
X}
X
X
X
X/* Return TRUE if the cursor is in the given window.
X */
Xwl_hascur(w)
Xgwindow		*w;
X{
X	int		grow, gcol;		/* Global cursor location. */
X	int		lrow, lcol;		/* Cursor location relative to window. */
X
X	grow = rowcursor();
X	gcol = colcursor();
X	lrow = grow - w->worg_row + 1;
X	lcol = gcol - w->worg_col + 1;
X
X	if (lrow < 1  ||  w->wheight < lrow)  return(FALSE);
X	if (lcol < 1  ||  w->wwidth  < lcol)  return(FALSE);
X	return(TRUE);
X}
X
X
X
X/* Generic draw routine.
X */
Xwl_draw(w)
Xgwindow	*w;
X{
X	(*(w->wredraw))(w);
X}
X
X
X/* Redraw routine that can be used with any twindow.
X * Leaves cursor on the last display line.
X */
Xwl_twdraw(w)
Xtwindow	*w;
X{
X	displine	**lines, *line;
X
X	for (lines = w->dlines ; (line = *lines) != NULL ; lines++)  {
X		(*(line->wredraw))(line);
X		}
X}
X
X
X/* Erase the window by putting spaces of all of it.
X * Leave the cursor at the window's origin.
X */
Xwl_erase(w)
Xgwindow	*w;
X{
X	int	grow, gcol;		/* Global row and column locations. */
X	int i;
X
X	grow = w->worg_row;
X	gcol = w->worg_col;
X
X	for (i = 0 ; i < w->wheight ; i++)  {
X		setcursor(grow+i, gcol);
X		plnspaces(w->wwidth);
X		}
X	wl_setcur(w, 1, 1);
X}
X
X
X/* Outline a window without changing its inside.
X * Leave cursor at the origin.
X */
Xwl_outline(w)
Xgwindow	*w;
X{
X	int	grow, gcol;		/* Global row and column locations. */
X
X	grow = w->worg_row;
X	gcol = w->worg_col;
X
X	setcursor(grow, gcol);
X	plnchars(w->wwidth, '-');
X	setcursor(grow+w->wheight-1, gcol);
X	plnchars(w->wwidth, '-');
X
X	setcursor(grow, gcol);
X	vertnchars(w->wheight, '|');
X	setcursor(grow, gcol+w->wwidth-1);
X	vertnchars(w->wheight, '|');
X
X	grow = w->worg_row + w->wcur_row - 1;
X	gcol = w->worg_col + w->wcur_col - 1;
X	setcursor(grow, gcol);
X}
END_OF_windowlib.c
if test 4375 -ne `wc -c <windowlib.c`; then
    echo shar: \"windowlib.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 11\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 11 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Rich $alz			rsalz@pineapple.bbn.com
Cronus Project, BBN Labs	"Anger is an energy"