#!/bin/bash

#
# Name:		functions.sh
# Version:      1.0.5
#
# (c) 2016-2022, Rapidseedbox, alexey@rapidseedbox.com
#

export LANG=en_US

[ "${DEBUG}" = "yes" ] || DEBUG="no"

#
# Idea from
# http://www.cubicrace.com/2016/03/efficient-logging-mechnism-in-shell.html
#


#LOGFILE=SystemOut.log
#TMP_DIR="/var/tmp/support.$$"
TMP_DIR="/var/tmp/$( basename ${0} ).tmp.$$"
touch "${LOGFILE}"
tmp="${TMP_DIR}/${0}.tmp.$$"

function ENTRY(){
    local cfn="${FUNCNAME[1]}"
    local tstamp="$( date -u +"%d-%m-%Y %T %Z" )"
    local msg="> ${cfn} ${FUNCNAME}"
    echo -e "[${tstamp}] [DEBUG]\t${msg}" >> "${LOGFILE}"
}

function RETURN(){
    local cfn="${FUNCNAME[1]}"
    local tstamp="$( date -u +"%d-%m-%Y %T %Z" )"
    local msg="< ${cfn} ${FUNCNAME}"
    echo -e "[${tstamp}] [DEBUG]\t${msg}" >> "${LOGFILE}"
}

function INFO()
{
    local msg="${1}"
    local tstamp="$( date -u +"%d-%m-%Y %T %Z" )"
    echo -e "[${tstamp}] [INFO]\t${msg}" >> "${LOGFILE}"
}

function ERROR()
{
    local msg="${1}"
    local tstamp="$( date -u +"%d-%m-%Y %T %Z" )"
    echo -e "[${tstamp}] [ERROR]\t${msg}" >> "${LOGFILE}"
}

function DEBUG()
{
    local msg="${1}"
    local tstamp="$( date -u +"%d-%m-%Y %T %Z" )"
    echo -e "[${tstamp}] [DEBUG]\t${msg}" >> ${LOGFILE}
}

_get_ip () {
#    echo "$( ip route get 8.8.8.8 | head -1 | sed -e 's/.*\s*src\s*\([0-9.]*\).*$/\1/' )"
    echo "$( ip -o route get to 8.8.8.8 | sed -nre 's/.*\s+src\s+([0-9.]+).*/\1/p' )"
}

# --------------------------------------------------------------
# RSB custom code
# --------------------------------------------------------------
export IP="$( _get_ip )"
export DEV="$( ip route get 8.8.8.8 | grep '8.8.8.8' | sed -e 's/.*dev//' | awk '{print $1}' )"
export DATE="$( date +%Y-%m-%d:%H:%M:%S )"
export DEBIAN_FRONTEND=noninteractive


function L_LOG () {
    echo "-------------------------------------------------------------" >> "${LOGFILE}"
}

function LOG_INFO()
{
    local title
    local result=""
    [ -n "${1}" ] && title="${1}" || title="${JOB_NAME}"
    [ -n "${2}" ] && result="${2}"
    INFO "${title}"
    [ ! -z "${LOG}" ] && INFO "${LOG}"
    [ ! -z "${result}" ] && INFO "${result}"
    L_LOG
    LOG=""
}

function LOG_ERROR()
{
    local title
    local result=""
    [ -n "${1}" ] && title="${1}" || title="${JOB_NAME}"
    [ -n "${2}" ] && result="${2}"
    ERROR "${title}"
    [ ! -z "${LOG}" ] && ERROR "${LOG}"
    [ ! -z "${result}" ] && ERROR "${result}"
    L_LOG
    LOG=""
}

function LOG_DEBUG()
{
    local title
    local result=""
    [ -n "${1}" ] && title="${1}" || title="${JOB_NAME}"
    [ -n "${2}" ] && result="${2}"
    DEBUG "${title}"
    [ ! -z "${LOG}" ] && DEBUG "${LOG}"
    [ ! -z "${result}" ] && DEBUG "${result}"
    L_LOG
    LOG=""
}


