rs@uunet.UU.NET (Rich Salz) (06/19/87)
Submitted by: Robert W. Baldwin <BALDWIN@XX.LCS.MIT.EDU> Mod.sources: Volume 10, Issue 5 Archive-name: cbw/Part05 #! /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 5 (of 11)." # Contents: Read.me cipher.c eclass.c knit.c zeecode.perm # Wrapped by rs@uunet on Wed Jun 17 18:17:17 1987 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f Read.me -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Read.me\" else echo shar: Extracting \"Read.me\" \(9793 characters\) sed "s/^X//" >Read.me <<'END_OF_Read.me' X XUNPACKING NOTES [by Rich $alz] X There Usenet distribution of CBW includes six files that have Xbeen UUENCODE'd because they contain non-printing characters: X UU.foo UU.graphics UU.test UU.test1 UU.test2 UU.test3 XYou must first decode these files before using them; one of Xthe command sets will do the trick: X for I in UU.* ; do uudecode $I ; done -- /bin/sh X foreach I (UU.*) -- C shell X uudecode $I -- X end -- X X This directory contains the source, documentation, and Xauxilary files for the Crypt Breakers Workbench (cbw). CBW is Xa multi-window integrated workbench of tools that help a cryptanalist Xread files encrypted with the BSD4.2 crypt command. Anyone Xmay copy, modify, use, or redistribute this system. It was Xoriginally written by Robert W. Baldwin at MIT. X X XGETTING STARTED X X A user's manual is provided in cbw.doc. The scribe source Xfor the user's manual is in cbw.mss. The file Index briefly describes Xthe various programs in this directory. X X CBW is written in C and distributed with the source code to Xencourage people to play with it. It should run on any display Xterminal. Read the users manual for information on terminal Xcompatibility. X X X XTO COMPILE CBW X X Execute "make" with no arguments. CBW uses routines from the termcap Xand curses libraries, but it does not use the full curses package. X X XA FEW OTHER NOTES X X Page 2 of the users manual mentions that CBW cannot work X against files that have been run through compress (1) before Xencryption. Personally, I would prefer to have a DES-based Xself-inverse cipher. Most DES programs need to be told whether they Xare in encrypt or decrypt mode. However, IBM only grants free use of XDES if it is used according to NBS guidelines, and self-inverse is not Xone of the accepted operating modes. X X XTESTING X X The following is a step by step sequence of commands to exercise Xthe Crypt Breakers Workbench. It demonstrates how easily crypt files Xcan be broken. X X 1. Edit stats.slice to set the name of the directory that contains the X statistics files. Statistics for scribe documents are included with X the source files. X X The stats.slice file also defines the location of the dictionary X used by the lookup-pattern command. The default dictionary is X /usr/dict/words. The dictionary is just a list of words, one per X line. Case does not matter. X X 2. Execute 'source stats.slice' to initialize the necessary shell X variables. X X 3. If there is a .slice file for your terminal type (e.g., vt100.slice, X or h19.slice), execute source on that file. This initializes the X graphics map and key map. X X 4. Print out cbw.doc, so you can read it after you have decided that X you can't figure out how the program works. X X 5. Copy test3.perm and .cipher to foo.perm and foo.cipher. The .txt X files contain the original plaintext. X X 6. Execute 'cbw foo'. X X 7. The cursor will on the command line. Use the arrow keys (or C-P, X C-N, C-F, C-B) to move the cursor to the upper lefthand position of X the decryption window. Try typing '@Device[Dover]'. Notice that X most of the characters you type deduced other characters in the X block. X X 8. The 'D' in 'Dover' is wrong. Using the arrow keys, position the X cursor over the 'D' and type 'd'. X X 9. Advance to the position after the ']' and type C-T. A list of X possible characters for this position will be displayed. The list X is sorted with the most likely character on the left. Notice that X many characters are not possible because they would deduce non-ascii X characters elsewhere in the block, or they would conflict with X previously accepted guesses. X X Try guessing tab, comma and linefeed for the character after the X ']'. Use C-G to undo each guess. Delete and C-D do not restore the X old state, they just erase the wiring that was deduced by a X particular character. X X 10. Move the cursor down to the command line. You can use emacs cursor X characters (C-N, C-P, C-F, C-B) or the arrow keys. Unfortunately, X C-U does not work as in emacs. The C-X key or F4 will jump directly X to the command line. X X 11. Type 'pw '. The space will cause command completion for the X probable-word guessing command. Type F2 (or C-S) to advance to the X first argument, and enter the file name 'mss.words'. That file X contains a list of keywords used by the Scribe (Finalword) text X formatter. Press F2 to advance to the second argument, which X specifies a cut-off level for automatically accepting guesses. The X level is the maximum number of standard deviations that the scoring X function can be away from its expected value. Enter 1.2, and press X return to invoke the command. X X 12. A partially filled in block will appear in the guessing window. To X accept the result of this command, press F3 (or C-A). X X 13. Try the pword guess command again with a level of 3. To do this, X just move to the command line, change the 1.2 to a 3, and press X return. Again F3 accepts the guess. If some guesses look wrong X (such as the 'F' on the second line under the '[Article]'), you can X correct them using the editor in the decryption block window. X X 14. Advance to block 1 of the file by moving the cursor to the X decryption window and pressing F2 (or C-S). F1 (or C-R) moves back X one block, F2 moves ahead one block. X X 15. The second block is likely to be plain english with few scribe X commands. Move to the command window, type C-U to erase the line X and type 'bi ' to setup the bigram guessing command. Try an X acceptance level of 1.0 and a minimum probability of 0.6. Type X return to invoke the command. X X 16. After a short wait (~15 seconds), a partial block will appear. X Accept the guess with the F3 key in the guessing window. X X 17. Try looking up a pattern in the dictionary. In the command window X type 'look ', use F2 to advance to the pattern, and type in the X pattern '....llit.', and press return. This will match against the X word 'satellite' if it is in you site's dictionary. X X 18. One could go on like this, but let's skip ahead by loading in a X previously saved state. Invoke the load command (it loads the file X foo.perm, just as save dumps to foo.perm (making this command take a X filename is a good implementation exercise)). Type C-U, 'load ', X and return. Notice that all the work so far is replaced by the X information in the .perm file. This can be considered a feature. X X 19. Use the F1 and F2 keys in the decryption window to view the blocks X that have been solved. Notice that a fully solved block does not X specify all the wirings of the block key (permutation). Typically X only 105 of the 128 wires are used. X X 20. Lets try deducing the inter-block relationship (zee). Execute the X clear-zee command. X X 21. Execute knit blocks 0 through 3 with a min show count of 20. This X means that the program should only show you guesses that deduce 20 X or more wirings of the zee permutation. Press return to invoke this X guessing strategy. The cursor will move to the guessing window. X Press F2 to start the first round of guessing. X X The running time of the knit command is exponential in the number of X blocks knitted, and it will run for a very long time if any of the X blocks are decrypted incorrectly. This means that it is better to X leave a position blank than to guess at it. X X 22. The program moves to block 4 and shows you the characters in block 4 X that would be deduced from block 3 given the deduced wirings of zee. X If these look reasonable, press F3 to accept the guess, and press F2 X to try the next guess. To reject a guess, press F2 without pressing X F3. X X 23. Now that part of zee is known, try propagating the settings of block X 1 into block 0 using zee. The propagate command will do this. Also X try propagating blocks 2, 3, and 4 to zero. X X Notice that the number of known wires can increase without deducing X additional characters in the block. X X 24. There should be a command that propagates information between groups X of blocks, but for now you must do this one block at a time. After X propagating block 1 - 4 to block zero, and block zero to blocks 1 - X 4, et cetera, try the knit command again. X X 25. Propagate block 4 to 5 to provide a framework to evaluate new X guesses. X X 26. Knit block 0 through 4 with a minimum show level of 2. You may want X to skip accepting guesses that do not deduce any characters. Repeat X this process with a show level of 1. X X 27. The program should now know all 256 wirings of zee. Repeat the X process of propagating information between blocks until all 128 X wires of the block zero are known. X X 28. Save your work with the save-permutations command (on the command X line type 'sa ' and press return). This writes the file foo.perm. X X 29. Exit the program with the quit command. X X 30. Copy foo.perm to zeecode.perm. X X 31. Execute 'zeecode < foo.cipher | more '. This program reads CBW's X save file to find the permutation for block zero and the Zee X permutation that describes how the remaining block keys are X generated. Using this information it decodes standard input and X writes on standard output. X X 32. That's all. END_OF_Read.me if test 9793 -ne `wc -c <Read.me`; then echo shar: \"Read.me\" unpacked with wrong size! fi # end of overwriting check fi if test -f cipher.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"cipher.c\" else echo shar: Extracting \"cipher.c\" \(9641 characters\) sed "s/^X//" >cipher.c <<'END_OF_cipher.c' X/* X * Routines for operating on cipher blocks. X * X * Robert W. Baldwin, January 1985. X */ 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 DEBUG FALSE X X X/* Decode the cblock into pblock using perm. X * Return FALSE if find a non-ascii character, else 1. X */ Xdecode(cblock, pblock, perm) Xchar cblock[]; Xint pblock[]; Xint perm[]; X{ Xint iplace; /* Index into ciphertext block. */ Xint spchar; /* Plaintext char not unshifted. */ Xint pchar; /* Plaintext char. */ Xint good; /* Plaintext doesn't have any unacceptable chars in it. */ X Xgood = TRUE; Xfor (iplace = 0 ; iplace < BLOCKSIZE ; iplace++) { X spchar = perm[(iplace+cblock[iplace])&MODMASK]; X if (spchar == -1) { X pchar = -1; X } X else { X pchar = (spchar-iplace) & MODMASK; X if (notascii(pchar)) { X good = FALSE; X } X } X pblock[iplace] = pchar; X } Xreturn(good); X} X X X/* Searches for string in block. X * Returns position it found that didn't have conflicts, or -1. X * If found, it will add to perm all the deduced wirings. X * If perm is not initially all -1, search will not accept any X * position that conflicts with the initial wirings, nor will X * it mutate any of those wirings. X */ Xint search(cipher, perm, initpos, thing) Xchar *cipher; Xint *perm; Xint initpos; Xchar *thing; /* NULL terminated string. */ X{ X int iplace; /* Current placement of trigram in plaintext block. */ X int i; /* Index for initializing arrays. */ X int pchar; /* Plaintext character. */ X int spchar; /* Plaintext character cyclically shifted by its pos. */ X int *spstkp; X int spstack[BLOCKSIZE]; X int *scstkp; X int scstack[BLOCKSIZE]; X int scchar; /* Ciphertext character cyclically shifted by its pos. */ X int offset; X int thinglen; X char *p; X X p = thing; X for (thinglen = 0 ; *p++ != 0 ; thinglen++) ; X X for (iplace = initpos ; iplace < BLOCKSIZE-thinglen ; iplace++) { X spstkp = spstack; X scstkp = scstack; X for (offset = 0 ; offset < thinglen ; offset++) { X pchar = ((int) thing[offset]); X spchar = (pchar + iplace + offset) & MODMASK; X scchar = (cipher[iplace + offset] + iplace + offset) & MODMASK; X if ((perm[spchar] != -1 || perm[scchar] != -1) X && (perm[spchar] != scchar)) { X while (spstkp > &spstack[0]) perm[*(--spstkp)] = -1; X while (scstkp > &scstack[0]) perm[*(--scstkp)] = -1; X goto nextplace; X } X perm[spchar] = scchar; X *spstkp++ = spchar; X perm[scchar] = spchar; X *scstkp++ = scchar; X } X return(iplace); X nextplace: ; X } X return(-1); X} X X X/* Fill in the pvec with the characters decoded from assuming X * that the ciphertext character at position firstpos maps to X * the plaintext character firstplain. X * Return the number of characters added to pvec not counting X * the termination character (NONE) that we always add. X * If any of the characers decoded to non-ascii values, then X * return ERROR (a negative number). X * Also return ERROR if the guess would conflict with the ones already X * in eci->perm. X */ Xint decode_class(eci, firstpos, firstplain, pvec) Xecinfo *eci; Xint firstpos; Xint firstplain; Xint *pvec; X{ X int x,y; X X firstpos = MODMASK & firstpos; X firstplain = CHARMASK & firstplain; X X x = eci->scipher[firstpos]; X y = MODMASK & (firstplain + firstpos); X X return(decode_wire(eci, x, y, pvec)); X} X X X/* Fill in the pvec with the characters decoded from assuming X * that the permutation for this block maps x to y and vice-versa. X * Return the number of characters added to pvec not counting X * the termination character (NONE) that we always add (but not if X * we return ERROR). X * If any of the characers decoded to non-ascii values, then X * return ERROR (a negative number). X * Also return ERROR if the guess would conflict with the ones already X * in eci->perm. X * Also return ERROR if x == y. X */ Xint decode_wire(eci, x, y, pvec) Xecinfo *eci; Xint x; Xint y; Xint *pvec; X{ X decode_wire_but(eci, x, y, pvec, NONE, NONE); X} X X X/* Fill in the pvec with the characters decoded from assuming X * that the permutation for this block maps x to y and vice-versa. X * Return the number of characters added to pvec not counting X * the termination character (NONE) that we always add (but not if X * we return ERROR). X * If any of the characers decoded to non-ascii values, then X * return ERROR (a negative number). X * Also return ERROR if the guess would conflict with the ones already X * in eci->perm. X * Also return ERROR if x == y. X * DO NOT include any characters in the postions ranging from X * first to last inclusive. X */ Xint decode_wire_but(eci, x, y, pvec, first, last) Xecinfo *eci; Xint x; Xint y; Xint *pvec; Xint first, last; X{ X int delta; X int pos, firstflag; X int c,i; X int firstpos; X int otherpos; X int pvecindex; X X X pvecindex = 0; X pvec[pvecindex] = NONE; X x = x & MODMASK; X y = y & MODMASK; X if (first > last) { X printf("\ndecode_wire_but called with first > last.\n"); X exit(0); X } X X if (perm_conflict(eci->perm,x,y) || x == y) { X#if DEBUG X printf("CANNOT accept the guess of %d wired to %d.\n", X x, y); X#endif X return(ERROR); X } X X firstpos = eci->permmap[x]; X if (firstpos != NONE) { X delta = y - x; X for_pos_in_class(pos, firstpos) { X if (first <= pos && pos <= last) continue; X c = MODMASK & (eci->scipher[pos] + delta - pos); X if (c != (c & CHARMASK)) return(ERROR); X pvec[pvecindex++] = c; X } X } X X otherpos = eci->permmap[y]; X if (otherpos != NONE) { X delta = x - y; X for_pos_in_class(pos, otherpos) { X if (first <= pos && pos <= last) continue; X c = MODMASK & (eci->scipher[pos] + delta - pos); X if (c != (c & CHARMASK)) return(ERROR); X pvec[pvecindex++] = c; X } X } X X pvec[pvecindex] = NONE; X return(pvecindex); X} X X X X/* Fill in an interger buffer from the characters of a byte buffer. X * The buffers must have equal lengths. X */ Xchar2buf(cptr, iptr, length) Xchar *cptr; Xint *iptr; Xint length; X{ X int i; X X for (i = 0 ; i < length ; i++) { X *iptr++ = MODMASK & (*cptr++); X } X} X X X/* Fill in a character buffer from the integers of a byte buffer. X * If the integer value is NONE, use nonechar instead. X * The buffers must have equal lengths. X */ Xbuf2char(cptr, iptr, length, nonechar) Xchar *cptr; Xint *iptr; Xint length; Xint nonechar; X{ X int i; X X for (i = 0 ; i < length ; i++) { X if (*iptr != NONE) { X *cptr++ = MODMASK & (*iptr++); X } X else { X *cptr++ = nonechar; X } X } X} X X X X/* Fill in an interger vector with the characters from a null X * terminated string. The interger vector is terminated by the X * value NONE. X */ Xstr2pvec(cptr, iptr) Xchar *cptr; Xint *iptr; X{ X while (*iptr++ = (MODMASK & *cptr++)); X *(--iptr) = NONE; X} X X X/* Fill in a null terminated string with the integers from a NONE X * terminated vector. X */ Xpvec2str(cptr, iptr) Xchar *cptr; Xint *iptr; X{ X while (*iptr != NONE) { X *cptr++ = (MODMASK & *iptr++); X } X *cptr = 0; X} X X X/* Print a pvec on a stream. X */ Xprint_pvec(out, pvec) XFILE *out; Xint *pvec; X{ X int i,c; X X i = 0; X while (*pvec != NONE) { X c = *pvec++; X if (i++ % 20 == 0) fprintf(out,"\n"); X write_char(out, c); X } X fprintf(out,"\n"); X} X X X/* Returns number of wires added to permvec assuming X * that plaintext str occurs at pos. X * Fills in permvec. Returns -1 if conflict. X * Note that the last entry in permvec is marked by x == -1. X * The permvec will not have duplicates and will not conflict X * with the perm specified by eci->perm. X */ Xint permvec_from_string(eci, str, pos, permvec) Xecinfo *eci; Xchar *str; Xint pos; Xperment permvec[]; X{ X int wcount; X int i, c, tmp; X int x,y; X char *cp; X int curpos; X X if (pos < 0 || pos >= BLOCKSIZE) {return(ERROR);} X X wcount = 0; X curpos = pos; X cp = str; X while ((c = (*cp & MODMASK)) != 0 && (curpos < BLOCKSIZE)) { X x = eci->scipher[curpos]; X y = MODMASK & (c + curpos); X if (perm_conflict(eci->perm, x, y)) { X permvec[0].x = NONE; X return(ERROR); X } X for (i = 0 ; i < wcount ; i++) { X if ( (permvec[i].x == x && permvec[i].y != y) X || (permvec[i].x == y && permvec[i].y != x) X || (permvec[i].y == x && permvec[i].x != y) X || (permvec[i].y == y && permvec[i].x != x) ) { X#if DEBUG X printf("Conflict within permvec.\n"); X#endif X permvec[0].x = NONE; X return(ERROR); X } X if ( (permvec[i].x == x && permvec[i].y == y) X || (permvec[i].x == y && permvec[i].y == x) ) X break; X } X permvec[i].x = x; X permvec[i].y = y; X if (i >= wcount) wcount++; X curpos++; X cp++; X } X X permvec[wcount].x = NONE; X return(wcount); X} X X X X/* Copy routine for permvecs. X */ Xpermvec_copy(from, to, maxnum) Xperment from[]; Xperment to[]; Xint maxnum; X{ X int i; X X for (i = 0 ; i < maxnum ; i++) { X to[i] = from[i]; X if (from[i].x == NONE) break; X } X} X X X/* Copy routine for pvecs. X */ Xpvec_copy(from, to, maxnum) Xint from[]; Xint to[]; Xint maxnum; X{ X int i; X X for (i = 0 ; i < maxnum ; i++) { X to[i] = from[i]; X if (from[i] == NONE) break; X } X} X X X X/* Fills in pvec with the plaintext characters deduced X * from the wires in permvec that are not in the positions X * ranging from butfirst to butlast. Returns -1 if any X * non-ascii chars are deduced, else count of chars. X */ Xint permvec2pvec(eci, permvec, pvec, butfirst, butlast) Xecinfo *eci; Xperment permvec[]; Xint pvec[]; Xint butfirst; Xint butlast; X{ int i, x, y; X int ccount; X int added; X X ccount = 0; X X for (i = 0 ; permvec[i].x != NONE ; i++) { X if (ccount >= BLOCKSIZE-1) break; X x = permvec[i].x; X y = permvec[i].y; X added = decode_wire_but(eci, x, y, &(pvec[ccount]), butfirst, butlast); X if (added < 0) { X#if DEBUG X printf("permvec wire decodes to non-ascii.\n"); X#endif X pvec[0] = -1; X return(ERROR); X } X ccount += added; X } X pvec[ccount] = -1; X return(ccount); X} END_OF_cipher.c if test 9641 -ne `wc -c <cipher.c`; then echo shar: \"cipher.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f eclass.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"eclass.c\" else echo shar: Extracting \"eclass.c\" \(9192 characters\) sed "s/^X//" >eclass.c <<'END_OF_eclass.c' X/* X * Equivalence class information about a cipher block. X * X * Bob Baldwin, January 1985. X */ X X#include <stdio.h> X#include <math.h> X#include "window.h" X#include "terminal.h" X#include "layout.h" X#include "specs.h" X#include "cipher.h" X X X#define DEBUG FALSE X X#define MIN_SHOW_SCORE (0.7) X#define ECBLABEL1 "Equiv class guessing at level %6.3f -- Please Wait" X#define ECBLABEL2 "Equiv class guessing at level %6.3f -- Done" X#define ECBHELP "F3 enters guess, ^G undoes it." X X Xextern char mcbuf[]; Xextern ecinfo gecinfo; Xextern ecbdraw(), ecbfirst(), ecbenter(), ecbundo(); X X/* Gloabal State. */ Xfloat ec_accept_level = 0.0; Xkeyer ecbktab[] = { X {CACCEPT, ecbenter}, X {CUNDO, ecbundo}, X {CGO_UP, jogup}, X {CGO_DOWN, jogdown}, X {CGO_LEFT, jogleft}, X {CGO_RIGHT, jogright}, X {0, NULL}, X}; X X X/* Routine invoked by user to put up the equivalence class X * guessing window. X * The window is drawn empty, and then filled in with the guess. X * Return NULL if command completes ok. X */ Xchar *ecbguess(str) Xchar *str; /* Command line */ X{ X ecinfo *ecbi; X int i; X gwindow *ecb; X X ecb = &gbstore; X ecbi = &gecinfo; X ec_init(mcbuf, refperm(dbsgetblk(&dbstore)), ecbi); X X if ((i = sscanf(str, "%*[^:]: %f", &ec_accept_level)) != 1) { X return("Could not parse acceptance level."); X } X X gbsswitch(ecb, ((char *) ecbi), ecbktab, ecbfirst, wl_noop, ecbdraw); X X sprintf(statmsg, ECBLABEL1, ec_accept_level); X gblset(&gblabel, statmsg); X X ecbdraw(ecb); X fflush(stdout); X X ec_autoguess(ecbi, ec_accept_level); X decode(ecbi->ciphertext, ecbi->plaintext, ecbi->perm); X X sprintf(statmsg, ECBLABEL2, ec_accept_level); X gblset(&gblabel, statmsg); X ecbdraw(ecb); X X return(NULL); X} X X X/* (re) Draw the window. X */ Xecbdraw(ecb) Xgwindow *ecb; X{ X int i; X int row, col; X ecinfo *ecbi; X X ecbi = ((ecinfo *) ecb->wprivate); X row = 1; X col = 1; X X for (i = 0 ; i < BLOCKSIZE ; i++) { X if (i%LINELEN == 0) { X wl_setcur(ecb, gbspos2row(i), gbspos2col(i)); X } X plnchars(1, char2sym(ecbi->plaintext[i])); X } X X for (i = gbspos2row(BLOCKSIZE) ; i <= GBHEIGHT ; i++) { X wl_setcur(ecb, i, 1); X plnchars(LINELEN, ' '); X } X X for (i = 1 ; i <= GBHEIGHT ; i++) { X wl_setcur(ecb, i, LINELEN+1); X plnchars(ecb->wwidth - LINELEN, ' '); X } X X wl_setcur(ecb, row, col); X} X X X/* First time cursor enters window. X */ Xecbfirst(ecb, row, col) Xgwindow *ecb; Xint row, col; X{ X usrhelp(&user, ECBHELP); X wl_setcur(ecb, row, col); X} X X X/* Enter the guess into the decryption block. X */ Xecbenter(ecb) Xgwindow *ecb; X{ X ecinfo *ecbi; X X ecbi = ((ecinfo *) ecb->wprivate); X dbsmerge(&dbstore, ecbi->perm); X wl_rcursor(ecb); X} X X X/* Undo the last guess. X */ Xecbundo(ecb) Xgwindow *ecb; X{ X ecinfo *ecbi; X X ecbi = ((ecinfo *) ecb->wprivate); X dbsundo(&dbstore); X wl_rcursor(ecb); X} X X X X X/* Dump plaintext chars onto stream. X */ Xec_dplain(out, eci) XFILE *out; Xecinfo *eci; X{ X int i,c; X int *pbuf; X X pbuf = &eci->plaintext[0]; X for (i = 0 ; i < BLOCKSIZE ; i++) { X c = *pbuf++; X if (i % 20 == 0) fprintf(out,"\n"); X if (c != NONE) X write_char(out, c); X else X write_char(out, '.'); X } X fprintf(out,"\n"); X} X X X/* Dump shifted cipher chars onto stream. X */ Xec_dscipher(out, eci) XFILE *out; Xecinfo *eci; X{ X int i,c; X int *pbuf; X X pbuf = &eci->scipher[0]; X for (i = 0 ; i < BLOCKSIZE ; i++) { X c = *pbuf++; X if (i++ % 20 == 0) fprintf(out,"\n"); X if (c != NONE) X write_char(out, c); X else X write_char(out, '.'); X } X fprintf(out,"\n"); X} X X X/* Dump table of next pointers onto a stream. X */ Xec_dnext(out, eci) XFILE *out; Xecinfo *eci; X{ X writeperm(out, &(eci->next[0])); X} X X X/* Dump size table onto a stream. X */ Xec_dsizetab(out, eci) XFILE *out; Xecinfo *eci; X{ X int i; X X fprintf(out, "\nThere are %d classes longer than 1 character.\n", X eci->sizelast); X for (i = 0 ; i < eci->sizelast ; i++) { X fprintf(out, "Size: %d, First member: %d.\n", X eci->sizelist[i].size, eci->sizelist[i].firstpos); X } X} X X X/* Dump our permutation onto a stream. X */ Xec_dperm(out, eci) XFILE *out; Xecinfo *eci; X{ X writeperm(out, &(eci->perm[0])); X} X X X/* Dump the permutation map onto a stream. X */ Xec_dpmap(out, eci) XFILE *out; Xecinfo *eci; X{ X writeperm(out, &(eci->permmap[0])); X} X X X X/* Update ecbi to reflect the automatic guesses. X */ Xec_autoguess(ecbi, alevel) Xecinfo *ecbi; Xfloat alevel; X{ int i, c; X int classpos; X int x, y; X X for (i = 0 ; i < ecbi->sizelast ; i++) { X classpos = ecbi->sizelist[i].firstpos; X c = ec_best(ecbi, classpos, alevel); X if (c != NONE) { X x = ecbi->scipher[classpos]; X y = MODMASK & (c + classpos); X if (!perm_conflict(ecbi->perm, x, y)) { X ecbi->perm[x] = y; X ecbi->perm[y] = x; X } X#if DEBUG X else { X printf("ec_autoguess: Best guess conflicts"); X printf(" with an accepted.\n"); X } X#endif X } X } X} X X X/* Score a single equivalence class. X * Bigger scores are better scores. They range from 0 to 1. X * A score of zero means the choice is not possible. X */ Xfloat ec_cscore(eci, firstpos, plainchar) Xecinfo *eci; Xint firstpos; Xint plainchar; X{ X extern float logvar; X float score; X int pvec[BLOCKSIZE+1]; X int ccount; X char str[BLOCKSIZE+1]; X X X if (decode_class(eci, firstpos, plainchar, pvec) == ERROR) { X return(0.0); X } X X score = pvec_1score(pvec); X if (score < 0.0) return(0.0); X score = exp(-(score * score) / 2.0); X for (ccount = 0 ; pvec[ccount] != NONE ; ccount++); X score = score / sqrt(2*PI*logvar/ccount); X X#if DEBUG X if (score > MIN_SHOW_SCORE) { X pvec2str(str, pvec); X printf("Derived characters are '%s", str); X printf("', their score is %7.4f\n", score); X } X#endif X return(score); X} X X X/* Select best plaintext value for a ciphertext equiv class. X * The class is identified by the position in the block of one X * of the characters in the class. The plaintext value for X * an entire class can be specified by the plaintext value of X * one of its members. This routine returns the best plaintext X * value for the ciphertext character at position firstpos. X * If there is not a clear best value, NONE is returned. X */ Xint ec_best(eci, firstpos, alevel) Xecinfo *eci; Xint firstpos; Xfloat alevel; X{ X float total_score, score; X float best_score; X int best_char; X int c; X int x,y; X float count; X X#if DEBUG X int pvec[BLOCKSIZE+1]; X char str[BLOCKSIZE+1]; X X printf("\n"); X printf("The first position of this class is %d.\n", firstpos); X#endif X total_score = 0.0; X best_score = 0.0; X count = 0.0; X best_char = NONE; X X for (c = 0 ; c <= MAXCHAR ; c++) { X score = ec_cscore(eci, firstpos, c); X if (score > 0.0) { X count += 1.0; X total_score += score; X } X if (score > best_score) { X best_score = score; X best_char = c; X } X } X X#if DEBUG X printf("Total score is %7.4f", total_score); X printf(". Count is %4.0f.\n", count); X#endif X if (total_score == 0.0 || count == 0.0 || best_char == NONE) { X#if DEBUG X printf("NO GUESSES\n"); X#endif X return(NONE); X } X#if DEBUG X printf("Best score is %7.4f", best_score); X printf(", which is %7.4f fraction of total", best_score/total_score); X printf(".\n"); X X decode_class(eci, firstpos, best_char, pvec); X pvec2str(str, pvec); X printf("The best chars are '%s.\n", str); X#endif X X if (best_score > alevel * (total_score - best_score)) { X return(best_char); X } X else { X return(NONE); X } X} X X X/* Fill in equiv class info from given ciphertext block X * and permutation. X */ Xec_init(cipher, perm, eci) Xchar cipher[]; Xint perm[]; Xecinfo *eci; X{ X int i,j; X int lastmember; X int firstpos, size; X X eci->sizelast = 0; X eci->sizemin = 2; X for (i = 0 ; i < BLOCKSIZE ; i++) { X eci->ciphertext[i] = cipher[i]; X eci->scipher[i] = (cipher[i] + i)&MODMASK; X eci->perm[i] = perm[i]; X eci->permmap[i] = NONE; X } X decode(eci->ciphertext, eci->plaintext, eci->perm); X X X /* The permmap points to the most recent member we have seen */ X /* of each known class, or a NONE. Ptrs are array indexes. */ X for (i = BLOCKSIZE-1 ; i >= 0 ; i--) { X eci->next[i] = i; X if ((lastmember = eci->permmap[eci->scipher[i]]) != NONE) { X eci->next[i] = eci->next[lastmember]; X eci->next[lastmember] = i; X } X eci->permmap[eci->scipher[i]] = i; X } X X for (i = 0 ; i < BLOCKSIZE ; i++) { X firstpos = eci->permmap[i]; X if (firstpos != NONE) { X size = ec_compsize(eci, firstpos); X ec_addsize(eci, size, firstpos); X } X } X} X X X/* Add an entry to the size list. X * Implementation: Find the first slot before sizelast+1 that X * has a size less than the size arg. Shuffle down the list X * to create a hole and insert the new entry. X */ Xec_addsize(eci, size, firstmember) Xregister ecinfo *eci; Xint size; Xint firstmember; X{ X int k; /* Slot where new entry will go. */ X int i; X ecsize sizeinfo; X X if (size < eci->sizemin) return; X X sizeinfo.size = size; X sizeinfo.firstpos = firstmember; X for (k = 0 ; k < eci->sizelast ; k++) { X if (eci->sizelist[k].size < size) break; X } X if (k >= SZMAX) return; X X for (i = eci->sizelast ; i > k ; i--) { X eci->sizelist[i] = eci->sizelist[i-1]; X } X eci->sizelast++; X X eci->sizelist[k] = sizeinfo; X} X X X/* Compute the size of a clas given a pointer to one of its members. X */ Xint ec_compsize(eci, member) Xecinfo *eci; Xint member; X{ X int size; X int position; X int firstflag; X X size = 0; X for_pos_in_class(position, member) { X size++; X } X return(size); X} END_OF_eclass.c if test 9192 -ne `wc -c <eclass.c`; then echo shar: \"eclass.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f knit.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"knit.c\" else echo shar: Extracting \"knit.c\" \(10707 characters\) sed "s/^X//" >knit.c <<'END_OF_knit.c' X/* X * Use serveral mostly solved blocks to solve the knitting equation X * and deduce the rotor and reflector wirings. 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 Xextern char gcbuf[]; /* All guess displays use same buffers. */ Xextern int gpbuf[]; Xextern int gperm[]; X X X#define KNTHELP "F2 = next guess, F3 = enter guess, ^G = Undo enter." X#define STARTMSG "Knitting from %d to %d. Known Zee: %d of 256." X#define GUESSMSG "guesscount = %d, xi=%d, yi=%d. Known Zee: %d of 256." X#define UNDOMSG "Undone. Current known Zee: %d of 256" X#define BIG 1000 /* Size of try stack in kntadvance(). */ X X X/* Pack and unpack two bytes into an integer. */ X#define pack(x,y) (((x&0377)<<8) + y) X#define unpack(x,y,v) tmpv = v; x = ((tmpv>>8)&0377); y = (tmpv&0377); X X X/* Keystroke handler table. */ X Xextern int kntadvance(); Xextern kntundo(); Xextern kntnextg(); Xextern kntenter(); X Xkeyer kntktab[] = { X {CNEXTGUESS, kntnextg}, X {CACCEPT, kntenter}, X {CUNDO, kntundo}, X {CGO_UP, jogup}, X {CGO_DOWN, jogdown}, X {CGO_LEFT, jogleft}, X {CGO_RIGHT, jogright}, X {0, NULL}, X}; X X X X/* Private data structure for guess blocks. */ X X#define kntinfo struct xkntinfo Xstruct xkntinfo { X char *cbuf; /* The cipher block. */ X int *pbuf; /* The derived guess plaintext, -1 = none. */ X int *perm; /* Permutation of block highbnum+1. */ X int xindex; /* Starting position of next x guess. */ X int yindex; /* Starting position of next y guess. */ X int *zee; /* Knitting matrix. */ X int *zeeinv; /* Its inverse. */ X int *ustkp; /* Undo stack pointer. */ X int *savedustkp; /* Undo stack pointer. */ X int *undostk; /* Undo stack. */ X int lowbnum; /* Block number of lowest source. */ X int highbnum; /* Block number of highest source. */ X int min_show; /* Smallest count to show. */ X }; X X X/* Private buffers. */ Xint kzee[BLOCKSIZE+1]; Xint kzeeinv[BLOCKSIZE+1]; Xint kustk[BLOCKSIZE+1]; X Xkntinfo kntprivate; X Xint kntinit = FALSE; X X Xextern kntdraw(), kntfirst(); /* Defined below. */ X X X/* This routine is called by the user command to clear the zee matrix. X */ Xchar *clearzee(str) Xchar *str; /* Command line */ X{ X int i; X kntinfo *knti; X X knti = &kntprivate; X initknt(); X kntclrzee(knti); X X if (&kntprivate == ((kntinfo *) gbstore.wprivate)) { X for (i = 0 ; i < BLOCKSIZE ; i++) { X knti->perm[i] = -1; X } X decode(knti->cbuf, knti->pbuf, knti->perm); X sprintf(statmsg, GUESSMSG, X 0, knti->xindex, knti->yindex, zeecount(knti)); X gblset(&gblabel, statmsg); X wl_draw(&gbstore); X } X X wl_rcursor(&user); X return(NULL); X} X X X X/* This routine is called to set up the guess block window X * to be used for guessing the zee matrix. X * It can be directly invoked by the command interpreter. X * Set up dbstore to show the block after the last block X * the the user says to consider complete. X */ Xchar *kntguess(str) Xchar *str; /* Command line */ X{ X int i; X int from,to; X gwindow *knt; X kntinfo *knti; X X knt = &gbstore; X knti = &kntprivate; X initknt(); X X if (!kntinit) { X kntinit = TRUE; X kntclrzee(knti); X } X X for (i = 0 ; i < BLOCKSIZE ; i++) { X knti->perm[i] = -1; X } X X from = to = 0; X if ((i = sscanf(str,"%*[^:]: %d %*[^:]: %d %*[^:]: %d", X &from, &to, &knti->min_show)) != 3) { X return("Could not parse all arguments."); X } X else { X if (to <= from) X return("To: must be less than From:"); X } X X dbssetblk(&dbstore, to+1); X if (!fillcbuf(to+1, knti->cbuf)) { X return("Bad to: value"); X } X decode(knti->cbuf, knti->pbuf, knti->perm); X knti->xindex = 0; X knti->yindex = 0; X knti->lowbnum = from; X knti->highbnum = to; X X gbsswitch(knt,((char *) knti), kntktab, kntfirst, wl_noop, kntdraw); X sprintf(statmsg, STARTMSG, from, to, zeecount(knti)); X gblset(&gblabel, statmsg); X kntdraw(knt); X X wl_setcur(knt, 1, 1); X return(NULL); X} X X X X/* Clear the zee permutation and update any display info. X */ Xkntclrzee(knti) Xkntinfo *knti; X{ X int i; X X for (i = 0 ; i < BLOCKSIZE ; i++) { X knti->zee[i] = -1; X knti->zeeinv[i] = -1; X } X} X X X/* Compute the next successful guess of a wiring of ZEE. X * Show it to the user for acceptance/rejection. X */ Xkntnextg(knt) Xgwindow *knt; X{ X int guesscnt; X kntinfo *knti; X knti = ((kntinfo *) knt->wprivate); X X kntclrlast(knti); X while (TRUE) { X guesscnt = kntadvance(knti); X if ((guesscnt == 0) || (guesscnt >= knti->min_show)) break; X kntclrlast(knti); X } X if (guesscnt == 0) { X gblset(&gblabel, "No more guesses"); X return; X } X decode(knti->cbuf, knti->pbuf, knti->perm); X X sprintf(statmsg, GUESSMSG, X guesscnt, knti->xindex, knti->yindex, zeecount(knti)); X gblset(&gblabel, statmsg); X kntdraw(knt); X} X X X X/* Clear last guess in zee, zeeinv, perm. X * Note that perm only holds the results of the last guess. X */ Xkntclrlast(knti) Xkntinfo *knti; X{ X int tmpv; /* For unpack. */ X int x,y; X int i; X X while (knti->ustkp > knti->undostk) { X unpack(x, y, *(--(knti->ustkp))); X knti->zee[x] = -1; X knti->zeeinv[y] = -1; X } X knti->ustkp = knti->savedustkp = knti->undostk; X X for (i = 0 ; i < BLOCKSIZE ; i++) { X knti->perm[i] = -1; X } X} X X X X/* Advance to the next acceptable guess at a wiring for Zee. X * This modifies zee, zeeinv, and perm. Perm only contains the X * info derived from this guess, while zee and zeeinv accumulate X * information from all preceeding accepted guesses. X * Returns the number of guesses that we derived from the initial one. X * If out of acceptable guesses, returns 0. X * Perm must be cleared before calling this. X */ Xint kntadvance(knti) Xkntinfo *knti; X{ X int guesscount; X int i; X int tmpv; /* For unpack. */ X int x,y; X int tx,ty; X int u,v; X int tu,tv; X int *a2; /* The permutation as in u = A2 x */ X int *a1; /* The permutation as in v = A1 y */ X int *propp; /* Temp for undo stack propagation. */ X int *highperm; /* Perm used to derive next perm. */ X int trycount; /* Size of trystk. */ X int *tstkp; /* Stack of guesses to check. */ X int trystk[BIG]; X X/* kntadvance(knti) X */ X guesscount = 0; /* In case loop body never executes. */ X X if (knti->xindex >= BLOCKSIZE) return(0); X if (knti->yindex >= BLOCKSIZE) { X knti->yindex = 0; X knti->xindex++; X } X X for (x = knti->xindex ; x < BLOCKSIZE ; x++) { X if (knti->zee[x] != -1) { X knti->yindex = 0; X continue; X } X for (y = knti->yindex ; y < BLOCKSIZE ; y++) { X if (knti->zeeinv[y] != -1) continue; X guesscount = 0; X tstkp = trystk; /* Assume ustkp == undostk. */ X trycount = 0; X *(tstkp++) = pack(x,y); X trycount++; X X while (tstkp > trystk) { X unpack(tx, ty, *(--tstkp)); X trycount--; X if (knti->zee[tx] == -1 && knti->zeeinv[ty] == -1) { X knti->zee[tx] = ty; X knti->zeeinv[ty] = tx; X *((knti->ustkp)++) = pack(tx,ty); X guesscount++; X for (i = knti->lowbnum ; (i+1) <= knti->highbnum ; i++) { X a1 = refperm(i); X a2 = refperm(i+1); X tu = a2[tx]; X tv = a1[ty]; X if (tu != -1 && tv != -1 && trycount < BIG) { X *(tstkp++) = pack(tu, tv); X trycount++; X } X } X } X else if (knti->zee[tx] != ty X || knti->zeeinv[ty] != tx) { /* If conflict. */ X while (knti->ustkp > knti->undostk) { X unpack(tx, ty, *(--(knti->ustkp))); X knti->zee[tx] = -1; X knti->zeeinv[ty] = -1; X guesscount--; X } X knti->ustkp = knti->undostk; X goto nxtguess; X } X else continue; /* Already know about it. */ X } X X knti->xindex = x; /* Zee[x] = y was a good guess. */ X knti->yindex = y+1; X propp = knti->ustkp; X highperm = refperm(knti->highbnum); X while (propp > knti->undostk) { /* Update perm. */ X unpack(tx, ty, *(--propp)); X v = highperm[ty]; X if (v != -1 && (tmpv = knti->zeeinv[v]) != -1) { X knti->perm[tx] = tmpv; X knti->perm[tmpv] = tx; X } X } X return (guesscount); X nxtguess: ; X } X knti->yindex = 0; X } X X knti->yindex = 0; X knti->xindex = 0; X return(guesscount); X} X X X/* Enter our current guess into the decryption block. X * Clear out the undo stack. X */ Xkntenter(knt) Xgwindow *knt; X{ X kntinfo *knti; X X knti = ((kntinfo *) knt->wprivate); X knti->savedustkp = knti->ustkp; /* If we change our mind. */ X knti->ustkp = knti->undostk; X if (knti->highbnum+1 != dbsgetblk(&dbstore)) X dbssetblk(&dbstore, knti->highbnum+1); X dbsmerge(&dbstore, knti->perm); X wl_rcursor(knt); X} X X X/* Undo the last guess. X */ Xkntundo(knt) Xgwindow *knt; X{ X kntinfo *knti; X X knti = ((kntinfo *) knt->wprivate); X knti->ustkp = knti->savedustkp; X kntclrlast(); X dbsundo(&dbstore); X X sprintf(statmsg, UNDOMSG, zeecount(knti)); X gblset(&gblabel, statmsg); X wl_rcursor(knt); X} X X X/* Behavior when first enter the window. X * Put up a help message. X * Accept the cursor where it is. X */ Xkntfirst(knt, row, col) Xgwindow *knt; Xint row,col; /* Current coordinates. */ X{ X usrhelp(&user, KNTHELP); X wl_setcur(knt, row, col); X} X X X X/* (re)Draw the window. X */ Xkntdraw(knt) Xgwindow *knt; X{ X int i; X int row, col; /* Original row and column. */ X kntinfo *knti; X X knti = ((kntinfo *) knt->wprivate); X row = knt->wcur_row; X col = knt->wcur_col; X X for (i = 0 ; i < BLOCKSIZE ; i++) { X if (i%LINELEN == 0) { X wl_setcur(knt, gbspos2row(i), gbspos2col(i)); X } X plnchars(1, char2sym(knti->pbuf[i])); X } X X for (i = gbspos2row(BLOCKSIZE) ; i <= GBHEIGHT ; i++) { X wl_setcur(knt, i, 1); X plnchars(LINELEN, ' '); X } X X for (i = 1 ; i <= GBHEIGHT ; i++) { X wl_setcur(knt, i, LINELEN+1); X plnchars(knt->wwidth - LINELEN, ' '); X } X X wl_setcur(knt, row, col); X} X X X/* Return number of known wires in Zee. X * Max is 256. X */ Xint zeecount(knti) Xkntinfo *knti; X{ X return(permcount(knti->zee)); X} X X X/* Store Zee permutation on a file. X */ Xstorezee(fd) XFILE *fd; X{ X writeperm(fd, kzee); X} X X X/* Load the Zee permutation from a file. X * Update display if necessary. X */ Xloadzee(fd) XFILE *fd; X{ X int i; X kntinfo *knti; X X knti = &kntprivate; X initknt(); X kntinit = TRUE; X kntclrzee(knti); /* Clear zeeinv */ X X readperm(fd, kzee); X for (i = 0 ; i < BLOCKSIZE ; i++) { X if (kzee[i] != -1) {kzeeinv[kzee[i]] = i;} X } X X if (knti == ((kntinfo *) gbstore.wprivate)) { X for (i = 0 ; i < BLOCKSIZE ; i++) { X knti->perm[i] = -1; X } X decode(knti->cbuf, knti->pbuf, knti->perm); X sprintf(statmsg, GUESSMSG, X 0, knti->xindex, knti->yindex, zeecount(knti)); X gblset(&gblabel, statmsg); X wl_draw(&gbstore); X wl_setcur(&gbstore, 1, 1); X } X} X X X/* Set up all the pointers in kntprivate. X */ Xinitknt() X{ X int i; X gwindow *knt; X kntinfo *knti; X X knt = &gbstore; X knti = &kntprivate; X X knti->zee = kzee; X knti->zeeinv = kzeeinv; X X knti->cbuf = gcbuf; X knti->pbuf = gpbuf; X knti->perm = gperm; X X knti->undostk = kustk; X knti->ustkp = knti->savedustkp = knti->undostk; X} END_OF_knit.c if test 10707 -ne `wc -c <knit.c`; then echo shar: \"knit.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f zeecode.perm -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"zeecode.perm\" else echo shar: Extracting \"zeecode.perm\" \(11550 characters\) sed "s/^X//" >zeecode.perm <<'END_OF_zeecode.perm' X 28 146 116 150 159 64 172 249 200 232 X 90 149 63 239 238 95 49 254 143 8 X191 231 123 117 243 210 179 186 119 17 X107 46 174 203 21 12 97 53 135 71 X 52 78 204 31 220 77 211 24 225 121 X 74 228 202 171 11 81 67 69 141 213 X 66 94 195 217 29 154 3 15 59 76 X205 155 25 93 209 160 212 36 173 68 X221 193 176 196 4 138 99 222 70 57 X 7 252 41 43 62 79 48 61 145 38 X 20 216 166 208 40 187 0 153 5 137 X 55 130 241 6 207 128 227 190 142 125 X177 75 226 105 2 175 51 120 96 13 X139 47 127 246 248 18 44 16 136 167 X132 113 151 98 244 114 182 198 201 189 X144 22 140 122 109 83 131 180 253 58 X162 50 250 134 37 1 35 242 23 214 X194 112 157 223 165 233 156 161 188 104 X124 103 54 234 89 80 101 26 19 85 X192 147 181 65 199 9 247 245 129 60 X169 102 32 88 224 106 235 45 236 84 X255 92 178 215 230 33 115 185 27 39 X237 251 30 14 163 126 219 87 206 73 X158 56 110 168 91 152 197 108 133 148 X 72 118 184 240 100 164 111 170 183 229 X 42 10 218 82 86 34 X 96 114 124 223 97 19 10 13 43 44 X 6 38 231 7 200 207 179 134 133 5 X100 230 48 160 152 93 162 168 191 127 X 65 103 183 90 252 193 243 242 11 180 X 87 173 154 8 9 99 112 58 22 108 X199 95 77 66 163 62 128 190 47 79 X215 109 55 245 73 30 53 178 214 82 X201 138 206 64 240 182 228 52 140 59 X197 248 69 203 175 111 137 40 153 139 X 33 195 212 25 217 51 0 4 251 45 X 20 122 148 31 227 234 167 202 49 61 X219 85 46 246 1 135 142 254 211 249 X144 255 101 218 2 150 186 29 56 169 X185 247 164 18 17 115 250 86 71 89 X 78 205 116 222 120 216 226 158 102 189 X125 225 24 88 42 159 221 188 147 155 X 23 210 26 54 132 232 184 106 27 129 X236 196 253 41 204 84 238 235 67 16 X 39 192 75 32 166 130 126 224 157 149 X 57 28 181 35 241 91 171 80 208 50 X 14 70 107 83 174 141 72 15 198 233 X161 118 92 244 68 60 145 94 123 110 X237 156 143 3 187 151 146 104 76 239 X 21 12 165 209 105 177 170 220 176 229 X 74 194 37 36 213 63 113 131 81 119 X136 98 34 172 117 121 X 20 122 118 119 71 229 158 28 223 174 X215 -1 197 249 82 126 237 23 87 93 X 0 35 252 17 77 177 137 225 7 163 X 52 171 42 155 214 21 84 60 216 85 X 45 152 32 181 220 40 241 235 142 210 X243 69 30 83 99 134 212 253 70 144 X 37 63 234 61 132 250 173 114 95 51 X 58 4 73 72 175 168 211 24 92 169 X176 166 14 53 36 39 207 18 148 117 X129 255 78 19 110 68 151 154 101 54 X244 98 242 147 227 204 128 203 188 254 X 94 217 170 251 67 231 -1 89 2 3 X206 146 1 183 -1 209 15 150 106 90 X184 159 64 141 55 238 195 26 162 205 X245 133 48 221 59 165 121 103 88 -1 X127 96 41 186 97 33 196 -1 6 131 X187 194 138 29 167 145 81 164 75 79 X112 31 178 66 9 74 80 25 172 -1 X -1 43 224 123 130 236 153 160 108 246 X192 230 190 222 161 136 156 12 200 213 X198 239 248 107 105 139 120 86 247 125 X 49 76 56 199 34 10 38 111 233 -1 X 44 143 193 8 182 27 232 104 240 5 X191 115 226 218 62 47 185 16 135 201 X228 46 102 50 100 140 189 208 202 13 X 65 113 22 57 109 91 X 90 49 26 132 156 140 212 129 147 122 X198 -1 97 148 38 79 25 154 80 173 X214 216 248 184 161 16 2 107 66 168 X 33 112 195 30 166 236 65 155 14 84 X222 211 123 53 136 47 69 45 218 1 X125 243 134 43 -1 102 145 126 238 194 X 78 232 138 246 224 36 28 225 150 46 X130 215 120 188 119 105 231 209 60 15 X 18 87 185 176 39 160 182 81 159 158 X 0 151 235 192 183 200 118 12 174 -1 X106 -1 55 196 207 75 100 27 249 187 X163 242 31 230 254 205 179 190 96 74 X 72 233 9 42 241 50 57 228 142 7 X 70 206 3 149 52 227 44 220 62 245 X 5 221 128 186 244 56 204 8 13 133 X 68 91 197 165 17 37 4 180 89 88 X 85 24 193 110 199 153 34 201 29 255 X177 247 226 19 98 252 83 170 237 116 X157 191 86 94 23 82 143 109 73 219 X117 181 93 162 59 32 103 152 10 164 X 95 167 250 239 146 115 131 104 217 77 X234 41 6 251 20 71 21 208 48 189 X137 141 40 253 64 67 172 135 127 240 X113 76 61 121 210 92 35 178 58 203 X229 124 111 51 144 139 63 171 22 108 X202 213 175 223 114 169 X 60 42 26 79 203 204 122 237 15 97 X106 238 133 33 159 8 165 145 27 191 X192 69 250 117 126 183 2 18 50 65 X218 57 143 13 101 36 35 93 116 213 X163 199 1 171 109 74 92 177 56 175 X 28 132 162 196 -1 227 48 31 80 221 X 0 248 202 103 233 29 140 95 170 21 X216 164 137 190 45 189 113 193 188 3 X 58 160 155 181 176 94 186 104 111 225 X198 125 46 37 85 67 252 9 231 223 X169 34 255 63 87 154 10 174 152 44 X201 88 -1 76 179 118 38 23 115 161 X247 123 6 121 187 91 24 240 241 239 X197 207 51 12 151 185 138 72 136 148 X 66 214 234 32 150 17 254 -1 139 226 X144 134 108 195 105 82 228 172 173 14 X 81 119 52 40 71 16 208 246 242 100 X 68 43 157 158 107 49 84 47 229 114 X -1 83 -1 25 230 135 86 124 78 75 X 73 19 20 77 245 153 53 130 90 41 X210 110 62 4 5 244 211 131 166 219 X200 206 220 39 141 222 70 253 30 209 X212 59 215 99 232 89 149 55 156 178 X184 98 224 64 142 236 235 7 11 129 X127 128 168 249 205 194 167 120 61 243 X 22 -1 96 217 146 102 X161 17 99 150 223 175 172 24 25 204 X147 122 181 198 54 56 125 1 202 67 X188 143 49 168 7 8 145 254 177 98 X 32 211 30 84 57 238 195 83 217 245 X160 178 108 89 76 81 228 225 184 22 X207 176 94 93 14 75 15 34 169 219 X152 189 107 158 193 123 95 19 80 141 X144 253 248 164 226 55 44 166 230 247 X 68 45 209 37 33 138 -1 213 101 43 X220 128 194 53 52 66 231 134 29 2 X190 88 103 102 224 180 199 62 42 240 X116 236 115 153 156 112 110 229 183 234 X131 149 11 65 187 16 140 196 91 215 X239 120 243 139 97 218 154 174 85 133 X126 69 163 21 70 26 182 10 232 121 X 3 162 60 113 136 192 114 171 63 185 X 40 0 151 142 73 250 77 233 23 58 X197 157 6 -1 137 5 51 28 41 227 X105 12 146 118 48 159 255 124 20 61 X100 -1 155 64 92 36 127 170 13 106 X244 210 18 246 9 251 208 50 206 82 X201 31 249 87 242 129 241 38 135 59 X 90 -1 252 4 104 47 74 179 46 117 X 78 96 148 167 119 237 111 235 35 130 X109 216 214 132 200 39 203 79 72 212 X165 205 222 71 27 186 X120 146 232 66 217 81 113 76 144 239 X 44 49 230 111 166 60 151 218 34 72 X 80 128 193 249 140 148 116 210 183 165 X 94 51 109 133 18 192 163 73 252 158 X 61 214 195 46 10 102 43 90 131 11 X122 31 135 172 153 207 188 58 57 227 X 15 40 77 99 143 138 3 231 226 136 X221 190 19 37 253 104 7 62 254 185 X 20 5 126 132 173 189 124 91 150 255 X 47 87 212 184 30 196 242 149 187 63 X178 112 45 228 75 180 177 141 125 32 X121 13 101 6 161 234 26 244 224 137 X 0 110 50 157 86 108 82 156 21 147 X238 48 83 33 240 52 69 119 65 175 X 24 107 160 64 8 176 1 129 25 97 X 88 16 225 54 243 164 127 123 39 200 X142 114 174 36 155 29 14 169 233 167 X211 216 53 84 162 139 145 106 100 204 X105 201 223 28 93 79 203 98 56 85 X 71 251 35 22 205 42 95 219 213 235 X159 181 222 186 179 194 220 55 246 215 X 27 170 92 198 41 209 171 4 17 197 X206 70 202 182 118 152 68 59 103 245 X 12 67 2 168 115 199 247 250 130 9 X134 248 96 154 117 229 208 236 241 23 X237 191 38 74 78 89 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 X -1 -1 -1 -1 -1 -1 END_OF_zeecode.perm if test 11550 -ne `wc -c <zeecode.perm`; then echo shar: \"zeecode.perm\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 5 \(of 11\). cp /dev/null ark5isdone 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. gazee[i