mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-08-21 22:06:34 -04:00
XOR:ing the time since epoch in seconds with the PID fails for processes started every second since the PID and time increment in step regularly in this scenario and therefore give identical seeds. Thanks to Steve K9AN for spotting this subtle flaw. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6294 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
83 lines
1.8 KiB
C
83 lines
1.8 KiB
C
#include "init_random_seed.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
|
|
/* basic PRNG to use for improving the basic seed selection */
|
|
static unsigned lcg (uint64_t seed)
|
|
{
|
|
if (0 ==seed)
|
|
{
|
|
seed = UINT64_C(104729);
|
|
}
|
|
else
|
|
{
|
|
seed %= UINT64_C(4294967296);
|
|
}
|
|
seed = (seed * UINT64_C(279470273)) % UINT64_C(4294967291);
|
|
return seed % UINT64_MAX;
|
|
}
|
|
|
|
/* Generate a good PRNG seed value */
|
|
void init_random_seed(void)
|
|
{
|
|
unsigned seed = 0u;
|
|
int have_seed = 0;
|
|
|
|
// try /dev/urandom for an initial seed
|
|
int random_source;
|
|
if ((random_source = open ("/dev/urandom", O_RDONLY)) >= 0)
|
|
{
|
|
size_t random_data_length = 0;
|
|
have_seed = -1;
|
|
while (random_data_length < sizeof seed)
|
|
{
|
|
ssize_t result = read (random_source, &seed + random_data_length, (sizeof seed) - random_data_length);
|
|
if (result < 0)
|
|
{
|
|
// error, unable to read /dev/random
|
|
have_seed = 0;
|
|
}
|
|
random_data_length += result;
|
|
}
|
|
close (random_source);
|
|
}
|
|
if (!have_seed)
|
|
{
|
|
// fallback to combining the time and PID in a fairly random way
|
|
pid_t pid = getpid ();
|
|
struct timeval tv;
|
|
gettimeofday (&tv, NULL);
|
|
seed = (unsigned)(((unsigned)pid << 16)
|
|
^ (unsigned)pid
|
|
^ (unsigned)tv.tv_sec
|
|
^ (unsigned)tv.tv_usec);
|
|
seed = lcg (seed);
|
|
}
|
|
srand (seed);
|
|
}
|
|
|
|
#ifdef TEST
|
|
#include <stdio.h>
|
|
|
|
int main (int argc, char * argv[])
|
|
{
|
|
init_random_seed ();
|
|
int i, j;
|
|
int r[10][4];
|
|
for (i = 0; i < 10; ++i)
|
|
{
|
|
for (j = 0; j < 4; ++j)
|
|
{
|
|
printf ("%10d ", rand ());
|
|
}
|
|
printf ("\n");
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|