function LOG_RC () {
    local _rc
    _rc=${1}
    if [ ${_rc} -ne 0 ] ; then
        LOG_ERROR "${JOB_NAME}" "Failed! Rc: [${_rc}]"
    else
        LOG_INFO "${JOB_NAME}" "Success."
    fi
}


function RM_FILES () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _main_rc=1
    local _rc=1
    local f
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Removing file:"
    if [ -z "${*}" ] ; then
        LOG="RM_FILES(): Argument missing!"
        LOG_RC ${_main_rc}
    else
        _main_rc=0
        for f in "${@}" ; do
            JOB_NAME="Removing file: '${f}'"
            _rc=1
            if [ -e "${f}" -o -L "${f}" ] ; then
                LOG="$( rm -f ${opts} "${f}" 2>&1 )"
                _rc=$?
                [ ${_rc} -ne 0 ] && _main_rc=${_rc}
            else
                LOG="'${f}': file not found !"
            fi
            LOG_RC ${_rc}
        done
    fi
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_main_rc}
}

function RM_DIRS () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _main_rc=1
    local _rc=1
    local d
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Removing directory:"
    if [ -z "${*}" ] ; then
        LOG="RM_DIRS(): Argument missing!"
        LOG_RC ${_main_rc}
    else
        _main_rc=0
        for d in "${@}" ; do
            JOB_NAME="Removing directory: '${d}'"
            if [ -d "${d}" ] ; then
                if [ "${d}" = "/" ] ; then
                    LOG="Can not remove this directory: '${d}'"
                    _main_rc=5
                else
                    LOG="$( rm -rf ${opts} "${d}" 2>&1 )"
                    _rc=$?
                    [ ${_rc} -ne 0 ] && _main_rc=${_rc}
                fi
            else
                LOG="'${d}': directory does not exists."
            fi
            LOG_RC ${_rc}
        done
    fi
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_main_rc}
}

function APT_CLEAN () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc
    local opts="-qq"
    [ ${DEBUG} = "yes" ] && opts=""
    JOB_NAME="Perform APT Clean"
    LOG="$( apt-get ${opts} clean 2>&1 )"
    _rc=$?
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function APT_UPDATE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc
    local _main_rc=0
    local opts="-qq"
    [ ${DEBUG} = "yes" ] && opts=""
    #
    JOB_NAME="Perform APT Update"
    LOG="$( apt-get ${opts} update 2>&1 )"
    _rc=$?
    LOG_RC ${_rc}
    [ ${_rc} -ne 0 ] && _main_rc=${_rc}
    #
    JOB_NAME="Perform APT -f install"
    LOG="$( apt-get ${opts} -f install 2>&1 )"
    _rc=$?
    LOG_RC ${_rc}
    [ ${_rc} -ne 0 ] && _main_rc=${_rc}
    #
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_main_rc}
}

