summaryrefslogtreecommitdiffstats
path: root/byterun/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'byterun/sys.c')
-rw-r--r--byterun/sys.c40
1 files changed, 31 insertions, 9 deletions
diff --git a/byterun/sys.c b/byterun/sys.c
index dcc290756..ce364d8c1 100644
--- a/byterun/sys.c
+++ b/byterun/sys.c
@@ -291,27 +291,49 @@ CAMLprim value caml_sys_time(value unit)
}
#ifdef _WIN32
-extern intnat caml_win32_random_seed (void);
+extern int caml_win32_random_seed (intnat data[16]);
#endif
CAMLprim value caml_sys_random_seed (value unit)
{
+ intnat data[16];
+ int n, i;
+ value res;
#ifdef _WIN32
- return Val_long(caml_win32_random_seed());
+ n = caml_win32_random_seed(data);
#else
- intnat seed;
+ int fd;
+ n = 0;
+ /* Try /dev/urandom first */
+ fd = open("/dev/urandom", O_RDONLY, 0);
+ if (fd != -1) {
+ unsigned char buffer[12];
+ int nread = read(fd, buffer, 12);
+ close(fd);
+ while (nread > 0) data[n++] = buffer[--nread];
+ }
+ /* If the read from /dev/urandom fully succeeded, we now have 96 bits
+ of good random data and can stop here. Otherwise, complement
+ whatever we got (probably nothing) with some not-very-random data. */
+ if (n < 12) {
#ifdef HAS_GETTIMEOFDAY
- struct timeval tv;
- gettimeofday(&tv, NULL);
- seed = tv.tv_sec ^ tv.tv_usec;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ data[n++] = tv.tv_usec;
+ data[n++] = tv.tv_sec;
#else
- seed = time (NULL);
+ data[n++] = time(NULL);
#endif
#ifdef HAS_UNISTD
- seed ^= (getppid() << 16) ^ getpid();
+ data[n++] = getpid();
+ data[n++] = getppid();
#endif
- return Val_long(seed);
+ }
#endif
+ /* Convert to an OCaml array of ints */
+ res = caml_alloc_small(n, 0);
+ for (i = 0; i < n; i++) Field(res, i) = Val_long(data[i]);
+ return res;
}
CAMLprim value caml_sys_get_config(value unit)