]> diplodocus.org Git - nmh/blob - sbr/m_rand.c
Another pass at cleaning up (some of) the manpages.
[nmh] / sbr / m_rand.c
1 /*
2 * m_rand -- provides pseudorandom bytes
3 *
4 * This code is Copyright (c) 2012, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
7 */
8
9 #include <stdlib.h> /* for abs(), srand(), rand(), arc4random() */
10 #include <stdio.h> /* for fopen(), fread(), fclose() */
11 #include <unistd.h> /* for getpid() */
12 #include <time.h> /* for time() */
13
14 #include <config.h>
15
16 #if !HAVE_ARC4RANDOM
17 static int seeded = 0;
18 #endif
19
20
21 int
22 m_rand (unsigned char *buf, size_t n) {
23 #if !HAVE_ARC4RANDOM
24 if (! seeded) {
25 FILE *devurandom;
26 unsigned int seed;
27
28 if ((devurandom = fopen ("/dev/urandom", "r"))) {
29 if (fread (&seed, sizeof (seed), 1, devurandom) == 1) seeded = 1;
30 fclose (devurandom);
31 }
32
33 if (! seeded) {
34 /* This seed calculation is from Helmut G. Katzgraber, "Random
35 Numbers in Scientific Computing: An Introduction",
36 arXiv:1005.4117v1 [physics.comp-ph], 22 May 2010, p. 19.
37 time() and getpid() shouldn't fail on POSIX platforms. */
38 seed = abs ((int) ((time (0) * 181 * ((getpid ()-83) * 359)) % 104729));
39 seeded = 1;
40 }
41
42 srand (seed);
43 }
44
45 while (n > 0) {
46 int rnd = rand ();
47 unsigned char *rndp = (unsigned char *) &rnd;
48 unsigned int i;
49
50 for (i = 0; i < sizeof rnd && n > 0; ++i, --n) {
51 *buf++ = *rndp++;
52 }
53 }
54 #else
55 arc4random_buf(buf, n);
56 #endif
57
58 return 0;
59 }