function APT_DIST_UPGRADE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc
    local opts="-qq"
    [ ${DEBUG} = "yes" ] && opts=""
    JOB_NAME="Perform APT Dist-Upgrade"
    LOG="$( apt-get ${opts} -y --force-yes dist-upgrade 2>&1 )"
    _rc=$?
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function APT_INSTALL () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local opts="-qq"
    [ ${DEBUG} = "yes" ] && opts=""
    if [ -z "${1}" ] ; then
        ERROR "APT_INSTALL(): Argument(s) missing!"
    else
        JOB_NAME="Perform APT Install ${*}"
        LOG="$( apt-get ${opts} -y install ${*} 2>&1 )"
        _rc=$?
        LOG_RC ${_rc}
    fi
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function APT_REMOVE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local opts="-qq"
    [ ${DEBUG} = "yes" ] && opts=""
    JOB_NAME="Perform APT Remove"
    if [ -z "${1}" ] ; then
        LOG="APT_REMOVE(): Argument(s) missing!"
    else
        JOB_NAME="${JOB_NAME} ${*}"
        LOG="$( apt-get ${opts} -y purge ${*} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function APT_AUTOREMOVE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc
    local opts="-qq"
    [ ${DEBUG} = "yes" ] && opts=""
    JOB_NAME="Perform APT Auto-Remove"
    LOG="$( apt-get ${opts} -y autoremove 2>&1 )"
    _rc=$?
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function ADD_APT_REPO () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _repo
    JOB_NAME="Add APT Repository"
    if [ -z "${1}" ] ; then
        LOG="ADD_APT_REPO(): Argument missing!"
    else
        _repo="${1}"
        JOB_NAME="${JOB_NAME} -> '${_repo}'"
        LOG="$( add-apt-repository -y ${_repo} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function DEL_APT_REPO () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _repo
    JOB_NAME="Remove APT Repository"
    if [ -z "${1}" ] ; then
        LOG="DEL_APT_REPO(): Argument missing!"
    else
        _repo="${1}"
        JOB_NAME="${JOB_NAME} -> '${_repo}'"
        LOG="$( add-apt-repository -y -r ${_repo} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function ADD_APT_KEY_URL () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _url
    JOB_NAME="Add APT Key"
    if [ -z "${1}" ] ; then
        LOG="ADD_APT_KEY_URL(): Argument missing!"
    else
        _url="${1}"
        JOB_NAME="${JOB_NAME} -> '${_url}'"
        LOG="$( wget -qO - ${_url} | apt-key add - 2>&1 )"
        _rc=$?
        LOG_RC ${_rc}
    fi
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function ADD_APT_KEY_FILE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _file
    JOB_NAME="Add APT Key"
    if [ -z "${1}" ] ; then
        LOG="ADD_APT_KEY_FILE(): Argument missing!"
    else
        _file="${1}"
        JOB_NAME="${JOB_NAME} -> '${_file}'"
        LOG="$( apt-key add ${_file} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function GIT_CLONE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _url
    local _dst
    local opts="-q"
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Cloning repository:"
    if [ -z "${1}" ] ; then
        LOG="GIT_CLONE(): Argument missing!"
    else
        _url="${1}"
        _dst="${2}"
        JOB_NAME="${JOB_NAME} '${_url}'"
        [ ! -z "${_dst}" ] && JOB_NAME="${JOB_NAME} -> '${_dst}'"
        LOG="$( git clone ${opts} "${_url}" "${_dst}" 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function CHOWN_FILE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local f
    local _owner
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Changing owner"
    if [ -z "${2}" ] ; then
        LOG="CHOWN_FILE(): Argument(s) missing!"
    else
        _owner="${1}"
        f="${2}"
        JOB_NAME="${JOB_NAME} of '${f}' file -> '${_owner}'"
        if [ -e "${f}" ] ; then
            LOG="$( chown ${opts} ${_owner} "${f}" 2>&1 )"
            _rc=$?
        else
            LOG="'${f}': file does not exists."
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function CHOWN_DIR () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local d
    local _owner
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Changing owner"
    if [ -z "${2}" ] ; then
        LOG="CHOWN_DIR(): Argument(s) missing!"
    else
        _owner="${1}"
        d="${2}"
        JOB_NAME="${JOB_NAME} of '${d}' directory -> '${_owner}'"
        if [ -d "${d}" ] ; then
            LOG="$( chown -R ${opts} ${_owner} "${d}" 2>&1 )"
            _rc=$?
        else
            LOG="'${d}': Directory does not exists."
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function CHMOD_FILE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local f
    local _mode
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Changing mode"
    if [ -z "${2}" ] ; then
        LOG="CHMOD_FILE(): Argument(s) missing!"
    else
        _mode="${1}"
        f="${2}"
        JOB_NAME="${JOB_NAME} of '${f}' -> '${_mode}'"
        if [ -e "${f}" ] ; then
            LOG="$( chmod ${opts} ${_mode} "${f}" 2>&1 )"
            _rc=$?
        else
            LOG="'${f}': file does not exists."
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function CHMOD_DIR () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local d
    local _mode
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Changing mode"
    if [ -z "${2}" ] ; then
        LOG="CHMOD_DIR(): Argument(s) missing!"
    else
        _mode="${1}"
        d="${2}"
        JOB_NAME="${JOB_NAME} of '${d}' -> '${_mode}'"
        if [ -d "${d}" ] ; then
            LOG="$( chmod -R ${opts} ${_mode} "${d}" 2>&1 )"
            _rc=$?
        else
            LOG="'${d}': directory does not exists."
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function CP_FILE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _src
    local _dst
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Copying"
    if [ -z "${2}" ] ; then
        LOG="CP_FILE(): Argument(s) missing!"
    else
        _src="${1}"
        _dst="${2}"
        JOB_NAME="Copying '${_src}' -> '${_dst}'"
        if [ -e "${_src}" ] ; then
            LOG="$( cp -f ${opts} "${_src}" "${_dst}" 2>&1 )"
            _rc=$?
        else
            LOG="'${_src}': file does not exists."
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function CP_DIR () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _src
    local _dst
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Copying"
    if [ -z "${2}" ] ; then
        LOG="CP_DIR(): Argument(s) missing!"
    else
        _src="${1}"
        _dst="${2}"
        JOB_NAME="Copying '${_src}' -> '${_dst}'"
        if [ -e "${_src}" ] ; then
            LOG="$( cp -rf ${opts} "${_src}" "${_dst}" 2>&1 )"
            _rc=$?
        else
            LOG="'${_src}': file does not exists."
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function MV () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _src
    local _dst
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Moving"
    if [ -z "${2}" ] ; then
        LOG="MV(): Argument(s) missing!"
    else
        _src="${1}"
        _dst="${2}"
        JOB_NAME="Moving '${_src}' -> '${_dst}'"
        if [ -e "${_src}" ] ; then
            LOG="$( mv -f ${opts} "${_src}" "${_dst}" 2>&1 )"
            _rc=$?
        else
            LOG="'${_src}': file does not exists."
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function SVC_ENABLE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _svc
    JOB_NAME="Enabling service:"
    if [ -z "${1}" ] ; then
        LOG="SVC_ENABLE(): Argument missing!"
    else
        _svc="${1}"
        JOB_NAME="${JOB_NAME} '${_svc}'"
        LOG="$( systemctl enable ${_svc} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function SVC_DISABLE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _svc
    JOB_NAME="Disabling service:"
    if [ -z "${1}" ] ; then
        LOG="SVC_DISABLE(): Argument missing!"
    else
        _svc="${1}"
        JOB_NAME="${JOB_NAME} '${_svc}'"
        LOG="$( systemctl disable ${_svc} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function SVC_START () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _svc
    JOB_NAME="Starting service:"
    if [ -z "${1}" ] ; then
        LOG="SVC_START(): Argument missing!"
    else
        _svc="${1}"
        JOB_NAME="${JOB_NAME} '${_svc}'"
        LOG="$( systemctl start ${_svc} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function SVC_STOP () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _svc
    JOB_NAME="Stopping service:"
    if [ -z "${1}" ] ; then
        LOG="SVC_STOP(): Argument missing!"
    else
        _svc="${1}"
        JOB_NAME="${JOB_NAME} '${_svc}'"
        LOG="$( systemctl stop ${_svc} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function SVC_RESTART () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _svc
    JOB_NAME="Restarting service:"
    if [ -z "${1}" ] ; then
        LOG="SVC_RESTART(): Argument missing!"
    else
        _svc="${1}"
        JOB_NAME="${JOB_NAME} '${_svc}'"
        LOG="$( systemctl restart ${_svc} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function SVC_MASK () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _svc
    JOB_NAME="Masking service:"
    if [ -z "${1}" ] ; then
        LOG="SVC_MASK(): Argument missing!"
    else
        _svc="${1}"
        JOB_NAME="${JOB_NAME} '${_svc}'"
        LOG="$( systemctl mask ${_svc} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function SVC_UNMASK () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _svc
    JOB_NAME="Unmasking service:"
    if [ -z "${1}" ] ; then
        LOG="SVC_UNMASK(): Argument missing!"
    else
        _svc="${1}"
        JOB_NAME="${JOB_NAME} '${_svc}'"
        LOG="$( systemctl unmask ${_svc} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function SYSTEMD_RELOAD () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    JOB_NAME="Reloading SystemD configuration"
    LOG="$( systemctl daemon-reload 2>&1 )"
    _rc=$?
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function MKDIR () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local d
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Creating directory:"
    if [ -z "${*}" ] ; then
        LOG="MKDIR(): Argument missing!"
    else
        d="${1}"
        _rc=0
        JOB_NAME="Creating directory: '${d}'"
        if [ ! -d "${d}" ] ; then
            LOG="$( mkdir -p ${opts} "${d}" 2>&1 )"
            _rc=$?
        else
            LOG="'${d}': directory already exists"
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function MKDIR_TMP () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=0
    if [ ! -d "${TMP_DIR}" ] ; then
        MKDIR "${TMP_DIR}"
        _rc=$?
    fi
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function WGET () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _url
    local opts="-nc -q"
    local path="-P ${TMP_DIR}/"
    [ ${DEBUG} = "yes" ] && opts="-nc -v -S"
    if [ -z "${1}" ] ; then
        LOG="WGET(): Argument(s) missing!"
    else
        if [ ! -z "${2}" ] ; then
            path="-O ${2}"
        fi
        _url="${1}"
        JOB_NAME="Fetching: '${_url}'"
        LOG="$( wget --no-check-certificate --timeout=20 --tries=5 ${opts} ${path} ${_url} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function TAR_ZXF () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _tar
    local opts=""
    local path="."
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Extracting:"
    if [ -z "${1}" ] ; then
        LOG="TAR_ZXF(): Argument missing!"
    else
        if [ ! -z "${2}" ] ; then
            path="${2}"
        fi
        _tar="${1}"
        JOB_NAME="${JOB_NAME} '${_tar}' -> '${path}'"
        if [ ! -e "${_tar}" ] ; then
            LOG="TAR_ZXF(): '${_tar}': file not found!"
        else
            LOG="$( tar ${opts} -zxf "${_tar}" -C "${path}" 2>&1 )"
            _rc=$?
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function UNZIP () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _zip
    local path="."
    JOB_NAME="Unzipping:"
    if [ -z "${1}" ] ; then
        LOG="UNZIP(): Argument missing!"
    else
        if [ ! -z "${2}" ] ; then
            path="${2}"
        fi
        _zip="${1}"
        JOB_NAME="${JOB_NAME} '${_zip}' -> '${path}'"
        if [ ! -e "${_zip}" ] ; then
            LOG="UNZIP(): '${_zip}': file not found!"
        else
            LOG="$( unzip -d "${path}" "${_zip}" 2>&1 )"
            _rc=$?
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function DPKG_CHECK () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _pkg
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-D1"
    JOB_NAME="Checking status of package:"
    if [ -z "${1}" ] ; then
        LOG="DPKG_CHECK(): Argument missing!"
    else
        _pkg="${1}"
        JOB_NAME="${JOB_NAME} '${_pkg}'"
        LOG="$( dpkg ${opts} -s ${_pkg} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function DPKG_INSTALL () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _pkg
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-D1"
    JOB_NAME="Installing:"
    if [ -z "${1}" ] ; then
        LOG="DPKG_INSTALL(): Argument missing!"
    else
        _pkg="${1}"
        JOB_NAME="${JOB_NAME} '${_pkg}'"
        if [ ! -e "${_pkg}" ] ; then
            LOG="'${_pkg}': file not found!"
        else
            LOG="$( dpkg ${opts} -i ${_pkg} 2>&1 )"
            _rc=$?
        fi
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function DPKG_REMOVE () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _pkg
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-D1"
    JOB_NAME="Removing:"
    if [ -z "${1}" ] ; then
        LOG="DPKG_REMOVE(): Argument missing!"
    else
        _pkg="${1}"
        JOB_NAME="${JOB_NAME} '${_pkg}'"
        LOG="$( dpkg ${opts} --purge ${_pkg} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function PIP_INSTALL () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Perform PIP Install"
    if [ -z "${1}" ] ; then
        LOG="PIP_INSTALL(): Argument(s) missing!"
    else
        JOB_NAME="${JOB_NAME} ${*}"
        LOG="$( pip install ${opts} ${*} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function PIP_UNINSTALL () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local opts=""
    [ ${DEBUG} = "yes" ] && opts="-v"
    JOB_NAME="Perform PIP Uninstall"
    if [ -z "${1}" ] ; then
        LOG="PIP_INSTALL(): Argument(s) missing!"
    else
        JOB_NAME="${JOB_NAME} ${*}"
        LOG="$( pip uninstall ${opts} -y ${*} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function MONIT_RELOAD () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    JOB_NAME="'monit' reload"
    systemctl is-active monit > /dev/null 2>&1
    if [ $? -ne 0 ] ; then
        LOG="'monit' service is not active"
    else
        LOG="$( monit reload 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}

