fixed a couple of things

This commit is contained in:
TLINDEN
2015-08-01 10:14:00 +02:00
parent a7e4d3aefe
commit 7187bc3e0a

289
dice.c
View File

@@ -9,101 +9,103 @@
#define DICTFILE "/usr/share/dict/american-english" #define DICTFILE "/usr/share/dict/american-english"
#define VERSION "1.0" #define VERSION "1.0"
#define RLEN 1024 #define RLEN 1024
#define WMIN 6
#define WMAX 10
int humantoss = 0; int humantoss = 0;
int WMIN = 5;
int WMAX = 10;
int usage() { int usage() {
fprintf(stderr, fprintf(stderr,
"Generate a random diceware passphrase\n" "Generate a random diceware passphrase\n"
"Usage: dice [-cfvh]\n" "Usage: dice [-cfvh]\n"
"Options: \n" "Options: \n"
"-t Asks interactively for tossed dices\n" "-t --humantoss Asks interactively for tossed dices\n"
"-c <count> Number of words (default: 4)\n" "-c --wordcount <count> Number of words (default: 4)\n"
"-f <dictfile> Dictionary file to use (default:\n" "-f --dictfile <dictfile> Dictionary file to use (default:\n"
" /usr/share/dict/american-english)\n" " /usr/share/dict/american-english)\n"
"-v Print program version\n" "-l --minlen <count> Minimum word len (default: 5)\n"
"-h Print this help screen\n" "-m --maxlen <count> Maximum word len (default: 10)\n"
"-v --version Print program version\n"
"-h -? --help Print this help screen\n"
); );
return 1; return 1;
} }
void _dump(unsigned char *d, size_t s) {
size_t i;
int c;
for (i=0; i<s; ++i) {
fprintf(stdout, "%d ", d[i]);
}
fprintf(stdout, "\n");
}
unsigned char *toss(int count) { unsigned char *toss(int count) {
FILE *RAND; /*
int i; toss <count> dices. if the global humandice is enabled (option -t),
int pos = 0; then ask the human to toss dices and enter the numbers interactively.
uint8_t onedice; otherwise generate tosses from /dev/random.
unsigned char *tosses = malloc((size_t)count); */
unsigned char *rand = NULL;
size_t len;
ssize_t linelen;
if(humantoss) { FILE *RAND;
char *line = NULL; int i;
char digit[2]; int pos = 0;
digit[1] = '\0'; uint8_t onedice;
unsigned char *tosses = NULL;
unsigned char *rand = NULL;
size_t len;
ssize_t linelen;
RETRY: if(humantoss) {
fprintf(stderr, "enter 5 digits, each between 1-6\n"); char *line = NULL;
linelen = getline(&line, &len, stdin); char digit[2];
digit[1] = '\0';
if(linelen < 6) RETRY:
goto RETRY; fprintf(stderr, "enter 5 digits, each between 1-6\n");
linelen = getline(&line, &len, stdin);
tosses = malloc((size_t)count);
for(i=0; i<count; i++) { if(linelen < 6) /* 5 digits max allowed */
if(isdigit(line[i]) == 0) goto RETRY;
goto RETRY;
digit[0] = line[i]; for(i=0; i<count; i++) { /* only digits allowed */
onedice = atoi(digit); if(isdigit(line[i]) == 0)
goto RETRY;
if (onedice < 1 || onedice > 6) digit[0] = line[i];
goto RETRY; onedice = atoi(digit);
tosses[i] = onedice; if (onedice < 1 || onedice > 6) /* no dice digit */
} goto RETRY;
free(line);
}
else {
rand = malloc(RLEN);
if((RAND = fopen("/dev/urandom", "rb")) == NULL) { tosses[i] = onedice;
perror("Could not open /dev/urandom"); }
} free(line);
}
else {
rand = malloc(RLEN);
fread(rand, RLEN, 1, RAND); if((RAND = fopen("/dev/urandom", "rb")) == NULL) {
fclose(RAND); perror("Could not open /dev/urandom");
}
for(i=0; i<RLEN; i++) { fread(rand, RLEN, 1, RAND);
onedice = rand[i]; fclose(RAND);
onedice &= 7;
onedice %= 6;
if(onedice >= 1 && onedice <= 6) {
tosses[pos] = onedice;
pos++;
}
if(pos == count)
break;
}
free(rand);
}
return tosses; tosses = malloc((size_t)count);
for(i=0; i<RLEN; i++) {
onedice = rand[i];
onedice &= 7; /* only use the last 3 bits, 0-7 */
onedice %= 6; /* 6 is the max */
if(onedice >= 1 && onedice <= 6) {
tosses[pos] = onedice;
pos++;
}
if(pos == count)
break;
}
free(rand);
}
return tosses;
} }
int rand_lim(int limit) { int rand_lim(int limit) {
/* return a random number in the range [0..limit) /*
return a random number in the range [0..limit)
*/ */
int divisor = RAND_MAX/limit; int divisor = RAND_MAX/limit;
@@ -116,32 +118,87 @@ int rand_lim(int limit) {
return retval; return retval;
} }
void getwords(char *dictfile, int count) { int *incr_dicedigit(int *digits) {
/*
increment an array of dice digits, we expect the first to
be a multiple of 10000, the 2nd a multiple of 1000 and so on.
*/
if(digits[4] == 6) {
digits[4] = 1;
if(digits[3] == 60) {
digits[3] = 10;
if(digits[2] == 600) {
digits[2] = 100;
if(digits[1] == 6000) {
digits[1] = 1000;
digits[0] += 10000; /* may overflow to 71111, must be catched by caller */
}
else
digits[1] += 1000;
}
else
digits[2] += 100;
}
else
digits[3] += 10;
}
else
digits[4]++;
return digits;
}
int get_dicenum(int *digits) {
/*
get the actual number of an array of dice digits
*/
int i = 0;
int pos = 0;
for(i=0; i<5; i++)
pos += digits[i];
return pos;
}
char **fetch_dict(char *dictfile) {
/*
read in the dictionary file. we generate an array of max
66666 entries from the dictionary, each entry's index will
be a dice number (1 <=> 6). to enhance randomness, we jump
over a number of lines (1-32 lines) and start from the beginning
of the file if we reach the end before our array is full.
*/
char **words; char **words;
int one, two, three, four, five, pos, i, next, jump; int pos, i, next, jump;
char *line = NULL; char *line = NULL;
size_t len = 0; size_t len = 0;
ssize_t linelen; ssize_t linelen;
FILE *DICT; FILE *DICT;
unsigned char *tosses; int *digits;
int *tossed;
one = 10000;
two = 1000;
three = 100;
four = 10;
five = 1;
pos = 11111;
words = malloc(66666 * sizeof(char *));
tossed = malloc(count);
jump = rand_lim(32);
if((DICT = fopen(dictfile, "rb")) == NULL) { if((DICT = fopen(dictfile, "rb")) == NULL) {
perror("Could not open dictfile"); perror("Could not open dictfile");
} }
words = malloc(66666 * sizeof(char *));
digits = malloc(5);
jump = rand_lim(32);
digits[0] = 10000;
digits[1] = 1000;
digits[2] = 100;
digits[3] = 10;
digits[4] = 1;
pos = 11111;
next = 0;
for(i=0; i<6666; i++)
words[i] = NULL;
LOOP: LOOP:
while ((linelen = getline(&line, &len, DICT)) != -1) { while ((linelen = getline(&line, &len, DICT)) != -1) {
if(jump > 0) { if(jump > 0) {
@@ -170,29 +227,8 @@ void getwords(char *dictfile, int count) {
strncpy( words[pos], line, linelen); strncpy( words[pos], line, linelen);
//fprintf(stdout, "%d: %s\n", pos, line); //fprintf(stdout, "%d: %s\n", pos, line);
if(five == 6) { digits = incr_dicedigit(digits);
five = 1; pos = get_dicenum(digits);
if(four == 60) {
four = 10;
if(three == 600) {
three = 100;
if(two == 6000) {
two = 1000;
one += 10000;
}
else
two += 1000;
}
else
three += 100;
}
else
four += 10;
}
else
five++;
pos = one + two + three + four + five;
/* this is what pos gets next after 66666, which is max reachable with 5 dices */ /* this is what pos gets next after 66666, which is max reachable with 5 dices */
if(pos == 71111) if(pos == 71111)
@@ -207,6 +243,24 @@ void getwords(char *dictfile, int count) {
fclose(DICT); fclose(DICT);
free(line); free(line);
free(digits);
return words;
}
void getwords(char *dictfile, int count) {
/*
initiate dice tossing, extract matching number of words
froom the wordlist and print it.
*/
char **words;
int i, pos, one, two, three, four, five;
int *tossed;
unsigned char *tosses;
words = fetch_dict(dictfile);
tossed = malloc(count * sizeof(int));
for(i=0; i<count; i++) { for(i=0; i<count; i++) {
tosses = toss(5); tosses = toss(5);
@@ -229,6 +283,14 @@ void getwords(char *dictfile, int count) {
} }
fprintf(stdout, "\n"); fprintf(stdout, "\n");
free(tossed);
for(i=0; i<6666; i++)
if(words[i] != NULL)
free(words[i]);
free(words);
} }
int main (int argc, char **argv) { int main (int argc, char **argv) {
@@ -239,13 +301,15 @@ int main (int argc, char **argv) {
static struct option longopts[] = { static struct option longopts[] = {
{ "wordcount", required_argument, NULL, 'c' }, { "wordcount", required_argument, NULL, 'c' },
{ "minlen", required_argument, NULL, 'l' },
{ "maxlen", required_argument, NULL, 'm' },
{ "humantoss", required_argument, NULL, 't' }, { "humantoss", required_argument, NULL, 't' },
{ "dictfile", required_argument, NULL, 'f' }, { "dictfile", required_argument, NULL, 'f' },
{ "version", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
}; };
while ((opt = getopt_long(argc, argv, "tf:c:vh?", longopts, NULL)) != -1) { while ((opt = getopt_long(argc, argv, "l:m:tf:c:vh?", longopts, NULL)) != -1) {
switch (opt) { switch (opt) {
case 'v': case 'v':
fprintf(stderr, "This is %s version %s\n", argv[0], VERSION); fprintf(stderr, "This is %s version %s\n", argv[0], VERSION);
@@ -258,6 +322,12 @@ int main (int argc, char **argv) {
case 'c': case 'c':
count = atoi(optarg); count = atoi(optarg);
break; break;
case 'l':
WMIN = atoi(optarg);
break;
case 'm':
WMAX = atoi(optarg);
break;
case 't': case 't':
humantoss = 1; humantoss = 1;
break; break;
@@ -276,10 +346,7 @@ int main (int argc, char **argv) {
dictfile = DICTFILE; dictfile = DICTFILE;
} }
//_dump(tosses, (size_t) count);
getwords(dictfile, count); getwords(dictfile, count);
return 0; return 0;
} }