This patch is from: http://cvs.fedoraproject.org/viewvc/devel/bash/bash-3.2-rng.patch http://cvs.fedoraproject.org/viewvc/devel/bash/bash-3.2-344411.patch The second patch (bash-3.2-344411.patch) was integrated in bash-4.0, to provide $RANDOM in sub shells. Use /dev/urandom for $RANDOM. This patch does not break the Korn shell behaviour, where we can initialize $RANDOM ourselves and get the same results each time. /dev/urandom is only opened when $RANDOM is called. I pulled out all the autoconf stuff. This patch depends on random(3) and srandom(3) in libc, and /dev/urandom. getpid(3) and gettimeofday(3) are used if /dev/urandom isn't available at run time (like in a chroot). Test case: ( echo $RANDOM; ( echo $RANDOM ); ( echo $RANDOM ) ) robert diff -Naur bash-4.0.orig/variables.c bash-4.0/variables.c --- bash-4.0.orig/variables.c 2009-01-04 19:32:46.000000000 +0000 +++ bash-4.0/variables.c 2009-02-22 20:15:50.000000000 +0000 @@ -44,6 +44,12 @@ #include "bashansi.h" #include "bashintl.h" +#include +#include "filecntl.h" +#ifndef RANDOMDEV +#define RANDOMDEV "/dev/urandom" +#endif + #include "shell.h" #include "flags.h" #include "execute_cmd.h" @@ -188,7 +194,7 @@ static SHELL_VAR *init_seconds_var __P((void)); static int brand __P((void)); -static void sbrand __P((unsigned long)); /* set bash random number generator. */ +static void sbrand __P((unsigned int)); /* set bash random number generator. */ static void seedrand __P((void)); /* seed generator randomly */ static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t, char *)); static SHELL_VAR *get_random __P((SHELL_VAR *)); @@ -518,9 +524,6 @@ } #endif /* HISTORY */ - /* Seed the random number generator. */ - seedrand (); - /* Handle some "special" variables that we may have inherited from a parent shell. */ if (interactive_shell) @@ -1204,9 +1207,8 @@ } /* The random number seed. You can change this by setting RANDOM. */ -static unsigned long rseed = 1; static int last_random_value; -static int seeded_subshell = 0; +static int seeded_subshell = -1; /* A linear congruential random number generator based on the example one in the ANSI C standard. This one isn't very good, but a more @@ -1216,44 +1218,36 @@ static int brand () { -#if 0 - rseed = rseed * 1103515245 + 12345; - return ((unsigned int)((rseed >> 16) & 32767)); /* was % 32768 */ -#else - /* From "Random number generators: good ones are hard to find", - Park and Miller, Communications of the ACM, vol. 31, no. 10, - October 1988, p. 1195. filtered through FreeBSD */ - long h, l; - - if (rseed == 0) - seedrand (); - h = rseed / 127773; - l = rseed % 127773; - rseed = 16807 * l - 2836 * h; -#if 0 - if (rseed < 0) - rseed += 0x7fffffff; -#endif + unsigned int rseed; + rseed = random(); return ((unsigned int)(rseed & 32767)); /* was % 32768 */ -#endif } /* Set the random number generator seed to SEED. */ static void sbrand (seed) - unsigned long seed; + unsigned int seed; { - rseed = seed; + srandom((unsigned int)seed); last_random_value = 0; } static void seedrand () { - struct timeval tv; - - gettimeofday (&tv, NULL); - sbrand (tv.tv_sec ^ tv.tv_usec ^ getpid ()); + unsigned int seed; + int fd; + int rv; + if ((rv = fd = open (RANDOMDEV, O_RDONLY)) != -1) { + while ((rv = read(fd, &seed, sizeof(seed))) != sizeof(seed) && errno == EINTR); + close (fd); + } + if (rv != sizeof(seed)) { + struct timeval tv; + gettimeofday (&tv, NULL); + seed = (unsigned int)tv.tv_sec + (unsigned int)tv.tv_usec + getpid(); + } + sbrand (seed); } static SHELL_VAR * @@ -1263,9 +1257,8 @@ arrayind_t unused; char *key; { - sbrand (strtoul (value, (char **)NULL, 10)); - if (subshell_environment) - seeded_subshell = getpid (); + sbrand ((unsigned int)strtoul (value, (char **)NULL, 10)); + seeded_subshell = getpid (); return (self); } @@ -1276,7 +1269,7 @@ /* Reset for command and process substitution. */ pid = getpid (); - if (subshell_environment && seeded_subshell != pid) + if (seeded_subshell != pid) { seedrand (); seeded_subshell = pid;