snac2

Fork of https://codeberg.org/grunfink/snac2
git clone https://git.inz.fi/snac2
Log | Files | Refs | README | LICENSE

xs_random.h (1816B)


      1 /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */
      2 
      3 #ifndef _XS_RANDOM_H
      4 
      5 #define _XS_RANDOM_H
      6 
      7 unsigned int xs_rnd_int32_d(unsigned int *seed);
      8 void *xs_rnd_buf(void *buf, int size);
      9 
     10 #ifdef XS_IMPLEMENTATION
     11 
     12 #include <stdio.h>
     13 #include <sys/time.h>
     14 #include <unistd.h>
     15 #include <stdlib.h>
     16 
     17 unsigned int xs_rnd_int32_d(unsigned int *seed)
     18 /* returns a deterministic random integer. If seed is NULL, uses a static one */
     19 {
     20     static unsigned int s = 0;
     21 
     22     if (seed == NULL)
     23         seed = &s;
     24 
     25     if (*seed == 0) {
     26         struct timeval tv;
     27 
     28         gettimeofday(&tv, NULL);
     29         *seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
     30     }
     31 
     32     /* Linear congruential generator by Numerical Recipes */
     33     *seed = (*seed * 1664525) + 1013904223;
     34 
     35     return *seed;
     36 }
     37 
     38 
     39 void *xs_rnd_buf(void *buf, int size)
     40 /* fills buf with random data */
     41 {
     42 #ifdef __OpenBSD__
     43 
     44     /* available since OpenBSD 2.2 */
     45     arc4random_buf(buf, size);
     46 
     47 #else
     48 
     49     FILE *f;
     50     int done = 0;
     51 
     52     if ((f = fopen("/dev/urandom", "r")) != NULL) {
     53         /* fill with great random data from the system */
     54         if (fread(buf, size, 1, f) == 1)
     55             done = 1;
     56 
     57         fclose(f);
     58     }
     59 
     60     if (!done) {
     61         /* fill the buffer with poor quality, deterministic data */
     62         unsigned int s   = 0;
     63         unsigned char *p = (unsigned char *)buf;
     64         int n            = size / sizeof(s);
     65 
     66         /* fill with full integers */
     67         while (n--) {
     68             xs_rnd_int32_d(&s);
     69             memcpy(p, &s, sizeof(s));
     70             p += sizeof(s);
     71         }
     72 
     73         if ((n = size % sizeof(s))) {
     74             /* fill the remaining */
     75             xs_rnd_int32_d(&s);
     76             memcpy(p, &s, n);
     77         }
     78     }
     79 
     80 #endif /* __OpenBSD__ */
     81 
     82     return buf;
     83 }
     84 
     85 
     86 #endif /* XS_IMPLEMENTATION */
     87 
     88 #endif /* XS_RANDOM_H */