--- pwgen-2.06/randnum.c 2007-07-05 09:42:19.000000000 +1000 +++ pwgen-2.06-mik/randnum.c 2013-05-28 10:17:33.808861141 +1000 @@ -7,53 +7,48 @@ * License. */ +#include +#include #include #include #include -#include #include #include #include #include "pwgen.h" -#ifdef HAVE_DRAND48 -extern double drand48(void); -#endif - static int get_random_fd(void); /* Borrowed/adapted from e2fsprogs's UUID generation code */ static int get_random_fd() { - struct timeval tv; - static int fd = -2; - int i; + static int fd = -2; - if (fd == -2) { - gettimeofday(&tv, 0); + if(fd == -2) { fd = open("/dev/urandom", O_RDONLY); - if (fd == -1) + if (fd == -1) { fd = open("/dev/random", O_RDONLY | O_NONBLOCK); -#ifdef HAVE_DRAND48 - srand48((tv.tv_sec<<9) ^ (getpgrp()<<15) ^ - (getpid()) ^ (tv.tv_usec>>11)); -#else - srandom((getpid() << 16) ^ (getpgrp() << 8) ^ getuid() - ^ tv.tv_sec ^ tv.tv_usec); -#endif + if (fd == -1) { + fprintf(stderr, "Unable to open /dev/urandom or /dev/random: %s\n", strerror(errno)); + exit(1); + } + } } - /* Crank the random number generator a few times */ - gettimeofday(&tv, 0); - for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) -#ifdef HAVE_DRAND48 - drand48(); -#else - random(); -#endif return fd; } +static unsigned int get_mask(int max_num) +{ + unsigned int numBits = 0; + while(max_num > 0) + { + numBits++; + max_num >>= 1; + } + return (1<= 0) { - while (nbytes > 0) { - i = read(fd, cp, nbytes); - if ((i < 0) && - ((errno == EINTR) || (errno == EAGAIN))) - continue; - if (i <= 0) { - if (lose_counter++ == 8) - break; - continue; - } - nbytes -= i; - cp += i; - lose_counter = 0; + while (nbytes > 0) { + i = read(fd, cp, nbytes); + if (i < 0) { + if ((errno == EINTR) || (errno == EAGAIN)) { + continue; + } else { + fprintf(stderr, "Error reading from random device: %s\n", strerror(errno)); + exit(1); + } } + nbytes -= i; + cp += i; } - if (nbytes == 0) - return (rand_num % max_num); - /* OK, we weren't able to use /dev/random, fall back to rand/rand48 */ + rand_num &= get_mask(max_num); + + if(rand_num < max_num) { + return rand_num; + } -#ifdef HAVE_DRAND48 - return ((int) ((drand48() * max_num))); -#else - return ((int) (random() / ((float) RAND_MAX) * max_num)); -#endif + return pw_random_number(max_num); /* tail-recurse */ }