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)11static 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)26void 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[])67int 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