/*
 * waitforrand.c: Wait until OpenSSL's RNG is ready.  Mostly useful in
 * startup scripts for ensuring that prngd has started up and seeded itself
 * before attempting to start up daemons that depend on the RNG.
 *
 * Compile with: cc -o waitforrand waitforrand.c \
 *   -L/usr/local/ssl/lib -I/usr/local/ssl/include -lcrypto [-lsocket]
 */

/*
 * Copyright (c) 2006 Darren Tucker
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdio.h>
#include <unistd.h>
#include <openssl/rand.h>

#define MAX_WAIT	60	/* seconds */

/* A list of places to look for a prngd/egd socket */
static char *egd_path[] = {
	"/var/run/egd-pool",
	"/dev/egd-pool",
	"/etc/egd-pool",
	"/etc/entropy",
	NULL
};

int
main(void)
{
	int ready = 0, count = 0, i;
	unsigned char buf[1];

	if (RAND_status() == 1)
		exit(0);	/* RNG ready */

	printf("Waiting for random source to become ready: ");
	fflush(stdout);

	while (ready != 1 && count++ < MAX_WAIT) {
		for (i = 0; egd_path[i] != NULL; i++) {
			ready = RAND_query_egd_bytes(egd_path[i], buf, 1);
			if (ready == 1)
				break;
		}
		sleep(1);
	}

	if (ready == 1) {
		printf("ready.\n");
		exit(0);
	} else {
		printf("NOT READY\n");
		exit(1);
	}
}
