#!/bin/sh
set -e

# https://lkml.org/lkml/2018/4/12/711
# https://github.com/boot2docker/boot2docker/pull/1322

if [ "$(id -u)" != 0 ]; then
	echo >&2 "error: must be root to invoke $0"
	exit 1
fi

# https://github.com/jirka-h/haveged/blob/1.9.4/init.d/sysv.lsb

PIDFILE='/var/run/haveged.pid'
pid() {
	if [ -s "$PIDFILE" ]; then
		local pid
		pid="$(cat "$PIDFILE")"
		if ps "$pid" > /dev/null 2>&1; then
			echo "$pid"
			return 0
		fi
	fi
	return 1
}

start() {
	if pid="$(pid)"; then
		echo >&2 "error: haveged is already running ($pid)"
		exit 1
	fi

	echo 'Starting haveged'

	mkdir -p /var/lib/boot2docker/log

	# https://github.com/jirka-h/haveged/blob/1.9.4/init.d/sysv.lsb#L41
	haveged -w 1024 -v 1 -p "$PIDFILE"
}

stop() {
	if pid="$(pid)"; then
		echo "Stopping haveged ($pid)"
		kill "$pid"
	fi
}

restart() {
	stop
	start
}

# only start the daemon if it's determined that we probably need to
conditional() {
	# https://bugs.debian.org/923675#72
	if [ -e /sys/devices/virtual/misc/hw_random/rng_current ] && rngCurrent="$(cat /sys/devices/virtual/misc/hw_random/rng_current)" && [ "${rngCurrent:-none}" != 'none' ]; then
		# hardware RNG likely present, do not start software RNG
		return
	fi
	if grep -q '^flags\b.*\brdrand\b' /proc/cpuinfo; then
		# CPU has RNG functionality, do not start software RNG
		return
	fi

	# given the default poolsize of 4096, 120 is ~3% of the total pool
	if currentEntropy="$(cat /proc/sys/kernel/random/entropy_avail)" && [ "$currentEntropy" -gt 120 ]; then
		# if we appear to have an OK amount of entropy already, skip software RNG
		return
	fi

	# "fire it up"
	start
}

case "$1" in
	start|stop|restart|conditional) "$1" ;;
	*) echo "Usage $0 {start|stop|restart|conditional}"; exit 1 ;;
esac
