commit - 88da105c5d8bf235538925538a0a36723b9daf48
commit + 926e1c04eee17d60a49e5903d3273232fbd30fb0
blob - aeeb3c2404fa31ee8abb2aefae8f1b5cb84ba3d6
blob + 78ac0b578eecc06acd9c2976066f2824afcba822
--- gpass.c
+++ gpass.c
+#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <math.h>
#include <sodium.h>
-#define MAXWORDS 128
-#define RANDLINE randombytes_uniform(nlines)+1
+#define MAXWORDS 32768
#ifndef PREFIX
# define PREFIX "/usr/local"
#endif
FILE *dicfp;
+uint32_t nwords = 0;
+int offs[MAXWORDS];
int plen = 70;
-uint32_t nlines = 0;
void
errx(int eval, const char *fmt, ...)
void
gen(void)
{
- char c;
- int left = plen;
- uint32_t cur = 1, sought = RANDLINE;
+ int c;
+ int left;
+ uint32_t n;
- rewind(dicfp);
-
- for (;;) {
- while (getc(dicfp) != '\n')
- ;
- if (++cur != sought)
- continue;
- while ((c = getc(dicfp)) != '\n')
+ for (left = plen; left; left--) {
+ n = randombytes_uniform(nwords) + 1;
+ if (fseek(dicfp, offs[n], SEEK_SET) == -1)
+ err(1, "fseek");
+ while ((c = getc(dicfp)) != EOF && !isspace(c))
putchar(c);
- if (!--left)
- break;
- putchar(' ');
- if ((sought = RANDLINE) <= cur) {
- rewind(dicfp);
- cur = 0;
- }
+ if (left > 1)
+ putchar(' ');
}
-
putchar('\n');
}
int
main(int argc, char *argv[])
{
- int c, npass = 1;
- char *dicname = NULL;
+ int c, isword, npass, temp;
+ char *dicname;
+ isword = 0;
+ npass = 1;
+ dicname = NULL;
+
#ifdef __OpenBSD__
if (pledge("stdio unveil rpath", NULL) == -1) /* first call */
err(1, "pledge");
if (pledge("stdio rpath", NULL) == -1) /* revoke unveil */
err(1, "pledge");
#endif
+
if (!(dicfp = fopen(dicname, "r")))
err(1, "could not open %s", dicname);
- while ((c = getc(dicfp)) != EOF && nlines < UINT32_MAX)
- nlines += (c == '\n');
- if (nlines < 2)
- errx(1, "%s has less that 2 lines", dicname);
- int log2nlines = log2(nlines);
- plen = plen / log2nlines + !!(plen % log2nlines);
+ offs[0] = ftell(dicfp);
+ while ((c = getc(dicfp)) != EOF && nwords < MAXWORDS)
+ if (isspace(c)) {
+ nwords += isword ? 1 : 0;
+ isword = 0;
+ offs[nwords] = ftell(dicfp);
+ } else
+ isword = 1;
+ if (nwords < 2)
+ errx(1, "%s has less that 2 words", dicname);
+
+ temp = log2(nwords);
+ plen = plen / temp + !!(plen % temp);
plen += !plen;
for (int i = 0; i < npass; i++)