// version 20230126 // public domain // djb #include #include #include #include #include #include #include "devurandom_wrapper.h" static void wait_for_random(void) { int random_fd; struct pollfd p; if (access("/var/run/urandom-ready",F_OK) == 0) return; for (;;) { errno = 0; random_fd = open("/dev/random",O_RDONLY); if (random_fd >= 0) break; if (errno == ENOENT) return; sleep(1); } for (;;) { p.fd = random_fd; p.events = POLLIN; p.revents = 0; errno = 0; if (poll(&p,1,0) == 1) break; if (errno != EINTR) sleep(1); // e.g., ENOMEM } close(random_fd); } static int urandom_fd = -1; int devurandom_wrapper_ready(void) { wait_for_random(); for (;;) { errno = 0; urandom_fd = open("/dev/urandom",O_RDONLY); if (urandom_fd >= 0) break; if (errno == ENOENT) return 0; sleep(1); } fcntl(urandom_fd,F_SETFD,1); // O_CLOEXEC is better but limits portability and is not necessary here: // librandombytes runs *_ready only in static constructors return 1; } void devurandom_wrapper(void *x,long long xbytes) { while (xbytes > 0) { int todo = 1048576; if (xbytes < 1048576) todo = xbytes; todo = read(urandom_fd,x,todo); if (todo < 1) { sleep(1); continue; } x += todo; xbytes -= todo; } }