/* * ppgen.c 1995-08-29 * Michael Shields * Public domain */ #include #include #include #include #include #ifdef STDC_HEADERS #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_MALLOC_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef HAVE_GETOPT_H #include #else char *optarg; #endif #include #include "ppg_random.h" int main(argc, argv) int argc; char **argv; { /* Parameters. */ char *dicts = "en"; int entropy = 64; int count = 1; char *dictpath = DICTPATH; /* The slurped dictionary. */ char *dictbuf = NULL; int dictbufsize = 0; char *dict; int dictfd; struct stat statbuf; /* The table of word offsets. */ int *table; int tablesize = 1024; int wordcount; int o; /* How many words we need. */ int words; while (1) { switch(getopt(argc, argv, "d:e:n:p:")) { case 'd': dicts = optarg; break; case 'e': entropy = atoi(optarg); if (entropy <= 0) { fprintf(stderr, "ppgen: Entropy must be positive\n"); exit(1); } break; case 'n': count = atoi(optarg); break; case 'p': dictpath = optarg; break; case -1: goto endargs; default: fprintf(stderr, "Usage: ppgen [-d dicts] [-e bits] [-n count] [-p path]\n"); exit(1); } } endargs: if (chdir(dictpath)) { fprintf(stderr, "ppgen: Couldn't chdir(%s): ", dictpath); perror(NULL); exit(errno); } dict = strtok(dicts, ":"); do { /* * Slurp the entire dictionary into dictbuf. */ dictfd = open(dict, O_RDONLY); if (dictfd < 0) { fprintf(stderr, "ppgen: Couldn't open `%s': ", dict); perror(NULL); exit(errno); } if (fstat(dictfd, &statbuf)) { fprintf(stderr, "ppgen: Couldn't fstat `%s': ", dict); perror(NULL); exit(errno); } if (dictbuf) dictbuf = realloc(dictbuf, dictbufsize + statbuf.st_size); else dictbuf = malloc(statbuf.st_size); if (!dictbuf) { fprintf(stderr, "ppgen: Couldn't alloc %ld bytes: ", dictbufsize + statbuf.st_size); perror(NULL); exit(errno); } if (read(dictfd, dictbuf + dictbufsize, statbuf.st_size) < statbuf.st_size) { fprintf(stderr, "ppgen: Couldn't read `%s'", dict); perror(NULL); exit(errno); } if (close(dictfd)) { fprintf(stderr, "ppgen: Couldn't close `%s'", dict); perror(NULL); exit(errno); } dictbufsize += statbuf.st_size; } while (dict = strtok(NULL, ":")); /* * Build a table of offsets to each word, dynamically growing it. */ table = malloc(tablesize * sizeof(int)); if (!table) { fprintf(stderr, "ppgen: Couldn't malloc %d bytes: ", tablesize * sizeof(int)); perror(NULL); exit(errno); } table[0] = 0; wordcount = 1; for (o = 1; o < dictbufsize; o++) { if (dictbuf[o-1] == '\n') { table[wordcount++] = o; if (wordcount == tablesize) { tablesize *= 2; table = realloc(table, tablesize * sizeof(int)); if (!table) { fprintf(stderr, "ppgen: Couldn't grow table to %d bytes: ", tablesize * sizeof(int)); perror(NULL); exit(errno); } } } } if (wordcount < 2) { fprintf(stderr, "ppgen: Dictionary must have at least two words!\n"); exit(1); } /* * See how many words we need, and print them. */ words = ceil(entropy / (log(wordcount)/log(2))); ppg_rand_init(words * count, entropy/words); while (count--) { int i; for (i = 0; i < words; i++) { char *cp; cp = &dictbuf[table[ppg_rand(wordcount-1)]]; while (*cp != '\n') putc(*cp++, stdout); if (words) putc(' ', stdout); } putc('\n', stdout); } exit(0); }