summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-03-10 02:36:17 (GMT)
committerH. Peter Anvin <hpa@zytor.com>2012-03-10 02:36:17 (GMT)
commitb444e1737742e091339f1a7b083adc9fa4e06c08 (patch)
treeef87c6fc6563d5247574a4b7e931d951df405baf
parentc955023c984c485d19b485a2c6a74b1e66020b62 (diff)
downloadgrv-b444e1737742e091339f1a7b083adc9fa4e06c08.zip
grv-b444e1737742e091339f1a7b083adc9fa4e06c08.tar.gz
grv-b444e1737742e091339f1a7b083adc9fa4e06c08.tar.bz2
grv-b444e1737742e091339f1a7b083adc9fa4e06c08.tar.xz
sysrand: Centralize getting randomness from the operating system
Centralize getting randomness from the underlying operating system, used to seed the Mersenne Twister PRNG and to generate game IDs.
-rw-r--r--Makefile2
-rw-r--r--Makefile.darwinx2
-rw-r--r--Makefile.w322
-rw-r--r--grv.c51
-rw-r--r--grv.h11
-rw-r--r--random.c7
-rw-r--r--sysrand.c116
7 files changed, 135 insertions, 56 deletions
diff --git a/Makefile b/Makefile
index b5dcc53..dfed040 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ OBJS = grv.o drawlevel.o play.o action.o bullets.o mystery.o \
prefs.o intro.o \
utils.o scoretbl.o highscore.o \
netopen.o keyboard.o graphics.o grvfont.o random.o \
- homedir.o
+ sysrand.o homedir.o
SCORED = grvscored.o scoretbl.o
diff --git a/Makefile.darwinx b/Makefile.darwinx
index 6891b91..459626f 100644
--- a/Makefile.darwinx
+++ b/Makefile.darwinx
@@ -27,7 +27,7 @@ OBJS = grv.o drawlevel.o play.o action.o bullets.o mystery.o \
prefs.o intro.o \
utils.o scoretbl.o highscore.o \
netopen.o keyboard.o graphics.o grvfont.o random.o \
- homedir.o \
+ sysrand.o homedir.o \
SDLMain.o
SCORED = grvscored.o scoretbl.o
diff --git a/Makefile.w32 b/Makefile.w32
index 9a80353..68421d6 100644
--- a/Makefile.w32
+++ b/Makefile.w32
@@ -33,7 +33,7 @@ OBJS = grv.o drawlevel.o play.o action.o bullets.o mystery.o \
prefs.o intro.o \
utils.o scoretbl.o highscore.o \
netopen.o keyboard.o graphics.o grvfont.o random.o \
- homedir.o
+ sysrand.o homedir.o
SCORED = grvscored.o scoretbl.o
diff --git a/grv.c b/grv.c
index 6ef8289..65c8b2c 100644
--- a/grv.c
+++ b/grv.c
@@ -13,37 +13,6 @@
#include "graphics.h"
#include "grv.h"
-#ifdef __unix__
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-int xread(int fd, void *buf, size_t count)
-{
- char *b = (char *)buf;
- int n = 0;
- int rv;
-
- while ( count ) {
- rv = read(fd, b, count);
- if ( rv == -1 ) {
- if ( errno == EINTR || errno == EAGAIN )
- continue;
- else
- return n ? n : -1;
- } else if ( rv == 0 ) {
- return n;
- }
-
- count -= rv;
- n += rv;
- b += rv;
- }
- return n;
-}
-#endif
-
struct gameparams gp;
struct monster ghost[MAXGHOST];
@@ -61,29 +30,13 @@ void init_gameparams(void)
gp.EOLWait = 1;
/* As good a start as any... */
- gp.have_id = 0;
gp.gameid = (uint64_t)genrand_int32() << 32;
-
-#ifdef __unix__
- {
- /* We might have /dev/urandom */
- int fd = open("/dev/urandom", O_RDONLY);
-
- if ( fd >= 0 ) {
- if ( xread(fd, &gp.gameid, sizeof(gp.gameid)) == sizeof(gp.gameid) )
- gp.have_id = 1;
- close(fd);
- }
- }
-#endif
+ gp.have_id = !get_random_bytes(&gp.gameid, sizeof gp.gameid);
}
-static int screen_width = 40;
void initscreen(int w)
{
- if ( w != screen_width )
- width(screen_width = w);
-
+ width(w);
color(0,gp.c);
cls();
}
diff --git a/grv.h b/grv.h
index 59272ea..3bd28bc 100644
--- a/grv.h
+++ b/grv.h
@@ -2,6 +2,11 @@
#define GRV_H 1
#include <inttypes.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
#include "graphics.h"
#include "SDL.h"
#include "SDL_keyboard.h"
@@ -9,11 +14,15 @@
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
+/* Get random bytes from the system */
+int get_random_bytes(void *, int);
+void randomize(void);
+
/* Get a random floating-point number between 0 and 1 */
extern void init_genrand(unsigned long);
extern double genrand_res53(void);
extern unsigned long genrand_int32(void);
-#define randomize() init_genrand(time(0))
+extern void init_by_array(const unsigned long *, unsigned long);
#define rnd() genrand_res53()
#define irnd(n) ((int)(genrand_int32() % (n)))
diff --git a/random.c b/random.c
index 1aac839..ea7de34 100644
--- a/random.c
+++ b/random.c
@@ -54,7 +54,7 @@ static unsigned long mt[N]; /* the array for the state vector */
static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
/* initializes mt[N] with a seed */
-void init_genrand(unsigned long s)
+static void init_genrand(unsigned long s)
{
mt[0]= s & 0xffffffffUL;
for (mti=1; mti<N; mti++) {
@@ -72,8 +72,7 @@ void init_genrand(unsigned long s)
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
-void init_by_array(init_key, key_length)
-unsigned long init_key[], key_length;
+void init_by_array(const unsigned long *init_key, unsigned long key_length)
{
int i, j, k;
init_genrand(19650218UL);
@@ -136,6 +135,7 @@ unsigned long genrand_int32(void)
return y;
}
+#if 0
/* generates a random number on [0,0x7fffffff]-interval */
long genrand_int31(void)
{
@@ -162,6 +162,7 @@ double genrand_real3(void)
return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
/* divided by 2^32 */
}
+#endif
/* generates a random number on [0,1) with 53-bit resolution*/
double genrand_res53(void)
diff --git a/sysrand.c b/sysrand.c
new file mode 100644
index 0000000..bdda374
--- /dev/null
+++ b/sysrand.c
@@ -0,0 +1,116 @@
+#include <time.h>
+#include "grv.h"
+
+#ifdef __unix__
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+static int xread(int fd, void *buf, size_t count)
+{
+ char *b = (char *)buf;
+ int n = 0;
+ int rv;
+
+ while ( count ) {
+ rv = read(fd, b, count);
+ if ( rv == -1 ) {
+ if ( errno == EINTR || errno == EAGAIN )
+ continue;
+ else
+ return n ? n : -1;
+ } else if ( rv == 0 ) {
+ return n;
+ }
+
+ count -= rv;
+ n += rv;
+ b += rv;
+ }
+ return n;
+}
+
+static int randfd = -1;
+
+int get_random_bytes(void *ptr, int len)
+{
+ /* We might have /dev/urandom */
+ if (randfd < 0) {
+ randfd = open("/dev/urandom", O_RDONLY);
+
+ if (randfd < 0)
+ return -1;
+
+ /*
+ * File descriptors are closed automatically on process exit, so
+ * we don't bother setting up atexit() here.
+ */
+ }
+
+ return xread(randfd, ptr, len) == len ? 0 : -1;
+}
+
+#elif defined(__WIN32__)
+#include <windows.h>
+#include <wincrypt.h>
+
+static HCRYPTPROV hProv;
+static int provider_open = 0;
+
+static void close_provider(void)
+{
+ CryptReleaseContext(hProv, 0);
+ provider_open = 0;
+}
+
+int get_random_bytes(void *ptr, int len)
+{
+ BOOL ok;
+ static const DWORD providers[] = {
+ PROV_RNG, PROV_INTEL_SEC, PROV_RSA_SIG, PROV_RSA_FULL,
+ PROV_DSS, PROV_SSL, 0
+ };
+
+ if (!provider_open) {
+ const DWORD *pp = providers;
+
+ while (*pp) {
+ if (CryptAcquireContext(&hProv, NULL, NULL, *pp,
+ CRYPT_SILENT | CRYPT_VERIFYCONTEXT))
+ goto found;
+ pp++;
+ }
+ return -1; /* No provider available */
+
+ found:
+ provider_open = 1;
+ atexit(close_provider);
+ }
+
+ ok = CryptGenRandom(hProv, len, ptr);
+
+ return ok ? 0 : -1;
+}
+
+#else
+
+/* Need system-specific code here */
+
+int get_random_bytes(void *ptr, int len)
+{
+ return -1;
+}
+
+#endif
+
+void randomize(void)
+{
+ unsigned long key_array[32/sizeof(unsigned long)];
+
+ key_array[0] = time(0); /* Better than nothing on failure*/
+
+ get_random_bytes(key_array, sizeof key_array);
+
+ init_by_array(key_array, sizeof key_array/(sizeof key_array[0]));
+}