1 #include "init_random_seed.h"
2 
3 #include <stdlib.h>
4 #include <stdint.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <sys/time.h>
8 #include <unistd.h>
9 
10 /* basic PRNG to use for improving the basic seed selection */
lcg(uint64_t seed)11 static unsigned lcg (uint64_t seed)
12 {
13   if (0 ==seed)
14     {
15       seed = UINT64_C(104729);
16     }
17   else
18     {
19       seed %= UINT64_C(4294967296);
20     }
21   seed = (seed * UINT64_C(279470273)) % UINT64_C(4294967291);
22   return seed % UINT64_MAX;
23 }
24 
25 /* Generate a good PRNG seed value */
init_random_seed(void)26 void init_random_seed(void)
27 {
28   unsigned seed = 0u;
29   int have_seed = 0;
30 
31   // try /dev/urandom for an initial seed
32   int random_source;
33   if ((random_source = open ("/dev/urandom", O_RDONLY)) >= 0)
34     {
35       size_t random_data_length = 0;
36       have_seed = -1;
37       while (random_data_length < sizeof seed)
38         {
39           ssize_t result = read (random_source, &seed + random_data_length, (sizeof seed) - random_data_length);
40           if (result < 0)
41             {
42               // error, unable to read /dev/random
43               have_seed = 0;
44             }
45           random_data_length += result;
46         }
47       close (random_source);
48     }
49   if (!have_seed)
50     {
51       // fallback to combining the time and PID in a fairly random way
52       pid_t pid = getpid ();
53       struct timeval tv;
54       gettimeofday (&tv, NULL);
55       seed = (unsigned)(((unsigned)pid << 16)
56         ^ (unsigned)pid
57         ^ (unsigned)tv.tv_sec
58         ^ (unsigned)tv.tv_usec);
59       seed = lcg (seed);
60     }
61   srand (seed);
62 }
63 
64 #ifdef TEST
65 #include <stdio.h>
66 
main(int argc,char * argv[])67 int main (int argc, char * argv[])
68 {
69   init_random_seed ();
70   int i, j;
71   int r[10][4];
72   for (i = 0; i < 10; ++i)
73     {
74       for (j = 0; j < 4; ++j)
75         {
76           printf ("%10d ", rand ());
77         }
78       printf ("\n");
79     }
80   return 0;
81 }
82 #endif
83