summaryrefslogtreecommitdiff
path: root/src/librandom
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2014-09-18 18:55:44 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2014-09-18 18:55:44 +0000
commit3534b428629be185e096be99e3bd5fdfe32d5544 (patch)
tree210ef3198ed66bc7f7b7bf6a85e4579f455e5a36 /src/librandom
downloadskalibs-3534b428629be185e096be99e3bd5fdfe32d5544.tar.xz
initial commit with rc for skalibs-2.0.0.0
Diffstat (limited to 'src/librandom')
-rw-r--r--src/librandom/badrandom_char.c13
-rw-r--r--src/librandom/badrandom_finish.c12
-rw-r--r--src/librandom/badrandom_here.c40
-rw-r--r--src/librandom/badrandom_init.c10
-rw-r--r--src/librandom/badrandom_int.c12
-rw-r--r--src/librandom/badrandom_string.c12
-rw-r--r--src/librandom/goodrandom_char.c13
-rw-r--r--src/librandom/goodrandom_finish.c12
-rw-r--r--src/librandom/goodrandom_here.c40
-rw-r--r--src/librandom/goodrandom_init.c10
-rw-r--r--src/librandom/goodrandom_int.c12
-rw-r--r--src/librandom/goodrandom_string.c12
-rw-r--r--src/librandom/random-internal.h20
-rw-r--r--src/librandom/random_mask2.c35
-rw-r--r--src/librandom/random_name.c13
-rw-r--r--src/librandom/random_sauniquename.c25
-rw-r--r--src/librandom/random_unsort.c17
-rw-r--r--src/librandom/randomegd_open.c20
-rw-r--r--src/librandom/randomegd_readb.c27
-rw-r--r--src/librandom/randomegd_readnb.c28
-rw-r--r--src/librandom/rrandom_add.c13
-rw-r--r--src/librandom/rrandom_finish.c14
-rw-r--r--src/librandom/rrandom_name.c13
-rw-r--r--src/librandom/rrandom_read.c21
-rw-r--r--src/librandom/rrandom_readint.c24
-rw-r--r--src/librandom/surf.c54
-rw-r--r--src/librandom/surf_autoinit.c10
-rw-r--r--src/librandom/surf_here.c8
-rw-r--r--src/librandom/surf_init.c10
-rw-r--r--src/librandom/surf_makeseed.c35
-rw-r--r--src/librandom/surf_sinit.c13
-rw-r--r--src/librandom/unidevrandom.c38
-rw-r--r--src/librandom/unidevurandom.c38
-rw-r--r--src/librandom/unihasegd.c38
-rw-r--r--src/librandom/unirandom_finish.c12
-rw-r--r--src/librandom/unirandom_init.c12
-rw-r--r--src/librandom/unirandom_readb.c10
-rw-r--r--src/librandom/unirandom_readnb.c10
-rw-r--r--src/librandom/unirandom_register.c16
-rw-r--r--src/librandom/unirandomdev.c50
-rw-r--r--src/librandom/unirandomegd.c37
-rw-r--r--src/librandom/unisurf.c23
-rw-r--r--src/librandom/unisurf_init.c18
43 files changed, 900 insertions, 0 deletions
diff --git a/src/librandom/badrandom_char.c b/src/librandom/badrandom_char.c
new file mode 100644
index 0000000..c0ca1de
--- /dev/null
+++ b/src/librandom/badrandom_char.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include "random-internal.h"
+#include <skalibs/random.h>
+
+unsigned char badrandom_char (void)
+{
+ unsigned char x ;
+ badrandom_string((char *)&x, 1) ;
+ return x ;
+}
diff --git a/src/librandom/badrandom_finish.c b/src/librandom/badrandom_finish.c
new file mode 100644
index 0000000..e0791ee
--- /dev/null
+++ b/src/librandom/badrandom_finish.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/rrandom.h>
+#include "random-internal.h"
+#include <skalibs/random.h>
+
+void badrandom_finish (void)
+{
+ rrandom_finish(&badrandom_here) ;
+}
diff --git a/src/librandom/badrandom_here.c b/src/librandom/badrandom_here.c
new file mode 100644
index 0000000..c7d2992
--- /dev/null
+++ b/src/librandom/badrandom_here.c
@@ -0,0 +1,40 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/sysdeps.h>
+#include <skalibs/config.h>
+#include <skalibs/unisurf.h>
+#include "random-internal.h"
+
+#ifdef SKALIBS_EGD
+
+# include <skalibs/unirandomegd.h>
+
+# ifdef SKALIBS_HASDEVURANDOM
+
+# include <skalibs/unirandomdev.h>
+
+rrandom badrandom_here = { { { UNIRANDOM_REGISTER_DEVURANDOM(), 3 }, { UNIRANDOM_REGISTER_HASEGD(), 3 }, { UNIRANDOM_REGISTER_SURF(), 3 } }, 3 } ;
+
+# else
+
+rrandom badrandom_here = { { { UNIRANDOM_REGISTER_HASEGD(), 3 }, { UNIRANDOM_REGISTER_SURF(), 3 }, { UNIRANDOM_ZERO, 3 } }, 2 } ;
+
+# endif
+
+#else
+
+# ifdef SKALIBS_HASDEVURANDOM
+
+# include <skalibs/unirandomdev.h>
+
+rrandom badrandom_here = { { { UNIRANDOM_REGISTER_DEVURANDOM(), 3 }, { UNIRANDOM_REGISTER_SURF(), 3 }, { UNIRANDOM_ZERO, 3 } }, 2 } ;
+
+# else
+
+rrandom badrandom_here = { { { UNIRANDOM_REGISTER_SURF(), 3 }, { UNIRANDOM_ZERO, 3 }, { UNIRANDOM_ZERO, 3 } }, 1 } ;
+
+# endif
+
+#endif
diff --git a/src/librandom/badrandom_init.c b/src/librandom/badrandom_init.c
new file mode 100644
index 0000000..a6eb7e3
--- /dev/null
+++ b/src/librandom/badrandom_init.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/random.h>
+
+int badrandom_init (void)
+{
+ return 1 ;
+}
diff --git a/src/librandom/badrandom_int.c b/src/librandom/badrandom_int.c
new file mode 100644
index 0000000..ae12db5
--- /dev/null
+++ b/src/librandom/badrandom_int.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/rrandom.h>
+#include "random-internal.h"
+#include <skalibs/random.h>
+
+unsigned int badrandom_int (unsigned int n)
+{
+ return rrandom_readint(&badrandom_here, n, &unirandom_readnb) ;
+}
diff --git a/src/librandom/badrandom_string.c b/src/librandom/badrandom_string.c
new file mode 100644
index 0000000..ec20f5b
--- /dev/null
+++ b/src/librandom/badrandom_string.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/rrandom.h>
+#include "random-internal.h"
+#include <skalibs/random.h>
+
+unsigned int badrandom_string (char *s, unsigned int n)
+{
+ return rrandom_readnb(&badrandom_here, s, n) ;
+}
diff --git a/src/librandom/goodrandom_char.c b/src/librandom/goodrandom_char.c
new file mode 100644
index 0000000..8fbf5e8
--- /dev/null
+++ b/src/librandom/goodrandom_char.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include "random-internal.h"
+#include <skalibs/random.h>
+
+unsigned char goodrandom_char (void)
+{
+ unsigned char x ;
+ goodrandom_string((char *)&x, 1) ;
+ return x ;
+}
diff --git a/src/librandom/goodrandom_finish.c b/src/librandom/goodrandom_finish.c
new file mode 100644
index 0000000..a764030
--- /dev/null
+++ b/src/librandom/goodrandom_finish.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include "random-internal.h"
+#include <skalibs/rrandom.h>
+#include <skalibs/random.h>
+
+void goodrandom_finish (void)
+{
+ rrandom_finish(&goodrandom_here) ;
+}
diff --git a/src/librandom/goodrandom_here.c b/src/librandom/goodrandom_here.c
new file mode 100644
index 0000000..8275ab2
--- /dev/null
+++ b/src/librandom/goodrandom_here.c
@@ -0,0 +1,40 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/sysdeps.h>
+#include <skalibs/config.h>
+#include <skalibs/unisurf.h>
+#include "random-internal.h"
+
+#ifdef SKALIBS_EGD
+
+# include <skalibs/unirandomegd.h>
+
+# ifdef SKALIBS_HASDEVRANDOM
+
+# include <skalibs/unirandomdev.h>
+
+rrandom goodrandom_here = { { { UNIRANDOM_REGISTER_DEVRANDOM(), 3 }, { UNIRANDOM_REGISTER_HASEGD(), 3 }, { UNIRANDOM_REGISTER_SURF(), 3 } }, 3 } ;
+
+# else
+
+rrandom goodrandom_here = { { { UNIRANDOM_REGISTER_HASEGD(), 3 }, { UNIRANDOM_REGISTER_SURF(), 3 }, { UNIRANDOM_ZERO, 3 } }, 2 } ;
+
+# endif
+
+#else
+
+# ifdef SKALIBS_HASDEVRANDOM
+
+# include <skalibs/unirandomdev.h>
+
+rrandom goodrandom_here = { { { UNIRANDOM_REGISTER_DEVRANDOM(), 3 }, { UNIRANDOM_REGISTER_SURF(), 3 }, { UNIRANDOM_ZERO, 3 } }, 2 } ;
+
+# else
+
+rrandom goodrandom_here = { { { UNIRANDOM_REGISTER_SURF(), 3 }, { UNIRANDOM_ZERO, 3 }, { UNIRANDOM_ZERO, 3 } }, 1 } ;
+
+# endif
+
+#endif
diff --git a/src/librandom/goodrandom_init.c b/src/librandom/goodrandom_init.c
new file mode 100644
index 0000000..dea6225
--- /dev/null
+++ b/src/librandom/goodrandom_init.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/random.h>
+
+int goodrandom_init (void)
+{
+ return 1 ;
+}
diff --git a/src/librandom/goodrandom_int.c b/src/librandom/goodrandom_int.c
new file mode 100644
index 0000000..11ef2e1
--- /dev/null
+++ b/src/librandom/goodrandom_int.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/rrandom.h>
+#include "random-internal.h"
+#include <skalibs/random.h>
+
+unsigned int goodrandom_int (unsigned int n)
+{
+ return rrandom_readint(&goodrandom_here, n, &unirandom_readb) ;
+}
diff --git a/src/librandom/goodrandom_string.c b/src/librandom/goodrandom_string.c
new file mode 100644
index 0000000..556c41c
--- /dev/null
+++ b/src/librandom/goodrandom_string.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/rrandom.h>
+#include "random-internal.h"
+#include <skalibs/random.h>
+
+unsigned int goodrandom_string (char *s, unsigned int n)
+{
+ return rrandom_readb(&goodrandom_here, s, n) ;
+}
diff --git a/src/librandom/random-internal.h b/src/librandom/random-internal.h
new file mode 100644
index 0000000..37b534e
--- /dev/null
+++ b/src/librandom/random-internal.h
@@ -0,0 +1,20 @@
+/* ISC license. */
+
+#ifndef RANDOM_INTERNAL_H
+#define RANDOM_INTERNAL_H
+
+#include <skalibs/gccattributes.h>
+#include <skalibs/surf.h>
+#include <skalibs/unirandom.h>
+#include <skalibs/rrandom.h>
+
+extern void unirandom_register (unirandom_ref, int (*) (union unirandominfo *), int (*) (union unirandominfo *), unsigned int (*) (union unirandominfo *, char *, unsigned int), unsigned int (*) (union unirandominfo *, char *, unsigned int)) ;
+
+extern unsigned int random_mask2 (unsigned int) gccattr_const ;
+extern unsigned int random_nchars (unsigned int) gccattr_const ;
+
+extern SURFSchedule surf_here ;
+extern rrandom goodrandom_here ;
+extern rrandom badrandom_here ;
+
+#endif
diff --git a/src/librandom/random_mask2.c b/src/librandom/random_mask2.c
new file mode 100644
index 0000000..ab8c8e7
--- /dev/null
+++ b/src/librandom/random_mask2.c
@@ -0,0 +1,35 @@
+/* ISC license. */
+
+#include <skalibs/sysdeps.h>
+#include "random-internal.h"
+
+unsigned int random_mask2 (register unsigned int n)
+{
+ for (;;)
+ {
+ register unsigned int m = n | (n >> 1) ;
+ if (m == n) return n ;
+ n = m ;
+ }
+}
+
+unsigned int random_nchars (register unsigned int n)
+{
+ return n <= 0xff ? 1 :
+#if SKALIBS_SIZEOFUINT == 2
+ 2
+#else
+ n <= 0xffff ? 2 :
+ n <= 0xffffffUL ? 3 :
+# if SKALIBS_SIZEOFUINT == 4
+ 4
+# else
+ n <= 0xffffffffUL ? 4 :
+ n <= 0xffffffffffULL ? 5 :
+ n <= 0xffffffffffffULL ? 6 :
+ n <= 0xffffffffffffffULL ? 7 :
+ 8
+# endif
+#endif
+ ;
+}
diff --git a/src/librandom/random_name.c b/src/librandom/random_name.c
new file mode 100644
index 0000000..8736699
--- /dev/null
+++ b/src/librandom/random_name.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include "random-internal.h"
+#include <skalibs/random.h>
+
+int random_name (char *s, unsigned int n)
+{
+ register unsigned int r = rrandom_name(&badrandom_here, s, n, 1) ;
+ if (r < n) return -1 ;
+ return n ;
+}
diff --git a/src/librandom/random_sauniquename.c b/src/librandom/random_sauniquename.c
new file mode 100644
index 0000000..7c902ef
--- /dev/null
+++ b/src/librandom/random_sauniquename.c
@@ -0,0 +1,25 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/stralloc.h>
+#include <skalibs/skamisc.h>
+#include <skalibs/random.h>
+
+int random_sauniquename (stralloc *sa, unsigned int n)
+{
+ unsigned int base = sa->len ;
+ int wasnull = !sa->s ;
+ register int r ;
+ if (sauniquename(sa) == -1) return -1 ;
+ if (!stralloc_readyplus(sa, n+1)) goto err ;
+ stralloc_catb(sa, ":", 1) ;
+ r = random_name(sa->s + sa->len, n) ;
+ if (r == -1) goto err ;
+ sa->len += r ;
+ return r ;
+
+err:
+ if (wasnull) stralloc_free(sa) ; else sa->len = base ;
+ return -1 ;
+}
diff --git a/src/librandom/random_unsort.c b/src/librandom/random_unsort.c
new file mode 100644
index 0000000..289ef96
--- /dev/null
+++ b/src/librandom/random_unsort.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/random.h>
+
+void random_unsort (char *s, unsigned int n, unsigned int chunksize)
+{
+ char tmp[chunksize] ;
+ while (n--)
+ {
+ register unsigned int i = badrandom_int(n+1) ;
+ byte_copy(tmp, chunksize, s + i * chunksize) ;
+ byte_copy(s + i * chunksize, chunksize, s + n * chunksize) ;
+ byte_copy(s + n * chunksize, chunksize, tmp) ;
+ }
+}
diff --git a/src/librandom/randomegd_open.c b/src/librandom/randomegd_open.c
new file mode 100644
index 0000000..7c43f0d
--- /dev/null
+++ b/src/librandom/randomegd_open.c
@@ -0,0 +1,20 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/webipc.h>
+#include <skalibs/randomegd.h>
+
+int randomegd_open (char const *path)
+{
+ int s = ipc_stream() ;
+ if (s < 0) return -1 ;
+ if (ipc_connect(s, path) == -1)
+ {
+ register int e = errno ;
+ fd_close(s) ;
+ errno = e ;
+ return -1 ;
+ }
+ return s ;
+}
diff --git a/src/librandom/randomegd_readb.c b/src/librandom/randomegd_readb.c
new file mode 100644
index 0000000..614f7a8
--- /dev/null
+++ b/src/librandom/randomegd_readb.c
@@ -0,0 +1,27 @@
+/* ISC license. */
+
+#include <skalibs/allreadwrite.h>
+#include <skalibs/randomegd.h>
+
+unsigned int randomegd_readb (int s, char *x, unsigned int n)
+{
+ unsigned int w = 0 ;
+ unsigned int i = 0 ;
+ for (; i < (n / 255) ; i++)
+ {
+ char const c[2] = { 0x02, 0xFF } ;
+ register unsigned int wtmp ;
+ if (allwrite(s, c, 2) < 2) return w ;
+ wtmp = allread(s, x + w, 255) ;
+ w += wtmp ;
+ if (wtmp < 255) return w ;
+ }
+ if (w < n)
+ {
+ char c[2] = "\002" ;
+ c[1] = n - w ;
+ if (allwrite(s, c, 2) < 2) return w ;
+ w += allread(s, x + w, c[1]) ;
+ }
+ return w ;
+}
diff --git a/src/librandom/randomegd_readnb.c b/src/librandom/randomegd_readnb.c
new file mode 100644
index 0000000..29165c4
--- /dev/null
+++ b/src/librandom/randomegd_readnb.c
@@ -0,0 +1,28 @@
+/* ISC license. */
+
+#include <skalibs/allreadwrite.h>
+#include <skalibs/randomegd.h>
+
+unsigned int randomegd_readnb (int s, char *x, unsigned int n)
+{
+ unsigned int w = 0 ;
+ while ((n - w) >= 255)
+ {
+ char c[2] = { 0x01, 0xFF } ;
+ register unsigned char wtmp ;
+ if (allwrite(s, c, 2) < 2) return w ;
+ if (sanitize_read(fd_read(s, c+1, 1)) < 1) return w ;
+ wtmp = allread(s, x + w, c[1]) ;
+ w += wtmp ;
+ if ((wtmp < (unsigned char)c[1]) || ((unsigned char)c[1] < 0xFF)) return w ;
+ }
+ if (w < n)
+ {
+ char c[2] = "\001" ;
+ c[1] = n - w ;
+ if (allwrite(s, c, 2) < 2) return w ;
+ if (sanitize_read(fd_read(s, c+1, 1)) < 1) return w ;
+ w += allread(s, x + w, c[1]) ;
+ }
+ return w ;
+}
diff --git a/src/librandom/rrandom_add.c b/src/librandom/rrandom_add.c
new file mode 100644
index 0000000..c22a43c
--- /dev/null
+++ b/src/librandom/rrandom_add.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/unirandom.h>
+#include <skalibs/rrandom.h>
+
+int rrandom_add (rrandom_ref z, int (*f) (unirandom_ref))
+{
+ if (z->n >= 3) return (errno = EBUSY, 0) ;
+ if (!(*f)(&z->tries[z->n].it)) return 0 ;
+ z->tries[z->n++].ok = 3 ;
+ return 1 ;
+}
diff --git a/src/librandom/rrandom_finish.c b/src/librandom/rrandom_finish.c
new file mode 100644
index 0000000..a3cb24b
--- /dev/null
+++ b/src/librandom/rrandom_finish.c
@@ -0,0 +1,14 @@
+/* ISC license. */
+
+#include <skalibs/unirandom.h>
+#include <skalibs/rrandom.h>
+
+int rrandom_finish (rrandom_ref z)
+{
+ rrandom zero = RRANDOM_ZERO ;
+ unsigned int i = z->n ;
+ int e = 1 ;
+ while (i--) e &= unirandom_finish(&z->tries[i].it) ;
+ if (e) *z = zero ;
+ return e ;
+}
diff --git a/src/librandom/rrandom_name.c b/src/librandom/rrandom_name.c
new file mode 100644
index 0000000..5e77e83
--- /dev/null
+++ b/src/librandom/rrandom_name.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <skalibs/unirandom.h>
+#include <skalibs/rrandom.h>
+
+unsigned int rrandom_name (rrandom_ref z, char *s, unsigned int n, int nb)
+{
+ static char const *oklist = "ABCDEFGHIJKLMNOPQRSTUVWXYZghijklmnopqrstuvwxyz-_0123456789abcdef" ;
+ register unsigned int r = rrandom_read(z, s, n, nb ? &unirandom_readnb : &unirandom_readb) ;
+ register unsigned int i = 0 ;
+ for (; i < r ; i++) s[i] = oklist[s[i] & 63] ;
+ return r ;
+}
diff --git a/src/librandom/rrandom_read.c b/src/librandom/rrandom_read.c
new file mode 100644
index 0000000..57ff920
--- /dev/null
+++ b/src/librandom/rrandom_read.c
@@ -0,0 +1,21 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/allreadwrite.h>
+#include <skalibs/error.h>
+#include <skalibs/unirandom.h>
+#include <skalibs/rrandom.h>
+
+unsigned int rrandom_read (rrandom_ref z, char *s, unsigned int n, unsigned int (*f) (unirandom_ref, char *, unsigned int))
+{
+ unsigned int i = 0 ;
+ for (; i < 3 ; i++)
+ {
+ int r ;
+ if (!z->tries[i].ok) continue ;
+ r = sanitize_read((*f)(&z->tries[i].it, s, n)) ;
+ if (r > 0) return r ;
+ z->tries[i].ok = error_temp(errno) ? z->tries[i].ok - 1 : 0 ;
+ }
+ return (errno = ENOENT, 0) ;
+}
diff --git a/src/librandom/rrandom_readint.c b/src/librandom/rrandom_readint.c
new file mode 100644
index 0000000..e4f677c
--- /dev/null
+++ b/src/librandom/rrandom_readint.c
@@ -0,0 +1,24 @@
+/* ISC license. */
+
+#include <skalibs/uint.h>
+#include <skalibs/unirandom.h>
+#include "random-internal.h"
+#include <skalibs/rrandom.h>
+
+unsigned int rrandom_readint (rrandom_ref z, unsigned int n, unsigned int (*f) (unirandom_ref, char *, unsigned int))
+{
+ if (!n) return 0 ;
+ else
+ {
+ unsigned int i = n, nchars = random_nchars(n), m = random_mask2(n-1) ;
+ char tmp[UINT_PACK] ;
+ while (i >= n)
+ {
+ if (rrandom_read(z, tmp, nchars, f) < nchars) return 0 ;
+ byte_zero(tmp + nchars, UINT_PACK - nchars) ;
+ uint_unpack(tmp, &i) ;
+ i &= m ;
+ }
+ return i ;
+ }
+}
diff --git a/src/librandom/surf.c b/src/librandom/surf.c
new file mode 100644
index 0000000..1687df9
--- /dev/null
+++ b/src/librandom/surf.c
@@ -0,0 +1,54 @@
+/* ISC license. */
+
+#include <skalibs/uint32.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/surf.h>
+
+#define ROTATE(x, b) (((x) << (b)) | ((x) >> (32 - (b))))
+#define MUSH(i, b) x = t[i] += (((x ^ ctx->seed[i]) + sum) ^ ROTATE(x, b))
+
+static void surfit (SURFSchedule_ref ctx)
+{
+ uint32 t[12] ;
+ uint32 z[8] ;
+ uint32 x ;
+ uint32 sum = 0 ;
+ unsigned int i = 0, loop = 0 ; ;
+
+ if (!++ctx->in[0] && !++ctx->in[1] && !++ctx->in[2]) ++ctx->in[3] ;
+ for (; i < 12 ; i++) t[i] = ctx->in[i] ^ ctx->seed[12+i] ;
+ for (i = 0 ; i < 8 ; i++) z[i] = ctx->seed[24+i] ;
+ x = t[11] ;
+ for (; loop < 2 ; loop++)
+ {
+ for (i = 0 ; i < 16 ; i++)
+ {
+ sum += 0x9e3779b9 ;
+ MUSH(0, 5) ; MUSH(1, 7) ; MUSH(2, 9) ; MUSH(3, 13) ;
+ MUSH(4, 5) ; MUSH(5, 7) ; MUSH(6, 9) ; MUSH(7, 13) ;
+ MUSH(8, 5) ; MUSH(9, 7) ; MUSH(10, 9) ; MUSH(11, 13) ;
+ }
+ for (i = 0 ; i < 8 ; i++) z[i] ^= t[i+4] ;
+ }
+ for (i = 0 ; i < 8 ; i++) uint32_pack(ctx->out + (i<<2), z[i]) ;
+}
+
+void surf (SURFSchedule_ref ctx, char *s, unsigned int n)
+{
+ {
+ register unsigned int i = 32 - ctx->pos ;
+ if (n < i) i = n ;
+ byte_copy(s, i, ctx->out + ctx->pos) ;
+ s += i ; n -= i ; ctx->pos += i ;
+ }
+ while (n > 32)
+ {
+ surfit(ctx) ;
+ byte_copy(s, 32, ctx->out) ;
+ s += 32 ; n -= 32 ;
+ }
+ if (!n) return ;
+ surfit(ctx) ;
+ byte_copy(s, n, ctx->out) ;
+ ctx->pos = n ;
+}
diff --git a/src/librandom/surf_autoinit.c b/src/librandom/surf_autoinit.c
new file mode 100644
index 0000000..920612b
--- /dev/null
+++ b/src/librandom/surf_autoinit.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <skalibs/surf.h>
+
+void surf_autoinit (SURFSchedule_ref ctx, char *s, unsigned int n)
+{
+ if (!ctx->in[0] && !ctx->in[1] && !ctx->in[2] && !ctx->in[3])
+ surf_init(ctx) ;
+ surf(ctx, s, n) ;
+}
diff --git a/src/librandom/surf_here.c b/src/librandom/surf_here.c
new file mode 100644
index 0000000..ebbdffb
--- /dev/null
+++ b/src/librandom/surf_here.c
@@ -0,0 +1,8 @@
+/* ISC license. */
+
+/* MT-unsafe */
+
+#include <skalibs/surf.h>
+#include "random-internal.h"
+
+SURFSchedule surf_here = SURFSCHEDULE_ZERO ;
diff --git a/src/librandom/surf_init.c b/src/librandom/surf_init.c
new file mode 100644
index 0000000..3662fa8
--- /dev/null
+++ b/src/librandom/surf_init.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <skalibs/surf.h>
+
+void surf_init (SURFSchedule_ref ctx)
+{
+ char s[160] ;
+ surf_makeseed(s) ;
+ surf_sinit(ctx, s) ;
+}
diff --git a/src/librandom/surf_makeseed.c b/src/librandom/surf_makeseed.c
new file mode 100644
index 0000000..adae9a4
--- /dev/null
+++ b/src/librandom/surf_makeseed.c
@@ -0,0 +1,35 @@
+/* ISC license. */
+
+#include <unistd.h>
+#include <skalibs/uint32.h>
+#include <skalibs/tai.h>
+#include <skalibs/sha1.h>
+#include <skalibs/surf.h>
+
+void surf_makeseed (char *s)
+{
+ SHA1Schedule bak = SHA1_INIT() ;
+ {
+ tain_t now ;
+ char tmp[20 + TAIN_PACK] ;
+ uint32 x = getpid() ;
+ uint32_pack(tmp, x) ;
+ x = getppid() ;
+ uint32_pack(tmp + 4, x) ;
+ tain_now(&now) ;
+ tain_pack(tmp + 8, &now) ;
+ sha1_update(&bak, tmp, 8 + TAIN_PACK) ;
+ sha1_final(&bak, tmp) ;
+ sha1_init(&bak) ;
+ sha1_update(&bak, tmp, 20) ;
+ }
+ {
+ char i = 0 ;
+ for (; i < 8 ; i++)
+ {
+ SHA1Schedule ctx = bak ;
+ sha1_update(&ctx, &i, 1) ;
+ sha1_final(&ctx, s + 20*i) ;
+ }
+ }
+}
diff --git a/src/librandom/surf_sinit.c b/src/librandom/surf_sinit.c
new file mode 100644
index 0000000..ae7f480
--- /dev/null
+++ b/src/librandom/surf_sinit.c
@@ -0,0 +1,13 @@
+/* ISC license. */
+
+#include <skalibs/uint32.h>
+#include <skalibs/surf.h>
+
+void surf_sinit (SURFSchedule_ref ctx, char const *s)
+{
+ SURFSchedule zero = SURFSCHEDULE_ZERO ;
+ register unsigned int i = 4 ;
+ *ctx = zero ;
+ for (; i < 12 ; i++) uint32_unpack(s + (i<<2) - 16, ctx->in + i) ;
+ for (i = 0 ; i < 32 ; i++) uint32_unpack(s + 32 + (i<<2), ctx->seed + i) ;
+}
diff --git a/src/librandom/unidevrandom.c b/src/librandom/unidevrandom.c
new file mode 100644
index 0000000..fb7b6b8
--- /dev/null
+++ b/src/librandom/unidevrandom.c
@@ -0,0 +1,38 @@
+/* ISC license. */
+
+#include <skalibs/sysdeps.h>
+#include <skalibs/unirandomdev.h>
+#include <skalibs/unirandom.h>
+
+#ifdef SKALIBS_HASDEVRANDOM
+
+#include "random-internal.h"
+
+int unidevrandom_init (union unirandominfo *u)
+{
+ return unirandomdev_sinit(u, "/dev/random") ;
+}
+
+int unirandom_register_devrandom (unirandom *u)
+{
+ unirandom_register(u, &unidevrandom_init, &unirandomdev_finish, &unirandomdev_readb, &unirandomdev_readnb) ;
+ return 1 ;
+}
+
+#else
+
+#include <errno.h>
+
+int unidevrandom_init (union unirandominfo *u)
+{
+ (void)u ;
+ return (errno = ENOSYS, 0) ;
+}
+
+int unirandom_register_devrandom (unirandom *u)
+{
+ (void)u ;
+ return (errno = ENOSYS, 0) ;
+}
+
+#endif
diff --git a/src/librandom/unidevurandom.c b/src/librandom/unidevurandom.c
new file mode 100644
index 0000000..d601ea0
--- /dev/null
+++ b/src/librandom/unidevurandom.c
@@ -0,0 +1,38 @@
+/* ISC license. */
+
+#include <skalibs/sysdeps.h>
+#include <skalibs/unirandomdev.h>
+#include <skalibs/unirandom.h>
+
+#ifdef SKALIBS_HASDEVURANDOM
+
+#include "random-internal.h"
+
+int unidevurandom_init (union unirandominfo *u)
+{
+ return unirandomdev_sinit(u, "/dev/urandom") ;
+}
+
+int unirandom_register_devurandom (unirandom *u)
+{
+ unirandom_register(u, &unidevurandom_init, &unirandomdev_finish, &unirandomdev_readb, &unirandomdev_readnb) ;
+ return 1 ;
+}
+
+#else
+
+#include <errno.h>
+
+int unidevurandom_init (union unirandominfo *u)
+{
+ (void)u ;
+ return (errno = ENOSYS, 0) ;
+}
+
+int unirandom_register_devurandom (unirandom *u)
+{
+ (void)u ;
+ return (errno = ENOSYS, 0) ;
+}
+
+#endif
diff --git a/src/librandom/unihasegd.c b/src/librandom/unihasegd.c
new file mode 100644
index 0000000..ab263c7
--- /dev/null
+++ b/src/librandom/unihasegd.c
@@ -0,0 +1,38 @@
+/* ISC license. */
+
+#include <skalibs/config.h>
+#include <skalibs/unirandomegd.h>
+#include <skalibs/unirandom.h>
+
+#ifdef SKALIBS_EGD
+
+#include "random-internal.h"
+
+int unihasegd_init (union unirandominfo *u)
+{
+ return unirandomegd_sinit(u, SKALIBS_EGD) ;
+}
+
+int unirandom_register_hasegd (unirandom *u)
+{
+ unirandom_register(u, &unihasegd_init, &unirandomegd_finish, &unirandomegd_readb, &unirandomegd_readnb) ;
+ return 1 ;
+}
+
+#else
+
+#include <errno.h>
+
+int unihasegd_init (union unirandominfo *u)
+{
+ (void)u ;
+ return (errno = ENOSYS, 0) ;
+}
+
+int unirandom_register_hasegd (unirandom *u)
+{
+ (void)u ;
+ return (errno = ENOSYS, 0) ;
+}
+
+#endif
diff --git a/src/librandom/unirandom_finish.c b/src/librandom/unirandom_finish.c
new file mode 100644
index 0000000..14c4411
--- /dev/null
+++ b/src/librandom/unirandom_finish.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/unirandom.h>
+
+int unirandom_finish (unirandom_ref u)
+{
+ if (!u->initted) return 1 ;
+ if (!(*u->finish)(&u->data)) return 0 ;
+ u->initted = 0 ;
+ return 1 ;
+}
diff --git a/src/librandom/unirandom_init.c b/src/librandom/unirandom_init.c
new file mode 100644
index 0000000..711a4ac
--- /dev/null
+++ b/src/librandom/unirandom_init.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/unirandom.h>
+
+int unirandom_init (unirandom_ref u)
+{
+ if (u->initted) return 1 ;
+ if (!(*u->init)(&u->data)) return 0 ;
+ u->initted = 1 ;
+ return 1 ;
+}
diff --git a/src/librandom/unirandom_readb.c b/src/librandom/unirandom_readb.c
new file mode 100644
index 0000000..cbe45a6
--- /dev/null
+++ b/src/librandom/unirandom_readb.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/unirandom.h>
+
+unsigned int unirandom_readb (unirandom_ref u, char *s, unsigned int n)
+{
+ if (!u->initted && !unirandom_init(u)) return 0 ;
+ return (*u->readb)(&u->data, s, n) ;
+}
diff --git a/src/librandom/unirandom_readnb.c b/src/librandom/unirandom_readnb.c
new file mode 100644
index 0000000..f0cc38e
--- /dev/null
+++ b/src/librandom/unirandom_readnb.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/unirandom.h>
+
+unsigned int unirandom_readnb (unirandom_ref u, char *s, unsigned int n)
+{
+ if (!u->initted && !unirandom_init(u)) return 0 ;
+ return (*u->readnb)(&u->data, s, n) ;
+}
diff --git a/src/librandom/unirandom_register.c b/src/librandom/unirandom_register.c
new file mode 100644
index 0000000..35f7411
--- /dev/null
+++ b/src/librandom/unirandom_register.c
@@ -0,0 +1,16 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/unirandom.h>
+#include "random-internal.h"
+
+void unirandom_register (unirandom_ref u, int (*init) (union unirandominfo *), int (*finish) (union unirandominfo *), unsigned int (*readb) (union unirandominfo *, char *, unsigned int), unsigned int (*readnb) (union unirandominfo *, char *, unsigned int))
+{
+ unirandom zero = UNIRANDOM_ZERO ;
+ *u = zero ;
+ u->init = init ;
+ u->finish = finish ;
+ u->readb = readb ;
+ u->readnb = readnb ;
+ u->initted = 0 ;
+}
diff --git a/src/librandom/unirandomdev.c b/src/librandom/unirandomdev.c
new file mode 100644
index 0000000..4a22514
--- /dev/null
+++ b/src/librandom/unirandomdev.c
@@ -0,0 +1,50 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/unirandom.h>
+#include <skalibs/unirandomdev.h>
+
+int unirandomdev_sinit (union unirandominfo *u, char const *file)
+{
+ register int fd = open_read(file) ;
+ if (fd < 0) return 0 ;
+ if (coe(fd) < 0)
+ {
+ register int e = errno ;
+ fd_close(fd) ;
+ errno = e ;
+ return 0 ;
+ }
+ buffer_init(&u->device.b, &buffer_read, fd, u->device.buf, RANDOMBUF_BUFSIZE) ;
+ u->device.nb = 1 ;
+ return 1 ;
+}
+
+int unirandomdev_finish (union unirandominfo *u)
+{
+ return fd_close(buffer_fd(&u->device.b)) < 0 ;
+}
+
+static unsigned int unirandomdev_read (union unirandominfo *u, char *s, unsigned int n, unsigned int h)
+{
+ unsigned int w = 0 ;
+ if (u->device.nb != h)
+ {
+ if ((h ? ndelay_on(buffer_fd(&u->device.b)) : ndelay_off(buffer_fd(&u->device.b))) < 0) return 0 ;
+ u->device.nb = h ;
+ }
+ buffer_getall(&u->device.b, s, n, &w) ;
+ return w ;
+}
+
+unsigned int unirandomdev_readb (union unirandominfo *u, char *s, unsigned int n)
+{
+ return unirandomdev_read(u, s, n, 0) ;
+}
+
+unsigned int unirandomdev_readnb (union unirandominfo *u, char *s, unsigned int n)
+{
+ return unirandomdev_read(u, s, n, 1) ;
+}
diff --git a/src/librandom/unirandomegd.c b/src/librandom/unirandomegd.c
new file mode 100644
index 0000000..a340f06
--- /dev/null
+++ b/src/librandom/unirandomegd.c
@@ -0,0 +1,37 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/randomegd.h>
+#include <skalibs/unirandom.h>
+#include <skalibs/unirandomegd.h>
+
+int unirandomegd_sinit (union unirandominfo *u, char const *path)
+{
+ register int s = randomegd_open(path) ;
+ if (s == -1) return 0 ;
+ if (coe(s) == -1)
+ {
+ register int e = errno ;
+ fd_close(s) ;
+ errno = e ;
+ return 0 ;
+ }
+ u->egd.fd = s ;
+ return 1 ;
+}
+
+int unirandomegd_finish (union unirandominfo *u)
+{
+ return !fd_close(u->egd.fd) ;
+}
+
+unsigned int unirandomegd_readb (union unirandominfo *u, char *s, unsigned int n)
+{
+ return randomegd_readb(u->egd.fd, s, n) ;
+}
+
+unsigned int unirandomegd_readnb (union unirandominfo *u, char *s, unsigned int n)
+{
+ return randomegd_readnb(u->egd.fd, s, n) ;
+}
diff --git a/src/librandom/unisurf.c b/src/librandom/unisurf.c
new file mode 100644
index 0000000..334d044
--- /dev/null
+++ b/src/librandom/unisurf.c
@@ -0,0 +1,23 @@
+/* ISC license. */
+
+#include <skalibs/surf.h>
+#include <skalibs/unirandom.h>
+#include <skalibs/unisurf.h>
+
+int unisurf_sinit (union unirandominfo *u, char const *s)
+{
+ surf_sinit(&u->surf_ctx, s) ;
+ return 1 ;
+}
+
+int unisurf_finish (union unirandominfo *u)
+{
+ (void)u ;
+ return 1 ;
+}
+
+unsigned int unisurf_read (union unirandominfo *u, char *s, unsigned int n)
+{
+ surf(&u->surf_ctx, s, n) ;
+ return n ;
+}
diff --git a/src/librandom/unisurf_init.c b/src/librandom/unisurf_init.c
new file mode 100644
index 0000000..d5a1f73
--- /dev/null
+++ b/src/librandom/unisurf_init.c
@@ -0,0 +1,18 @@
+/* ISC license. */
+
+#include <skalibs/surf.h>
+#include "random-internal.h"
+#include <skalibs/unirandom.h>
+#include <skalibs/unisurf.h>
+
+int unisurf_init (union unirandominfo *u)
+{
+ surf_init(&u->surf_ctx) ;
+ return 1 ;
+}
+
+int unirandom_register_surf (unirandom *u)
+{
+ unirandom_register(u, &unisurf_init, &unisurf_finish, &unisurf_read, &unisurf_read) ;
+ return 1 ;
+}