#!/bin/sh
#/
#/ \file
#/
#/ \brief       initialize or save random seed
#/
#/ \author      Arthur
#/
#/ \date        June 9, 2013
#/
#/ \version     0.2
#/


################################################################################
#                                                                              #
#                              C O N S T A N T S                               #
#                                                                              #
################################################################################


RC_NAME=`basename $0 2>/dev/null`
RC_DIR=`dirname \`readlink -qe $0\` 2>/dev/null`
RC_VER="0.2"
RC_ID="setup random number generator"

SEED_FILE=/var/lib/misc/random-seed
POOL_FILE=/proc/sys/kernel/random/poolsize


################################################################################
#                                                                              #
#                               I N C L U D E S                                #
#                                                                              #
################################################################################


. $RC_DIR/include/rc_utils


################################################################################
#                                                                              #
#                              F U N C T I O N S                               #
#                                                                              #
################################################################################


#-------------------------------------------------------------------------------


#/
#/ Output script usage and exit.
#/
#/ \returns
#/
#/ Always exit code 1.
#/
usage()
{
    $ECHO "Usage: $RC_NAME [-n][-q][-v][-h][-V] [ACTION]"

    exit 1
}


#-------------------------------------------------------------------------------


#/
#/ Output script version and exit.
#/
#/ \returns
#/
#/ Always exit code 1.
#/
version()
{
    $ECHO "$RC_NAME $RC_VER"

    exit 1
}


#-------------------------------------------------------------------------------


#/
#/ Seed the random number generator, if possible, and refresh the random seed
#/ file of the system. The random number generator is fed the random seed file
#/ file only if that file exists.
#/
#/ \returns
#/
#/ Always 0.
#/
init()
{
    poolsz=0

    $ECHO_N "Initializing random number generator..."

    if test -f $SEED_FILE
    then
        $DRY_RUN cat $SEED_FILE >/dev/urandom
    else
        $DRY_RUN touch $SEED_FILE
        $DRY_RUN chmod 600 $SEED_FILE
    fi

    if test -r "$POOL_FILE"
    then
        poolsz=`cat $POOL_FILE`
    else
        poolsz=512
    fi
    $DRY_RUN dd if=/dev/urandom of=$SEED_FILE count=1 bs=$poolsz

    $ECHO
    return 0
}


#-------------------------------------------------------------------------------


#/
#/ Write random seed to file; to be used at a later time.
#/
#/ \returns
#/
#/ Always 0.
#/
save()
{
    poolsz=0

    $ECHO_N "Saving random seed..."

    if test -r "$POOL_FILE"
    then
        poolsz=`cat $POOL_FILE`
    else
        poolsz=512
    fi
    $DRY_RUN dd if=/dev/urandom of=$SEED_FILE count=1 bs=$poolsz
    $DRY_RUN touch $SEED_FILE
    $DRY_RUN chmod 600 $SEED_FILE

    $ECHO
    return 0
}


#-------------------------------------------------------------------------------


#/
#/ Save and re-seed the random number generator.
#/
#/ \returns
#/
#/ Return code 0 if re-seeding succeeded, otherwise 1.
#/
reinit()
{
    save && init
    return $?
}


#-------------------------------------------------------------------------------


#/
#/ Show current state of random number generator. The function outputs some
#/ basic details about the random number generator and tests whether there's
#/ any entropy in de RNG device files.
#/
#/ \returns
#/
#/ Always return code 0.
#/
status()
{
    poolsz=0
    poolsz_file=""
    seed_file=""
    ret=0

    if test -r "$POOL_FILE"
    then
        poolsz=`cat $POOL_FILE`
        poolsz_file=$POOL_FILE
    else
        poolsz="<unknown>"
        poolsz_file="<non-existant or inaccessible>"
    fi
    $ECHO   "Entropy pool size file: $poolsz_file"
    $ECHO   "     Entropy pool size: $poolsz"


    # test entropy of /dev/random and /dev/urandom (use non-blocking access):
    $ECHO_N "   Entropy /dev/random: "
    dd if=/dev/random iflag=nonblock count=4 bs=1 of=/dev/null 2>/dev/null
    if test $? -eq 0; then $ECHO "OK"; else $ECHO "None"; fi

    $ECHO_N "  Entropy /dev/urandom: "
    dd if=/dev/urandom iflag=nonblock count=4 bs=1 of=/dev/null 2>/dev/null
    if test $? -eq 0; then $ECHO "OK"; else $ECHO "None"; fi

    
    if test -f "$SEED_FILE"
    then
        seed_file=$SEED_FILE
    else
        seed_file="<unavailable>"
    fi
    $ECHO   "      Random-seed file: $seed_file"

    return 0
}


#-------------------------------------------------------------------------------


################################################################################
#                                                                              #
#                         S T A R T  O F  S C R I P T                          #
#                                                                              #
#                                                                              #
# Operation:                                                                   #
#                                                                              #
# o Process command line arguments.                                            #
# o Call appropriate ACTION function.                                          #
#                                                                              #
################################################################################

QUIET=0                 # quiet flag (0 or 1)
VERBOSE=0               # verbose flag (0 or 1)
DRY_RUN=""              # default is to actually execute commands

ACTION=""



#
# Handle command line OPTIONS.
#
while test $# -gt 0
do
    case "$1" in
    -n|--dry-run)
        DRY_RUN="$ECHO -e \n> "     # ensure we begin on a new line
        ;;
    -q|--quiet)
        QUIET=1
        exec >/dev/null             # mute stdout
        ;;
    -v|--verbose)
        VERBOSE=1
        ECHO_N=$ECHO                # don't inhibit newline;
                                    # this prevents clobbering of text
        ;;
    -h|--help)
        usage
        ;;
    -V|--version)
        version
        ;;
    -*)
        fatal "unknown option: $1"
        ;;
    *)                              # first non-OPTIONS argument
        break
        ;;
    esac
    shift
done

#
# Handle influential environment variables.
#
if test "$RC_VERBOSE" = "0" -o "$RC_VERBOSE" = "1"
then
    VERBOSE=$RC_VERBOSE
fi


#
# Determine what to do (ACTION).
#

# try to derive ACTION from script name: 
ACTION=`get_action $RC_NAME`


#
# Command line parameters MAY override the
# derived ACTION, if specified.
#
if test -n "$1"; then ACTION=$1; shift; fi

if test -n "$ACTION"
then
    case "$ACTION" in
    start)   init   ;;
    stop)    save   ;;
    restart) reinit ;;
    status)  status ;;
    *)
        fatal "unknown action: $ACTION"
        ;;
    esac
else
    fatal "missing action"
fi
