#!/usr/bin/env bash
#
#       oeautostart
#       Version 0.1
#
# This is an automation tool for the EMAC OE 5.0 SDK
#
# Makes the passed program run automatically on boot of the system
#
# Usage: oeautostart [OPTION] [-i program_to_install [priority] | -r program_to_remove]
#
# kyoungmeyer@emacinc.com
# September 12, 2013
#
# Copyright (C) 2013, EMAC, Inc.
# All rights reserved.      
#

# Constants
TEMPLATE="/etc/emac/oeautostart-template"
TEMPLATE_HOST="/opt/emac/5.1/share/oeautostart-template"

#Default priority
SPRIORITY=91
KPRIORITY=9
PROGRAM=""
PROG_PATH=""
regex='^[0-9]+$'

Version="1.1.0"

PriStart=
PriEnd=
Command=
ARGUMENT=""

#TOOLS
BASENAME="/usr/bin/env basename"
CP="/usr/bin/env cp"
SED="/usr/bin/env sed"
MV="/usr/bin/env mv"
MKTEMP="/usr/bin/env mktemp" 
CHMOD="/usr/bin/env chmod"
RMDIR="/usr/bin/env rmdir"
RM="/usr/bin/env rm"
UPDATERCD="/usr/bin/env update-rc.d"
CHKCONFIG="/usr/bin/env chkconfig"
######
RCD=0
CHKC=0
if hash $UPDATERCD 2>/dev/null; then
    RCD=1
elif hash $CHKCONFIG 2>/dev/null; then
    CHKC=1
else
    echo "Error: no supported init sequence program found"
    exit 1
fi
version () { 
	echo "$(basename $0) (EMAC OE Automation Tools) Version $Version"
	echo "Copyright (C) 2013-2014 EMAC, Inc.  All rights reserved."; 
}

help () {
    echo "Usage: oeautostart [OPTIONS] [-i PROGRAM | -u PROGRAM | -r PROGRAM]"
    echo "Make a PROGRAM run at the startup of the board"
    echo
    echo "Example: oeautostart -i startup_program"
    echo "Example: oeautostart -i startup_program 97 3"
    echo
    echo "Example: oeautostart -r startup_program"
    echo "Example: oeautostart -f -r startup_program"
    echo
    echo "Example: oeautostart -u startup_program"
    echo
    echo "Options:"
    echo "  -i      Install PROGRAM into init sequence. Optionally add Start"
    echo "          Priority number and Kill Priority number, in that order."
    echo "  -r      Remove PROGRAM from init sequence."
    echo "  -u      Overwrite current version of PROGRAM in init sequence with"
    echo "          version passed to $(basename $0). Optionally add Start"
    echo "          Priority number and Kill Priority number, in that order."
    echo "  -f      Force execution without user input. Must be placed ahead of"
    echo "          any -i, -u, or -r flags."
    echo "  -x      Force chmod +x (if needed) without user input. Must be placed ahead of "
    echo "          any -i, -u, or -r flags."
    echo "  -v      Display version info and exit."
    echo "  -h      Display this help and exit."
    echo
    version
    echo
    }
