#!/bin/sh
#
# Check what's installed on a PCP/PCPQA VM looking for missing apps
# and packages
#

_usage()
{
    echo "Usage: $0 [-v]"
    exit 1
}

verbose=false
while getopts 'v?' p
do
    case "$p"
    in
	v)	verbose=true
		;;

	?)	_usage
		# NOTREACHED
    esac
done
shift `expr $OPTIND - 1`
[ $# -eq 0 ] || _usage

tmp=/var/tmp/$$
trap "rm -f $tmp.*; exit 0" 0 1 2 3 15

# same function is in allow-pmlc-access ... need to track changes
#
_getnetworkaddr()
{
    if `which ifconfig >/dev/null 2>&1`
    then
	# expecting ifconfig lines like ...
        # inet 192.168.1.222  netmask 255.255.255.0  broadcast 192.168.1.255
	# inet addr:192.168.1.100  Bcast:192.168.1.255  Mask:255.255.255.0
	#
	# skip ip tunnels/vpns like
	# inet addr:10.8.3.138  P-t-P:10.8.3.137  Mask:255.255.255.255
	#
	ifconfig \
	| grep -v '[ :]127\.0\.0' \
	| sed -n >$tmp.addr \
	    -e '/^[ 	]*inet .*cast[ :]/{
s/^[ 	]*inet[ 	]//
s/^addr://
s/[ 	][ 	]*broadcast[ 	][^ 	]*//
s/:Bcast:[^ ]*//
s/[ 	][ 	]*netmask[ 	]/ /
s/[ 	][ 	]*Mask:/ /
p
}'
	#debug# cat $tmp.addr >&2
	num=`wc -l <$tmp.addr | sed -e 's/ //g'`
	case "$num"
	in
	    1)	# good
		addr=`cat $tmp.addr | sed -e 's/ .*//'`
		mask=`cat $tmp.addr | sed -e 's/.* //'`
		case "$mask"
		in
		    255.255.255.0)	# /24 network
			echo "$addr" | sed -e 's/\.[0-9]*$/.*/'
			;;
		    # pmcd's [access] is not smart enough to handle other
		    # than /24 networks, so map the other likely options
		    # to the broader /24 network
		    #
		    255.255.255.128|255.255.255.192|255.255.255.224|255.255.255.240|255.255.255.248|255.255.255.252|255.255.255.254)
			echo "$addr" | sed -e 's/\.[0-9]*$/.*/'
			;;
		    *)
			echo >&2 "_getnetworkaddr: cannot handle network mask: $mask"
			;;
		esac
		;;
	    0)	# none?
		echo >&2 "_getnetworkaddr: cannot get network address"
		;;
	    *)	# multiple?
		echo >&2 "_getnetworkaddr: cannot handle multiple network addresses:"
		cat >&2 $tmp.addr
		;;
	esac
    else
	echo >&2 '_getnetworkaddr: no ifconfig?'
    fi
}

# add additional and optional directories
for dir in /sbin /usr/sbin
do
    if [ -d "$dir" ]
    then
	if echo ":$PATH:" | grep -q ":$dir:"
	then
	    :
	else
	    export PATH="$PATH:$dir"
	    #debug# echo add $dir to \$PATH
	fi
    fi
done