function RUN_LOG () {
    [ "${DEBUG}" = "yes" ] && ENTRY
    local _rc=1
    local _cmd
    JOB_NAME="Running command:"
    if [ -z "${1}" ] ; then
        LOG="RUN_LOG(): Argument missing!"
    else
        _cmd="${1}"
        JOB_NAME="${JOB_NAME} [${_cmd}]"
        LOG="$( eval ${_cmd} 2>&1 )"
        _rc=$?
    fi
    LOG_RC ${_rc}
    [ "${DEBUG}" = "yes" ] && RETURN
    return ${_rc}
}



# ----------------------------------------------------------
# Prepare environment functions
# ----------------------------------------------------------

function _prep_env () {
    local d
    for d in \
      Documents \
      Downloads \
      Torrents \
      Watch \
      tmp \
      log
    do
        [ ! -d "/etc/skel/${d}" ] && MKDIR "/etc/skel/${d}"
    done
}

function _create_std_user () {
    local _uid
    local _g
    local _rc
    local _main_rc=0
    _uid=$( id -u "user" 2>/dev/null )
    if [ ! -z "${_uid}" ] ; then
        INFO "'user': account exists!"
    else
        # Add regular user's account
        RUN_LOG "adduser --gecos 'RapidSeedbox.com User' --disabled-password user"
        _rc=$?
        [ ${_rc} -ne 0 ] && _main_rc=${_rc}
        # set user's password
        RUN_LOG "echo 'user:ChangeMe' | chpasswd"
        _rc=$?
        [ ${_rc} -ne 0 ] && _main_rc=${_rc}
        # Modify new user's group membership
        for _g in sudo www-data ; do
            grep -e "^${_g}:" "/etc/group" > /dev/null 2>&1
            if [ $? -eq 0 ] ; then
                RUN_LOG "usermod -a -G ${_g} user"
                _rc=$?
                [ ${_rc} -ne 0 ] && _main_rc=${_rc}
            fi
        done
    fi
    L_LOG
    return ${_main_rc}
}

