1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
// version 20230126
// public domain
// djb
// planned long-term cleanup:
// once all systems support getrandom() via sys/random.h,
// get rid of the other options and the SIGSYS handling
#include <unistd.h>
// automatic-alternatives 5
#ifdef getrandom_wrapper_5
#include "getrandom_wrapper.h"
int getrandom_wrapper_ready(void)
{
return 0;
}
void getrandom_wrapper(void *x,long long xbytes)
{
for (;;) pause();
}
#else
#include <errno.h>
#include <signal.h>
#ifdef getrandom_wrapper_1
#include <sys/random.h>
#endif
#ifdef getrandom_wrapper_2
#include <linux/random.h>
#endif
#ifdef getrandom_wrapper_3
#include <syscall.h>
#define getrandom(a,b,c) syscall(SYS_getrandom,a,b,c)
#endif
#ifdef getrandom_wrapper_4
#include <syscall.h>
#define getrandom(a,b,c) syscall(__NR_getrandom,a,b,c)
#endif
#include "getrandom_wrapper.h"
static int getrandom_wrapper_ready_core(void)
{
char ch;
int r;
for (;;) {
errno = 0;
r = getrandom(&ch,1,0);
if (r == 1) return 1;
if (r == -1 && errno == ENOSYS) return 0;
if (r == -1 && errno == EPERM) return 0; // QNAP bug
if (r == -1 && errno == EINVAL) return 0;
}
}
int getrandom_wrapper_ready(void)
{
struct sigaction old_sigsys;
int result;
sigaction(SIGSYS,0,&old_sigsys);
signal(SIGSYS,SIG_IGN);
result = getrandom_wrapper_ready_core();
sigaction(SIGSYS,&old_sigsys,0);
return result;
}
void getrandom_wrapper(void *x,long long xbytes)
{
while (xbytes > 0) {
int todo = 1048576;
if (xbytes < 1048576) todo = xbytes;
todo = getrandom(x,todo,0);
if (todo < 1) {
sleep(1);
continue;
}
x += todo;
xbytes -= todo;
}
}
#endif
|