# perl ? apt-get install -qqy --force-yes libxml-tokeparser-perl
# perl ? apt-get install -qqy --force-yes libspreadsheet-read-perl
cat <<End-of-File >$tmp.control
# one line per app, alternate items separated by white space
# first item ending in ? means this item is a guard, if it does not
# exist silently ignore the rest of the line
# tests items can be
#	starting with a /	test for existence of file or directory
#                               (alternates separated by |)
#	containing ::		test for presence of the associated Perl module
#	otherwise		test for an executable with which(1)
#                               (alternates separated by |)
#
# text after # is treated as a comment
# text after [ is treated as annotation
#
# executables
ed
git
make
gcc
autoconf
flex
bison
gdb
mktemp
gawk
cpan
# optional executables
dpkg?	dpkg-buildpackage	[dpkg-dev]
dpkg?	dh			[debhelper]
dpkg?	chrpath			[chrpath]
dpkg?	sysv-rc-conf		[sysv-rc-conf]
rpm?	rpmbuild		[rpm-build]
# other build prerequisites
dpkg?	/usr/share/doc/pkg-config	[pkg-config]
dpkg?	/usr/share/doc/python-all-dev	[python-all-dev]
dpkg?	/usr/include/microhttpd.h	[optional][libmicrohttpd-dev]
rpm?	/usr/include/microhttpd.h	[optional][libmicrohttpd-devel]
dpkg?	/usr/include/sasl/sasl.h	[optional][libsasl2-dev]
rpm?	/usr/include/sasl/sasl.h	[optional][cyrus-sasl-devel]
rpm?	/usr/include/systemd/sd-daemon.h	[optional][systemd-devel but not for CentOS 5.8]
dpkg?	/usr/include/infiniband/umad.h	[optional][libibumad-dev]
rpm?	/usr/include/infiniband/umad.h	[optional][libibumad-devel]
dpkg?	/usr/include/infiniband/mad.h	[optional][libibmad-dev]
rpm?	/usr/include/infiniband/mad.h	[optional][libibmad-devel]
dpkg?	/usr/include/avahi-common	[optional][libavahi-common-dev]
rpm?	/usr/include/avahi-common	[optional][avahi-devel]
dpkg?	g++				[g++]
rpm?	g++				[gcc-c++]
# files
dpkg?	/usr/include/readline/readline.h	[libreadline-dev]
rpm?	/usr/include/readline/readline.h	[readline-devel]
rpm?	/usr/include/ncurses.h	[ncurses-devel] # is this a bug in the spec file?
# perl modules
Time::HiRes			[Perl Time-HiRes perl-Time-HiRes(rpm)]
Date::Format			[Perl TimeDate perl-TimeDate(rpm)]
Date::Parse			[Perl TimeDate perl-TimeDate(rpm)]
Getopt::Std			[base Perl]
dpkg?	ExtUtils::MakeMaker	[libextutils-autoinstall-perl]
rpm?	ExtUtils::MakeMaker	[perl-ExtUtils-MakeMaker]
dpkg?	XML::TokeParser		[libxml-tokeparser-perl]
rpm?	XML::TokeParser		[perl-XML-TokeParser]
dpkg?	Spreadsheet::Read	[libspreadsheet-read-perl]
rpm?	Spreadsheet::Read	[cpan]
dpkg?	Spreadsheet::WriteExcel	[libspreadsheet-writeexcel-perl]
rpm?	Spreadsheet::WriteExcel	[perl-Spreadsheet-WriteExcel or cpan]
Spreadsheet::ReadSXC		[cpan]
# other run-time
sadf				[sysstat]
# QA
bc
curl
dpkg?	Spreadsheet::XLSX	[libspreadsheet-xlsx-perl]
rpm?	Spreadsheet::XLSX	[cpan]
dpkg?	Text::CSV_XS		[Text-CSV_XS]
rpm?	Text::CSV_XS		[perl-Text-CSV_XS]
crontab				[from vixie-cron?]
valgrind
dpkg?	mail			[bsd-mailx]
rpm?	mail			[mailx]
host				[bind-utils(redhat)]
dpkg?	apache2			[apache2]
rpm?	httpd			[httpd]
time				[time(redhat)]
dpkg?	realpath		[realpath]
# pcp-gui
dpkg?	qmake			[qt4-qmake]
rpm?	qmake|qmake-qt4			[qt-devel]
dpkg?	/usr/lib/libQtCore.so|/usr/lib/*/libQtCore.so	[libqt4-dev]
dpkg?	/usr/lib/libSoQt4.so|/usr/lib/*/libSoQt4.so	[optional][libsoqt4-dev]
rpm?	/usr/lib/libQtCore.so|/usr/lib*/libQtCore.so	[optional][qt-devel]
dpkg?	/usr/include/Inventor/Qt/SoQt.h	[optional][libsoqt-dev-common]
dpkg?	/usr/include/Inventor/SoPath.h	[optional][libcoin60-dev or libcoin80-dev]
# python
rpm?	/usr/include/python*/Python.h	[python-devel]
dpkg?	/usr/include/python*/Python.h	[python-dev]
rpm?	/usr/lib/python*/curses		[python-curses]
# nss
dpkg?	/usr/include/nspr/nspr.h	[optional][libnspr4-dev]
rpm?	/usr/include/nspr4/nspr.h	[optional][nspr-devel]
dpkg?	/usr/include/nss/nss.h		[optional][libnss3-dev]
rpm?	/usr/include/nss3/nss.h		[optional][nss-devel]
dpkg?	certutil			[optional][libnss3-tools]
rpm?	certutil			[optional][nss-tools or mozilla-nss-tools]
End-of-File

if which python >/dev/null 2>&1
then
    # For python-ctypes, check for python before 2.5 ... expect something like
    # Python 2.7.3
    eval `python -V 2>&1 | sed -e 's/Python //' -e 's/^/maj=/' -e 's/\./ min=/' -e 's/\..*//'`
    if [ -n "$maj" -a -n "$min" ]
    then
	rm -f $tmp.need
	if [ "$maj" -lt 2 ]
	then
	    touch $tmp.need
	elif [ "$maj" -eq 2 -a "$min" -lt 5 ]
	then
	    touch $tmp.need
	fi
	[ -f $tmp.need ] && \
	    echo "rpm?	/usr/share/doc/packages/python-ctypes	[python-ctypes]" >>$tmp.control
    fi
fi