showerr()
{
    printf "\e[01;31mERROR: \e[01;37m${*}\e[0m\n"
    exit 9
}
check_tool()
{
    $1 > /dev/null 2>&1

    if [ $? == "127" ]
    then
        showerr "${2} command not found in path.  Exiting."
    fi
}
check_tools()
{
    check_tool "$RM" "rm"
    check_tool "$CP" "cp"
    check_tool "$MV" "mv"
    check_tool "$CHMOD" "chmod"
    check_tool "$SED" "sed"
    check_tool "$BASENAME" "basename"
    check_tool "$MKTEMP" "mktemp"
    check_tool "$RMDIR" "rmdir"
}
get_prog_name () {
    PROGRAM="$($BASENAME $ARGUMENT)"
    PROG_PATH="${ARGUMENT%/*}"
}
update_add () {
    if [[ $RCD -eq 1 ]]; then
        $UPDATERCD $1 defaults $2 $3
        if [[ $? -ne 0 ]];then
            error_out "update-rc.d failed"
            exit 5
        fi
    elif [[ $CHKC -eq 1 ]]; then
        $CHKCONFIG --add $1
        if [[ $? -ne 0 ]];then
            error_out "chkconfig failed"
            exit 5
        fi
    else
        # This error will almost certainly never happen (famous last words)
        echo "Error: nothing was added"
        exit 6
    fi
}
update_remove () {
    if [[ $RCD -eq 1 ]]; then
        $UPDATERCD $1 remove
        if [[ $? -ne 0 ]];then
            error_out "update-rc.d failed"
            exit 5
        fi
    elif [[ $CHKC -eq 1 ]]; then
        $CHKCONFIG --del $1
        if [[ $? -ne 0 ]];then
            error_out "chkconfig failed"
            exit 5
        fi
    else
        # This error will almost certainly never happen (famous last words)
        echo "Error: nothing was removed"
        exit 6
    fi
}
install () {
    # Check if boot file already exists, update if needed
    if [[ -f "/etc/init.d/$PROGRAM" ]]; then
        if [[ $FORCE -eq 0 ]]; then
            echo "Program:'$PROGRAM' already exists in the startup directoty. Would you like to update it with this version? (y/n)"
            read RESPONSE
            if [[ $RESPONSE == "y" ]] || [[ $RESPONSE == "Y" ]]; then
                $RM -f "/etc/init.d/$PROGRAM"
                update_remove "$PROGRAM"
            else
                echo "Exiting...";exit 0
            fi
        else
            $RM -f "/etc/init.d/$PROGRAM"
            update_remove "$PROGRAM"
        fi

    fi
    core $PriStart $PriEnd 
}

core () {

    if [[ "$PROG_PATH" == "$PROGRAM" ]]; then
        PROG_PATH=""
    fi
    
    if [[ $1 != "" ]]; then
        if [[ $1 =~ $regex ]]; then
            SPRIORITY=$1
        else
            error_out "Start priority must be an integer"
            exit 2
        fi
    fi
    if [[ $2 != "" ]]; then
        if [[ $1 =~ $regex ]]; then
            KPRIORITY=$2
        else
            error_out "Kill priority must be an integer"
            exit 2
        fi
    fi
   
    # Make sure init.d template exists
    if [[ ! -f "$TEMPLATE" ]];then
        if [[ ! -f "$TEMPLATE_HOST" ]]; then
            echo "No init template found" 1>&2
            exit 3
        else
            TEMPLATE="$TEMPLATE_HOST"
        fi
    fi
    
    # Make sure the user program is found
    if [[ "$PROG_PATH" == "" ]]; then
        if [[ -f "/usr/local/bin/$PROGRAM" ]]; then
            PROG_PATH="/usr/local/bin"
        elif [[ -f "/usr/bin/$PROGRAM" ]]; then
            PROG_PATH="/usr/bin"
        elif [[ -f "/bin/$PROGRAM" ]]; then
            PROG_PATH="/bin"
        elif [[ -f "$PWD/$PROGRAM" ]]; then
            PROG_PATH="$PWD"
        else
            error_out "$PROGRAM not found, please enter full path of file or place $PROGRAM in /usr/local/bin" 1>&2
            exit 4
        fi
    fi
    ##Debug echo
    #echo "$PROG_PATH"

    # Make sure the user program is executable
    if [[ ! -x "$PROG_PATH/$PROGRAM" ]]; then
        if [[ "$F_EXE" -eq 0 ]]; then
            echo "$PROGRAM is not executable. Would you like to make it executable? (y/n)"
            read RESPONSE2
            if [[ $RESPONSE2 == "y" ]] || [[ $RESPONSE2 == "Y" ]]; then
                $CHMOD +x "$PROG_PATH/$PROGRAM"
            else
                echo "Startup programs must be executable; this utility will now exit without making any changes...";exit 0
            fi
        else
            $CHMOD +x "$PROG_PATH/$PROGRAM"
        fi
    fi
    
    # Make sure there is a valid temp file to use
    TMP="$($MKTEMP -d)"
    if [[ ! -d $TMP ]]; then
        error_out "Temp directory not created correctly"
        exit 3
    fi
    
    # Copy the template init.d file and rename it
    $CP "$TEMPLATE" "$TMP/$PROGRAM"
    
    # Replace references to template with user program
    $SED -i "s%TEMPLATE%$PROGRAM%g" "$TMP/$PROGRAM"
    $SED -i "s%PPATH%$PROG_PATH%g" "$TMP/$PROGRAM"

    $MV "$TMP/$PROGRAM" "/etc/init.d/$PROGRAM"
    $CHMOD +x "/etc/init.d/$PROGRAM"
    
    # Make/update symlinks to init.d script
    update_add "$PROGRAM" $SPRIORITY $KPRIORITY
    
    echo " $PROGRAM successfully installed as a startup program."

    $RMDIR "$TMP"
}

