home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume10 / cbw / part03 / pword.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-16  |  5.3 KB  |  262 lines

  1. /*
  2.  * Automatic guessing based on probable words.
  3.  *
  4.  * Bob Baldwin, February 1985.
  5.  */
  6.  
  7. #include    <stdio.h>
  8. #include    <math.h>
  9. #include    "window.h"
  10. #include    "terminal.h"
  11. #include    "layout.h"
  12. #include    "specs.h"
  13. #include    "cipher.h"
  14. #include    "autotri.h"
  15.  
  16.  
  17. #define    DEBUG    FALSE
  18.  
  19. #define    NWORDS        100
  20. #define WDBUFSZ        (8*NWORDS)
  21. #define    WDPERMSZ    40
  22. #define    PWDLABEL1    "Probable word search -- Please Wait"
  23. #define    PWDLABEL2    "Probable word search -- Done"
  24. #define    PWDHELP        "F3 enters guess, ^G undoes it."
  25.  
  26.  
  27. extern    char    mcbuf[];
  28. extern    ecinfo    gecinfo;
  29. extern    atrinfo gatrinfo;
  30. extern    atrdraw(), atrfirst(), atrenter(), atrundo();
  31. extern    char    *pwd_init();
  32.  
  33. /* Gloabal State. */
  34. char    *word_tab[NWORDS];
  35. char    word_buf[WDBUFSZ];
  36.  
  37. keyer    pwdktab[] = {
  38.         {CACCEPT, atrenter},
  39.         {CUNDO, atrundo},
  40.         {CGO_UP, jogup},
  41.         {CGO_DOWN, jogdown},
  42.         {CGO_LEFT, jogleft},
  43.         {CGO_RIGHT, jogright},
  44.         {0, NULL},
  45. };
  46.  
  47. /* Routine invoked by user to search of a list of probable words.
  48.  * The window is drawn empty, and then filled in with the guess.
  49.  * Return NULL if command completes ok.
  50.  */
  51. char    *pwdguess(str)
  52. char    *str;            /* Command line */
  53. {
  54.     gwindow    *pwd;
  55.     atrinfo    *pwdi;
  56.     ecinfo    *ecbi;
  57.     int        *dbsperm;
  58.     float    max_score;
  59.     char    *errmsg;
  60.     int        i;
  61.     char    filename[MAXWIDTH+1];
  62.  
  63.     if ((i = sscanf(str, "%*[^:]: %s %*[^:]: %f",
  64.         filename, &max_score)) != 2)  {
  65.             return("Could not parse both arguments.");
  66.         }
  67.  
  68.     pwd = &gbstore;
  69.     pwdi = &gatrinfo;
  70.     dbsperm = refperm(dbsgetblk(&dbstore));
  71.     errmsg = pwd_init(filename, mcbuf, dbsperm, pwdi);
  72.     if (errmsg != NULL)  return(errmsg);
  73.  
  74.     ecbi = pwdi->eci;
  75.     pwdi->min_total_chars = 1;
  76.     pwdi->max_score = max_score;
  77.     pwdi->min_wire_chars = 0;
  78.  
  79.     gbsswitch(pwd, ((char *) pwdi), pwdktab, atrfirst, wl_noop, atrdraw);
  80.  
  81.     gblset(&gblabel, PWDLABEL1);
  82.     atrdraw(pwd);
  83.     fflush(stdout);
  84.  
  85.     pwd_autoguess(pwdi);
  86.     decode(ecbi->ciphertext, ecbi->plaintext, ecbi->perm);
  87.  
  88.     gblset(&gblabel, PWDLABEL2);
  89.     atrdraw(pwd);
  90.  
  91.     return(NULL);
  92. }
  93.  
  94.  
  95. /* Load a word table from the given file.
  96.  * Format is a word on each line terminated by a blank line
  97.  * Returns error message or NULL.
  98.  */
  99. char *wtab_load_from(filename, charbuf, buffree, wtab, tabsize)
  100. int        buffree, tabsize;
  101. char    *filename, *charbuf;
  102. char    *wtab[];
  103. {
  104.     FILE    *inp;
  105.     char    *wordstart;
  106.     int        wordindex, wordlength;
  107.     int        c;
  108.  
  109.     if ((inp = fopen(filename, "r"))== NULL)  {
  110.         return("Cannot open file to read probable words.");
  111.         }
  112.  
  113.     wordindex = 0;
  114.     while(wordindex < tabsize-1)  {
  115.         wordstart = charbuf;
  116.         wordlength = 0;
  117.         while ((c = read_char(inp)) != EOL) {
  118.             *charbuf++ = c;
  119.             wordlength++;
  120.             buffree--;
  121.             if (buffree <= 1)  break;
  122.             }
  123.         *charbuf++ = NULL;
  124.         buffree--;
  125.         if (wordlength == 0  ||  buffree <= 0)  break;
  126.         wtab[wordindex++] = wordstart;
  127.         }
  128.  
  129.     wtab[wordindex] = NULL;
  130.  
  131.     fclose(inp);
  132.     return(NULL);
  133. }
  134.  
  135.  
  136.  
  137. /* Fill in probable word info from given ciphertext block.
  138.  * The filter parameters are not set by this routine.
  139.  */
  140. char *pwd_init(filename, cipher, perm, pwdi)
  141. char    *filename;
  142. char    cipher[];
  143. int        perm[];
  144. atrinfo    *pwdi;
  145. {
  146.     int        i;
  147.     char    *errmsg;
  148.  
  149.     pwdi->eci = &gecinfo;
  150.     errmsg = wtab_load_from(filename, word_buf, WDBUFSZ, word_tab, NWORDS);
  151.     if (errmsg != NULL)  return(errmsg);
  152.     ec_init(cipher, perm, pwdi->eci);
  153.     pwd_guess_init(pwdi);
  154.     return(NULL);
  155. }
  156.  
  157.  
  158. /* Per guess initialization.
  159.  */
  160. pwd_guess_init(pwdi)
  161. atrinfo    *pwdi;
  162. {
  163.     pwdi->best_trigram = NULL;
  164.     pwdi->best_score = 10.0;
  165.     pwdi->gcount = 0;
  166.     pwdi->total_score = 0;
  167.     pwdi->best_pvec[0] = NONE;
  168.     pwdi->best_permvec[0].x = NONE;
  169. }
  170.  
  171.  
  172.  
  173. /* Score a word at a given position.
  174.  * Fills in permvec and pvec.
  175.  */
  176. float    pwd_score(pwdi, word, pos, permvec, pvec)
  177. atrinfo        *pwdi;
  178. char        *word;
  179. int            pos;
  180. perment        permvec[];
  181. int            pvec[];
  182. {
  183.     int        added, wordlen;
  184.     char    *p;
  185.     float    score;
  186.     ecinfo    *eci;
  187.  
  188.     p = word;
  189.     wordlen = 0;
  190.     while (*p++ != NULL)  wordlen++;
  191.     eci = pwdi->eci;
  192.     added = permvec_from_string(pwdi->eci, word, pos, permvec);
  193.     if (added == ERROR)  return(-1.0);
  194.     added = permvec2pvec(pwdi->eci, permvec, pvec, -1, -1);
  195.     if (added == ERROR)  return(-1.0);
  196.     if (added < pwdi->min_total_chars) {
  197.         return(-1.0);
  198.         }
  199.  
  200.     score = pvec_1score(pvec);
  201. #if DEBUG
  202.     print_pvec(stdout, pvec);
  203.     printf("Putting %s at %d, gets a score of %f\n",
  204.             word, pos, score);
  205. #endif
  206.     return(score);
  207. }
  208.  
  209.  
  210. /* Select the best probable word for a given position.
  211.  * Returns pointer to the word, or NULL.
  212.  * Fills in pwdi with additional information.
  213.  * Filtering parameters are passed in pwdi.
  214.  */
  215. char    *pwd_best(pwdi, pos)
  216. atrinfo    *pwdi;
  217. int        pos;
  218. {
  219.     int        windex;
  220.     float    score;
  221.     perment    permvec[WDPERMSZ];
  222.     int        pvec[BLOCKSIZE+1];
  223.  
  224.     pwd_guess_init(pwdi);
  225.  
  226.     for (windex = 0 ; word_tab[windex] != NULL ; windex++)  {
  227.         score = pwd_score(pwdi, word_tab[windex], pos, permvec, pvec);
  228.         if (score < 0.0)  continue;
  229.         pwdi->gcount++;
  230.         pwdi->total_score += score;
  231.         if (score < pwdi->best_score) {
  232.             pwdi->best_score = score;
  233.             pwdi->best_trigram = word_tab[windex];
  234.             pvec_copy(pvec, pwdi->best_pvec);
  235.             permvec_copy(permvec, pwdi->best_permvec, WDPERMSZ);
  236.             }
  237.         }
  238.     if (pwdi->best_score < pwdi->max_score)
  239.         {return(pwdi->best_trigram);}
  240.     else
  241.         {return(NULL);}
  242. }
  243.  
  244.  
  245.  
  246. /* Perform automatic guessing given a set of
  247.  * filter parameters in an atrinfo structure.
  248.  */
  249. pwd_autoguess(pwdi)
  250. atrinfo    *pwdi;
  251. {
  252.     int        pos;
  253.     char    *word;
  254.  
  255.     for (pos = 0 ; pos < BLOCKSIZE ; pos++) {
  256.         word = pwd_best(pwdi, pos);
  257.         if (word != NULL) {
  258.             accept_permvec(pwdi, pwdi->best_permvec);
  259.             }
  260.         }
  261. }
  262.