function _prep_ssh () {

    local sshd_restart="no"
    local f

    # Configure sshd
    INFO "Configuring SSH service"
    for f in \
        "users-rapidseedbox-com-ca.pub" \
        "revoked_keys"
    do
        if [ ! -f "/etc/ssh/${f}" ] ; then
            WGET "${SUPPORT}/ssh/${f}" \
                 "/etc/ssh/${f}" \
              || return 1
            if [ ! -s "/etc/ssh/${f}" -a "${f}" != "revoked_keys" ] ; then
                 ERROR "'/etc/ssh/${f}': Empty file downloaded!"
                 RM_FILES "/etc/ssh/${f}"
                 return 1
            fi
        fi
    done

    # set TrustedUserCAKeys
    RUN_LOG "grep -e '^TrustedUserCAKeys' '/etc/ssh/sshd_config'"
    if [ $? -eq 0 ] ; then
        RUN_LOG "grep -e '^TrustedUserCAKeys /etc/ssh/users-rapidseedbox-com-ca.pub' '/etc/ssh/sshd_config'"
        if [ $? -ne 0 ] ; then
            RUN_LOG "sed -i -e 's#^TrustedUserCAKeys.*#TrustedUserCAKeys /etc/ssh/users-rapidseedbox-com-ca.pub#g' '/etc/ssh/sshd_config'"
            [ $? -eq 0 ] && sshd_restart="yes"
        fi
    else
        RUN_LOG "echo 'TrustedUserCAKeys /etc/ssh/users-rapidseedbox-com-ca.pub' >> '/etc/ssh/sshd_config'"
        [ $? -eq 0 ] && sshd_restart="yes"
    fi

    # set RevokedKeys
    RUN_LOG "grep -e '^RevokedKeys' '/etc/ssh/sshd_config'"
    if [ $? -eq 0 ] ; then
        RUN_LOG "grep -e '^RevokedKeys /etc/ssh/revoked_keys' '/etc/ssh/sshd_config'"
        if [ $? -ne 0 ] ; then
            RUN_LOG "sed -i -e 's#^RevokedKeys.*#RevokedKeys /etc/ssh/revoked_keys#g' '/etc/ssh/sshd_config'"
            [ $? -eq 0 ] && sshd_restart="yes"
        fi
    else
        RUN_LOG "echo 'RevokedKeys /etc/ssh/revoked_keys' >> '/etc/ssh/sshd_config'"
        [ $? -eq 0 ] && sshd_restart="yes"
    fi

    if [ "${sshd_restart}" = "yes" ] ; then
        SVC_RESTART "ssh"
    fi

    L_LOG
    return 0
}