update () {
    if [[ -f /etc/init.d/"$PROGRAM" ]]; then
        F_EXE=1
        $RM -f /etc/init.d/"$PROGRAM"
        update_remove "$PROGRAM"
        core $PriStart $PriEnd

    else
        error_out "$PROGRAM does not exist as a startup program. Cannot update." 1>&2
        exit 4
    fi
}

remove_init () 
{
    REMOVIT=0

    if [[ -f /etc/init.d/"$PROGRAM" ]]; then
        if [[ $FORCE -eq 0 ]]; then
            echo "Are you sure you want to remove this boot file? (y/n)"
            read RESPONSE

            if [[ $RESPONSE == "y" ]] || [[ $RESPONSE == "Y" ]]; then
		        REMOVIT=1
            else
                echo "Exiting...";exit 0
            fi
        else
            REMOVIT=1
        fi
    fi

	if [ $REMOVIT = "1" ]; then
            $RM -f "/etc/init.d/$PROGRAM"
            update_remove "$PROGRAM"

    else
        error_out "$PROGRAM is not an installed boot file" 1>&2
        exit 4
    fi
    
    exit 0
}

error_out () {
    txtbld="\e[01;37m"
    bldred="\e[01;31m"
    txtwht="\e[0;37m"
    txtrst="\e[0m"

    echo -e "${bldred}ERROR:${txtrst}${txtwht} $1${txtrst}"
}

if [[ $UID -ne 0 ]]; then
    error_out "This program must be run as root" 1>&2
    exit 1
fi

options=':i:r:u:vhfx'
options_found=0

FORCE=0
F_EXE=0

check_tools
if [[ $1 == "--help" ]]; then
    help
    exit 0
fi
if [[ $1 == "--version" ]]; then
    version
    exit 0
fi

while getopts $options opt
do
    options_found=1
    case $opt in
        f   ) FORCE=1;;
        x   ) F_EXE=1;;
        i   ) ARGUMENT=$OPTARG; Command="install";;
        r   ) ARGUMENT=$OPTARG; Command="remove_init";;
        u   ) ARGUMENT=$OPTARG; Command="update";;
        v   ) version; exit 0;;
        h   ) help; exit 0;;
        \?  ) error_out "Invalid option: -$OPTARG" >&2; help;  exit 1;;
        :   ) error_out "Option -$OPTARG requires an argument" >&2; help; exit 1;;
    esac
done
shift $(($OPTIND - 1))
PriStart=$1
PriEnd=$2
if (( !options_found ))
then
    error_out "Please enter a valid option"
    help
    exit 1
fi

oemntrw
get_prog_name
${Command}

exit 0

