#!/bin/bash

# **************************************************************************
# *                                                                        *
# *  Pointtools v.0.3 by Alexey Khromov AKA zxalexis AKA 2:5030/723        *
# *                                                                        *
# **************************************************************************
# *                                                                        *
# * pointcheck - check Links, Passwords and Userlist files for             *
# *     declaring same point numbers and display difference                *
# *                                                                        *
# **************************************************************************

NMSBASE=""
FIDOBASE=""

if [ -f /etc/fidonms ]; then
    source /etc/fidonms
fi
if [ -z "$NMSBASE" ]; then
    #Try to guess
    NMSBASE=/opt/fidonms
fi
if [ -z "$FIDOBASE" ]; then
    FIDOBASE=/var/spool/ftn
fi


# Read parameters
while [ -n "$1" ]
do
        case "$1" in
                -f)     cfgfile="$2"
                        shift;;
                *)      cmdusage="1";;
        esac
        shift
done

if [[ "${cmdusage}" = "1" ]]; then
        echo -ne "Usage: \n\
pointcheck {-f <cfgfile>}\n"
        exit -2
fi

pwdsource=${BASH_SOURCE[0]}
while [ -L "$pwdsource" ]; do
        pwddir=$( cd -P "$( dirname "$pwdsource" )" > /dev/null 2>&1 && pwd )
        pwdsource=$( readlink "$pwdsource" )
        [[ $pwdsource != /* ]] && pwdsource=$pwddir/$pwdsource
done
pwddir=$( cd -P "$( dirname "$pwdsource" )" > /dev/null 2>&1 && pwd )

if [[ -z ${cfgfile} ]]; then
        if [[ -f "${NMSBASE}/etc/pointcfg" ]]; then
                cfgfile="${NMSBASE}/etc/pointcfg"
        elif [[ -f "/etc/pointcfg" ]]; then
                cfgfile="/etc/pointcfg"
        elif [[ -f "$pwddir/etc/pointcfg" ]]; then
                cfgfile="$pwddir/etc/pointcfg"
        else
                echo "Config file not found. Please specify one"
                exit -2
        fi
fi

source ${cfgfile}

if [[ -f ${FIDOCONFIG} ]]; then
    AKA=$(cat ${FIDOCONFIG}| grep -ie ^Address | head -n1 | awk -F'[ @]' '{ print $2 }')
else
    echo "No FIDOCONFIG var found..."
    exit -1
fi


errorlvl=0
next_upnum=0
next_ppnum=0
next_lpnum=0
max_upnum=0
max_ppnum=0
max_lpnum=0
declare -a upntarri=()
declare -A upntarrs=()
declare -a ppntarri=()
declare -A ppntarrs=()
declare -a dpntarri=()
declare -A dpntarrs=()
declare -a bpntarri=()
declare -A bpntarrs=()
declare -a lpntarri=()
declare -A lpntarrs=()

if [[ -f ${USERLIST} ]]; then
        lnum=0
        while read -r line; do
                if [[ "$(echo -ne ${line}| awk -F',' '{ print $1 }')" =~ ^[Pp][Oo][Ii][Nn][Tt]$ ]]; then
                        next_upnum=$(echo -ne ${line}| awk -F',' '{print $2}')
                        upntarri+=(${next_upnum})
                        upntarrs+=([${next_upnum}]=${lnum})
                        if [[ ${max_upnum} < ${next_upnum} ]]; then
                                max_upnum="${next_upnum}"
                        fi
                fi
                if [[ "$(echo -ne ${line}| awk -F',' '{ print $1 }')" =~ ^[Dd][Oo][Ww][Nn]$ ]]; then
                        next_upnum=$(echo -ne ${line}| awk -F',' '{print $2}')
                        dpntarri+=(${next_upnum})
                        dpntarrs+=([${next_upnum}]=${lnum})
                        if [[ ${max_upnum} < ${next_upnum} ]]; then
                                max_upnum="${next_upnum}"
                        fi
                fi
                lnum=$(( ${lnum} + 1 ))
        done < ${USERLIST}
        max_upnum=$(( ${max_upnum} + 1 ))
else
        errorlvl=0
fi


if [[ -f ${BINKD_PASSWD} ]]; then
        lnum=0
        while read -r line; do

                tmpaka="$(echo -ne ${line}| awk '{ print $1 }'| awk -F'.' '{ --NF; print }'| sed -e 's/ /./')"

                if [[ ${tmpaka} == ${AKA} ]]; then
                        next_ppnum=$(echo -ne ${line}| awk '{ print $1 }'| awk -F'.' '{ print $NF }')
                        ppntarri+=(${next_ppnum})
                        ppntarrs+=([${next_ppnum}]=${lnum})
                        if [[ ${max_ppnum} < ${next_ppnum} ]]; then
                                max_ppnum="${next_ppnum}"
                        fi
                fi
                lnum=$(( ${lnum} + 1 ))
        done < ${BINKD_PASSWD}
        max_ppnum=$(( ${max_ppnum} + 1 ))
else
        errorlvl=3
fi

if [[ -f ${NMSBASE}/etc/bforce.passwd ]]; then
        lnum=0
        while read -r line; do
                # echo "bforce.passwd processing line $line" >&2
                if [[ $line =~ ^[Pp]assword ]]; then
                        # echo "found passwd line" >&2
                        tmpaka="$(echo -ne ${line}| awk '{ print $2 }'| awk -F'.' '{ --NF; print }'| sed -e 's/ /./')"
                        # echo "tmpaka $tmpaka" >&2
                        if [[ ${tmpaka} == ${AKA} ]]; then
                                next_bpnum=$(echo -ne ${line}| awk '{ print $2 }'| awk -F'.' '{ print $NF }')
                                bpntarri+=(${next_bpnum})
                                bpntarrs+=([${next_bpnum}]=${lnum})
                                # echo "bforce pnt ${next_bpnum} at line ${lnum}" >&2
                                if [[ ${max_bpnum} < ${next_bpnum} ]]; then
                                        max_bpnum="${next_bpnum}"
                                fi
                        # Adding after to store previous lines
                        fi
                fi      
                lnum=$(( ${lnum} + 1 ))
        done < ${NMSBASE}/etc/bforce.passwd
        max_bpnum=$(( ${max_bpnum} + 1 ))
        # echo "Max num is ${max_bpnum}, array is ${bpntarri[@]}"
        # echo "strings array is ${bpntarrs[@]}"
else
        # echo "No Binkleyforce passwd file found"
        errorlvl=0
fi


if [[ -f ${HPT_POINTS} ]]; then
        lnum=0
        loclink=0
        while read -r line; do
                if [[ "$(echo -ne ${line}| awk '{ print $1 }')" =~ ^[Ll][Ii][Nn][Kk]$ ]]; then
                        # echo "Link begins at ${lnum}"
                        loclink=${lnum}
                fi
                if [[ "$(echo -ne ${line}| awk '{print $1 }')" =~ ^[Aa][Kk][Aa]$ ]]; then

                        next_lpnum=$(echo -ne ${line}| awk '{print $2}'| awk -F'.' '{ print $NF }')
                        lpntarri+=(${next_lpnum})
                        lpntarrs+=([${next_lpnum}]=${loclink})
                        if [[ ${max_lpnum} < ${next_lpnum} ]]; then
                                max_lpnum="${next_lpnum}"
                        fi
                fi
                lnum=$(( ${lnum} + 1 ))
        done < ${HPT_POINTS}
        max_lpnum=$(( ${max_lpnum} + 1 ))
else
        errorlvl=3
fi

# Now we have indexes from all 2/3/4 files (userlist is optional, but preferrable
# We can a) compare them for consistency

declare -a lsortedlst=()
declare -a usortedlst=()
declare -a psortedlst=()
declare -a bsortedlst=()

readarray -t lsortedlst < <(printf '%s\n' "${lpntarri[@]}"| sort -g)
readarray -t psortedlst < <(printf '%s\n' "${ppntarri[@]}"| sort -g)

if [ -f "${NMSBASE}/etc/bforce.passwd" ]; then
	readarray -t bsortedlst < <(printf '%s\n' "${bpntarri[@]}"| sort -g)
fi

if [ -f "${USERLIST}" ]; then
        readarray -t usortedlst < <(printf '%s\n' "${upntarri[@]}"| sort -g)
        if [[ ${usortedlst[@]} != ${upntarri[@]} ]] && [[ ${errorlvl} = 0 ]]; then
                errorlvl=1
        elif [[ ${usortedlst[@]} != ${psortedlst[@]} ]] || [[ ${usortedlst[@]} != ${lsortedlst[@]} ]]; then
                errorlvl=2
        fi

fi
if [[ ${lsortedlst[@]} = ${psortedlst[@]} ]]; then
        if [[ ${lsortedlst[@]} != ${lpntarri[@]} ]] || [[ ${psortedlst[@]} != ${ppntarri[@]} ]]; then
                errorlvl=1
                # echo "LS: ${lsortedlst[@]}"
                # echo "LPNT: ${lpntarri[@]}"
                # echo "PS: ${psortedlst[@]}"
                # echo "PPNT: ${ppntarri[@]}"
        fi
else
        errorlvl=2
fi

if [ -f "$NMSBASE/etc/bforce.passwd" ]; then
	# echo "CheckPoint BSL: ${bsortedlst[@]} "
	if [[ ${lsortedlst[@]} = ${bsortedlst[@]} ]]; then
		if [[ ${bsortedlst[@]} != ${bpntarri[@]} ]] && [[ "$errorlvl" == "0" ]]; then
			errorlvl=1
		fi
	else
		errorlvl=2
	fi
fi

# Now we have errorlevels:
# 0 - all ok and all files are identical and sorted
# 1 - may work on, files identical, but not sorted
# 2 - worst. files are not identical
# 3 - binkd passwords not found
# 4 - links include file not found

if [[ ${errorlvl} = 4 ]]; then
	echo "HPT links file does not exist"
fi
if [[ ${errorlvl} = 3 ]]; then
	echo "Binkd passwords file not found"
fi
if [[ ${errorlvl} = 1 ]]; then
	echo "Files ok, but not sorted. Run pointsort"
fi
if [[ ${errorlvl} = 0 ]]; then
	echo "OK"
fi

if [[ ${errorlvl} = 2 ]]; then
	for lpnt in ${lsortedlst[@]}; do
		pexist=$(printf '%s\n' "${psortedlst[@]}" | grep "${lpnt}" | wc -l)
		if [[ -f ${USERLIST} ]]; then
			uexist=$(printf '%s\n' "${usortedlst[@]}" | grep "${lpnt}"| wc -l)
		fi
		if [[ -f ${NMSBASE}/etc/bforce.passwd ]]; then
                        bexist=$(printf '%s\n' "${bsortedlst[@]}" | grep "${lpnt}" | wc -l)
                fi
		if [[ ${pexist} -eq 0 ]]; then
			echo "Point #${lpnt} is declared in Links, but not in Passwords"
		fi
		if [[ -f ${USERLIST} ]] && [[ ${uexist} -eq 0 ]]; then
			echo "Point #${lpnt} is declared in Links, but not in Userlist"
		fi
		if [[ -f ${NMSBASE}/etc/bforce.passwd ]] && [[ ${bexist} -eq 0 ]]; then
                        echo "Point #${lpnt} is declared in Links, but not in Binkleyforce"
                fi
	done

	for ppnt in ${psortedlst[@]}; do
		lexist=$(printf '%s\n' "${lsortedlst[@]}" | grep "${ppnt}" | wc -l)
		if [[ -f ${USERLIST} ]]; then
			uexist=$(printf '%s\n' "${usortedlst[@]}" | grep "${ppnt}" | wc -l)
		fi
		if [[ -f ${NMSBASE}/etc/bforce.passwd ]]; then
                        bexist=$(printf '%s\n' "${bsortedlst[@]}" | grep "${ppnt}" | wc -l)
                fi

		if [[ ${lexist} -eq 0 ]]; then
			echo "Point #${ppnt} is declared in Passwords, but not in Links"
		fi
		if [[ -f ${USERLIST} ]] && [[ ${uexist} -eq 0 ]]; then
			echo "Point #${ppnt} is declared in Passwords, but not in Userlist"
		fi
		if [[ -f ${NMSBASE}/etc/bforce.passwd ]] && [[ ${bexist} -eq 0 ]]; then
                        echo "Point #${ppnt} is declared in Passwords, but not in Binkleyforce"
                fi
	done

	if [[ -f ${USERLIST} ]]; then
		for upnt in ${usortedlst[@]}; do
			lexist=$(printf '%s\n' "${lsortedlst[@]}" | grep "${upnt}" | wc -l)
			pexist=$(printf '%s\n' "${psortedlst[@]}" | grep "${upnt}" | wc -l)
			if [[ -f ${NMSBASE}/etc/bforce.passwd ]]; then
                        	bexist=$(printf '%s\n' "${bsortedlst[@]}" | grep "${upnt}" | wc -l)
                	fi
			
			if [[ ${lexist} -eq 0 ]]; then
				echo "Point #${upnt} declared in Userlist, but not in Links"
			fi
			if [[ ${pexist} -eq 0 ]]; then
				echo "Point #${upnt} declared in Userlist, but not in Passwords"
			fi
			if [[ -f ${NMSBASE}/etc/bforce.passwd ]] && [[ ${bexist} -eq 0 ]]; then
                        	echo "Point #${upnt} is declared in Userlist, but not in Binkleyforce"
                	fi
		done
	fi
	
	if [[ -f ${NMSBASE}/etc/bforce.passwd ]]; then
                for bpnt in ${bsortedlst[@]}; do
                        lexist=$(printf '%s\n' "${lsortedlst[@]}" | grep "${bpnt}" | wc -l)
                        pexist=$(printf '%s\n' "${psortedlst[@]}" | grep "${bpnt}" | wc -l)
			if [[ -f ${USERLIST} ]]; then
                        	uexist=$(printf '%s\n' "${usortedlst[@]}" | grep "${bpnt}" | wc -l)
                	fi
			
                        if [[ ${lexist} -eq 0 ]]; then
                                echo "Point #${upnt} declared in Binkleyforce, but not in Links"
                        fi
                        if [[ ${pexist} -eq 0 ]]; then
                                echo "Point #${upnt} declared in Binkleyforce, but not in Passwords"
                        fi
			if [[ -f ${USERLIST} ]] && [[ ${uexist} -eq 0 ]]; then
                        	echo "Point #${bpnt} is declared in Binkleyforce, but not in Userlist"
                	fi
                done
        fi
fi

exit ${errorlvl}

