--- pwgen-2.06/randnum.c 2007-07-05 09:42:19.000000000 +1000 +++ pwgen-2.06-mik/randnum.c 2013-05-27 16:48:02.879636128 +1000 @@ -6,52 +6,36 @@ * This file may be distributed under the terms of the GNU Public * 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; } /* @@ -61,35 +45,28 @@ int pw_random_number(max_num) int max_num; { int i, fd = get_random_fd(); - int lose_counter = 0, nbytes=4; + int nbytes=4; unsigned int rand_num; char *cp = (char *) &rand_num; + double rand_double; - if (fd >= 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 &= 0x7fffffff; -#ifdef HAVE_DRAND48 - return ((int) ((drand48() * max_num))); -#else - return ((int) (random() / ((float) RAND_MAX) * max_num)); -#endif + rand_double = (double)(rand_num & 0x7fffffff) * 4.656612873077393e-10; + return (int)(rand_double * max_num); }