summaryrefslogtreecommitdiff
path: root/src/rand.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rand.c')
-rw-r--r--src/rand.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/rand.c b/src/rand.c
new file mode 100644
index 0000000..4a3f3ce
--- /dev/null
+++ b/src/rand.c
@@ -0,0 +1,123 @@
+/*
+ * Random numbers
+ * Copyright Jan Engelhardt, 2003-2008
+ *
+ * This file is part of libHX. libHX is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU Lesser
+ * General Public License as published by the Free Software Foundation;
+ * either version 2.1 or (at your option) any later version.
+ */
+#include "config.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#ifdef __unix__
+# include <unistd.h>
+#endif
+#ifdef _WIN32
+# include <process.h>
+#endif
+#include <libHX/init.h>
+#include <libHX/misc.h>
+#include "internal.h"
+
+static unsigned int HXrand_obtain_seed(void)
+{
+ unsigned int s;
+
+#if defined(HAVE_CLOCK_GETTIME)
+ struct timespec tv;
+
+ clock_gettime(CLOCK_REALTIME, &tv);
+ s = tv.tv_sec;
+ s ^= ~tv.tv_nsec;
+ clock_gettime(CLOCK_MONOTONIC, &tv);
+ s ^= tv.tv_sec;
+ s ^= ~tv.tv_nsec;
+#else
+ s = time(NULL);
+#endif
+#ifdef HAVE_GETPID
+ s ^= getpid() << 9;
+#endif
+#ifdef HAVE_GETPPID
+ s ^= getppid() << 1;
+#endif
+#ifdef HAVE_GETEUID
+ s ^= geteuid() << 13;
+#endif
+#ifdef HAVE_GETEGID
+ s ^= getegid() << 5;
+#endif
+ return s;
+}
+
+static void HXrand_init(void)
+{
+ unsigned int seed;
+ int fd, ret = 0;
+
+ if ((fd = open("/dev/urandom", O_RDONLY | O_BINARY)) >= 0) {
+ ret = read(fd, &seed, sizeof(seed));
+ close(fd);
+ }
+ if (ret != sizeof(seed))
+ seed = HXrand_obtain_seed();
+ srand(seed);
+}
+
+static pthread_mutex_t HX_init_lock = PTHREAD_MUTEX_INITIALIZER;
+static unsigned long HX_use_count;
+
+EXPORT_SYMBOL int HX_init(void)
+{
+ pthread_mutex_lock(&HX_init_lock);
+ if (HX_use_count == 0)
+ HXrand_init();
+ ++HX_use_count;
+ pthread_mutex_unlock(&HX_init_lock);
+ return 1;
+}
+
+EXPORT_SYMBOL void HX_exit(void)
+{
+ pthread_mutex_lock(&HX_init_lock);
+ if (HX_use_count == 0)
+ fprintf(stderr, "%s: reference count is already zero!\n", __func__);
+ else
+ --HX_use_count;
+ pthread_mutex_unlock(&HX_init_lock);
+}
+
+EXPORT_SYMBOL int HX_rand(void)
+{
+ /*
+ * If there is an overly broken system, we may need to use
+ * alternate methods again (/dev/urandom?)
+ */
+ return rand();
+}
+
+EXPORT_SYMBOL double HX_drand(double lo, double hi)
+{
+ double delta = hi - lo;
+
+ return static_cast(double, rand()) * delta / RAND_MAX + lo;
+}
+
+EXPORT_SYMBOL unsigned int HX_irand(unsigned int lo, unsigned int hi)
+{
+ unsigned int delta = hi - lo;
+
+ if (delta == 0)
+ return lo;
+ else if (delta <= RAND_MAX)
+ return rand() % delta + lo;
+ else
+ return static_cast(unsigned int,
+ static_cast(double, rand()) * delta / RAND_MAX) + lo;
+}