# ----------------------------------------------------------
# Script entry/exit functions
# ----------------------------------------------------------

function SCRIPTEXIT(){

    local script_name
    script_name=$( basename "${0}" )

    #
    # Common tasks
    [ -e "${tmp}" ] && RM_FILES  "${tmp}"
    RM_DIRS   "${TMP_DIR}"

    echo -e "\n\n" >> "${LOGFILE}"
    L_LOG
    echo "${FUNCNAME}: ${script_name}" >> "${LOGFILE}"
    L_LOG
    echo -e "\n\n\n\n\n\n" >> "${LOGFILE}"

    exit ${main_rc}
}


function SCRIPTEXIT_REBOOT(){

    local script_name
    script_name=$( basename "${0}" )

    #
    # Common tasks
    [ -e "${tmp}" ] && RM_FILES  "${tmp}"
    RM_DIRS   "${TMP_DIR}"

    echo -e "\n\n" >> "${LOGFILE}"
    L_LOG
    echo "${FUNCNAME}: ${script_name}" >> "${LOGFILE}"
    L_LOG
    echo -e "\n\n\n\n\n\n" >> "${LOGFILE}"

    reboot
}


function SCRIPTENTRY(){

    local script_name
    script_name=$( basename "${0}" )

    [ -e "${LOGFILE}" ] && echo -e "\n\n\n\n" >> "${LOGFILE}"
    L_LOG
    echo "${FUNCNAME}: ${script_name}" >> "${LOGFILE}"
    L_LOG

    #
    # Perform common tasks
    #

    MKDIR_TMP
    if [ $? -ne 0 ] ; then
        main_rc=1
        SCRIPTEXIT
    fi
}