cat $tmp.control \
| sed -e 's/#.*//' -e '/^[ 	]*$/d' \
| while read apps
do
    rm -f $tmp.ok
    rm -f $tmp.echo
    for app in $apps
    do
	case $app
	in
	    \[*)
	    	break
		;;
	    *\?)
	    	app=`echo $app | sed -e 's/?$//'`
		optional=true
		;;
	    *)
		optional=false
		;;
	esac
	case $app
	in
	    \[*)
	    	break
		;;
	    /*)
		rm -f $tmp.tmp
		for file in `echo "$app" | sed -e 's/|/ /g'`
		do
		    if [ -f "$file" -o -d "$file" ]
		    then
			touch $tmp.tmp
			break
		    fi
		done
		[ -f $tmp.tmp ]
		ok=$?
		;;
	    *::*)
		echo "use $app;" | perl >/dev/null 2>&1
		ok=$?
		;;
	    *)
		rm -f $tmp.tmp
		for exec in `echo "$app" | sed -e 's/|/ /g'`
		do
		    if which $exec >/dev/null 2>&1
		    then
			touch $tmp.tmp
			break
		    fi
		done
		[ -f $tmp.tmp ]
		ok=$?
		;;
	esac
	if $verbose
	then
	    if [ "$app" = dpkg -o "$app" = rpm ]
	    then
		# rpm? and dpkg? guards are not really useful to report
		#
		:
	    else
		echo -n "$app ... "
		$optional && echo -n "[optional]"
		if [ $ok = 0 ]
		then
		    echo -n "yes "
		else
		    echo -n "no "
		fi
		touch $tmp.echo
	    fi
	fi
	if [ $ok = 0 ]
	then
	    $optional && continue
	    touch $tmp.ok
	    break
	else
	    if $optional
	    then
		# guard not true, skip checks for other apps
		touch $tmp.ok
		break
	    fi
	fi
    done
    [ -f $tmp.echo ] && echo
    if [ ! -f $tmp.ok ]
    then
	echo "Missing: `echo $apps \
	    | sed \
		-e 's/[ 	][ 	]*/ /g' \
		-e '/ /{
s/? /?@/
:loop1
s/\(\[.*\) /\1@/
t loop1
:loop2
s/ \([^[]\)/@|@\1/
t loop2
s/@/ /g
}'`"
    fi
done

# Some platform-specific and special case tests
#
if which dpkg >/dev/null 2>&1
then
    # Debian based
    #
    dpkg -l >$tmp.tmp
    for pkg in python-all python-all-dev
    do
	if grep "^ii *$pkg" <$tmp.tmp >/dev/null
	then
	    :
	else
	    echo "Need # apt-get install $pkg"
	fi
    done
fi

# Networking goo
#
_check_host()
{
    ipaddr=`sed -n </etc/hosts -e '/^#/d' -e '/::/d' -e 's/$/ /' -e "/[ 	]$1[ 	]/"'{
s/[ 	].*//
p
}'`
    if [ -z "$ipaddr" ]
    then
	echo "No /etc/hosts entry for $1"
	return
    fi

    if [ `echo "$ipaddr" | wc -l | sed -e 's/  *//g'` -gt 1 ]
    then
	echo "Multiple /etc/hosts entries for $1"
	return
    fi

    ifconfig \
    | awk '
/^[^ 	]/	{ iface = $1; next }
/inet addr:'$ipaddr' / || /inet '$ipaddr' / {
			  if (iface == "lo")
			    print "Warning: '$1' associated with loopback network interface"
			  found = 1
			  exit
			}
END		{ if (found != 1)
		    print "Warning: '$1' ('$ipaddr') not associated with a network interface"
		}'
}

host=`hostname`
_check_host $host
if which pmhostname >/dev/null 2>&1
then
    pmhost=`pmhostname`
    if [ -z "$pmhost" ]
    then
	echo "Warning: pmhostname returns nothing!"
    else
	case $pmhost
	in
	    $host|$host.*)
		    ;;
	    *)
		    echo "Warning: hostname ($host) is not a prefix of pmhostname ($pmhost)"
		    ;;
	esac
	_check_host $pmhost
    fi
fi

if [ -f /etc/pcp.conf ]
then
    . /etc/pcp.conf

    # need QA access to pmlogger via pmlc from local subnet
    #
    network=`_getnetworkaddr`
    if [ -n "$network" ]
    then
	if [ -f $PCP_VAR_DIR/config/pmlogger/config.default ]
	then
	    if grep -q "allow $network" $PCP_VAR_DIR/config/pmlogger/config.default
	    then
		:
	    else
		echo "Missing: \"allow $network : all;\" [access] in $PCP_VAR_DIR/config/pmlogger/config.default"
		echo "Use \"$ sudo -E .../qa/admin/allow-pmlc-access\" to fix this."
	    fi
	else
	    echo "Warning: \"$PCP_VAR_DIR/config/pcp/pmlogger/config.default\" is missing"
	fi
    fi
else
    echo "Warning: \"/etc/pcp.conf\" is missing"
fi

sudo -u pcp [ -x $HOME ] || echo "Error: $HOME is not searchable by user \"pcp\""
