#!/bin/sh

# Shell script to summarize System Tools from snapshots for SCC.
# Copyright (C) 2001-2004 Open Challenge B.V.
# Copyright (C) 2004-2005 OpenEyeT Professional Services.
# Copyright (C) 2005-2009 QNH.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.
# If not, write to the Free Software Foundation,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Contact information: http://scc.qnh-infrastructure.nl

# SCC-release:	1.7.5
# file-version:	$Revision: 1.95 $


ProgName=${0##*/};			export ProgName

set -u

SCC_BIN=/opt/scc-srv/bin
SCC_TOP=/var/opt/scc-srv
export SCC_BIN SCC_TOP

export SCC_DATA=${SCC_TOP}/data
export SCC_TMP=${SCC_TOP}/tmp
export SCC_CONF=${SCC_TOP}/conf

export TMPDIR=${SCC_TMP}
export TMP=${SCC_TMP}

export SHELL=/bin/sh
export LANG=C

PATH=/sbin:/usr/sbin:/usr/bin:/bin:${SCC_BIN};		export PATH

# Use the following utilities for SunOS.
if [ -x /usr/ccs/bin/what ]
then
	alias what=/usr/ccs/bin/what
fi
if [ -x /usr/xpg4/bin/awk ]
then
	alias awk=/usr/xpg4/bin/awk
fi
if [ -x /usr/xpg4/bin/grep ]
then
	alias grep=/usr/xpg4/bin/grep
fi

SYNTAX="Syntax error, use: ${ProgName} [ -d <scc_web_path> ] <realm>"

scc_web_path_dir=""
while [ $# -gt 1 ]
do
	if [ $# -eq 1 ]
	then
		echo "${ProgName}: Syntax error, missing argument for option: $1" 
		exit 2
	fi

	case "${1}" in
	-d)	if [ "${2}" != "/" ]
		then
			scc_web_path_dir="$2"
		fi
		shift 2;;

	*)	echo "${SYNTAX}" >&2
		exit 1;;
	esac
done

if [ $# -ne 1 ]
then
	echo "${SYNTAX}" >&2
	exit 1
fi

realm="${1}"
if [ ! -d "${SCC_WWW}/${realm}" ]
then
	echo "${ProgName}: directory ${SCC_WWW}/${realm} does not exist" >&2
	exit 1
fi
cd "${SCC_WWW}/${realm}"

if [ -z "${scc_web_path_dir}" ]
then
	scc_web_path_dir="$(sed -n 's/^SCC_WEB_PATH=//p' ${SCC_CONF}/scc.conf 2>/dev/null)"
fi

web_realm_dir="${scc_web_path_dir}/${realm}"
HOME_URL="<A HREF=\"${web_realm_dir}/index.html\">Home</A>&nbsp;&nbsp;&nbsp;&nbsp;"

# Use the owner/group/permissions of the destination directory for the files we put there.
# We are only interested in the read-permissions of the directory.
set dummy $(ls -ld .)
case "${2}" in
?r??r??r??)	new_mode=0444; umask 333;;
?r??r??-??)	new_mode=0440; umask 337;;
?r??-??-??)	new_mode=0400; umask 377;;
?r??-??r??)	new_mode=0404; umask 373;;
*)		new_mode=0400; umask 077;;
esac
new_owner_group="${4}:${5}"

smt_file=""
if [ -f "custom/scc-smt-select" -o -h "custom/scc-smt-select" ]
then
	smt_file="$(pwd)/custom/scc-smt-select"
else
	# No SMT selection file present. Remove all files from a possible, previous run.
	rm -f scc-smt.data scc-smt-index.html
	find . -type f -name "scc.*.smt.html" 2>/dev/null	|
	xargs rm -f

	exit 0
fi

bg_color=""
if [ -f ./custom/scc-realm.conf ]
then
	color="$(sed -n 's/^BG_COLOR=//p' ./custom/scc-realm.conf)"
	if [ "${color}" ]
	then
		bg_color=" bgcolor=\"${color}\""
	fi
fi

logo_tag="<IMG SRC=\"${web_realm_dir}/custom/scc-logo.png\" ALT=HelpInfo BORDER=0>"

if [ ! -f scc-summary.data ]
then
	echo "${ProgName}: file scc-summary.data does not exist" >&2
	exit 1
fi
system_cnt=$(wc -l <scc-summary.data)

TMP_FILE=${SCC_TMP}/smt_$$
SMT_VERSIONS=scc-smt.data

trap "rm -f ${TMP_FILE}" 0
trap "exit 2" 1 2 3 15

if [ ! -f ${smt_file} ]
then
	echo "${ProgName}: file ${smt_file} does not exist" >&2
	exit 1
fi

# Ignore comments and blank lines in the selection-file.
sed -e '/^#/d' -e '/^[ 	]*$/d' ${smt_file} >${TMP_FILE}

# Ignore snapshots in sub-directories (with more than one '/' in the name).
# The awk-script could detect extracted data that is not matched.
# This is not (yet) implemented.
find . -name "scc.*.cur"				|
sed -e '/\/.*\//d'					|
xargs fgrep -f ${TMP_FILE} /dev/null			|
awk -F: '/'"$(basename ${smt_file})"'/	{
			# The client collects the contents of the specification file of this program.
			# The contents match the patterns of the next line.
			# Ignore the contents of this file to avoid bogus data in the report.
			next;
		}
	/\.cur:fix:software:installed-filesets::/	{
			# Format of input is:
			# scc.host.cur:fix:software:installed-filesets::# SCC   1.2.10   System Configuration Collector
			sub( "^[# ]*", "", $6 );		# remove leading chars
			sub( "[ 	][ 	]*", ":", $6 );	# join name and version
			sub( "[ 	].*", "", $6 );		# erase description
			printf( "%s:%s\n", $1, $6 );		# Name and version are joined in $6
			next;
		}
	/\.cur:fix:software:installed-packages:/	{
			# Format of input is:
			# scc.host.cur:fix:software:installed-packages:<cat>::<name>:<desc>:<version>:<pstamp>
			if ( $7 == "OPC" && $8 == "HP" )
			{
				# OPC-agent on Sun is indicated by OPC and HP. 
				# Map this to the same name as on HP-UX.
				# "system::OPC:HP:A.6.11
				printf( "%s:%s:%s\n", $1, "OVOPC-AGT", $9 );
			}
			else
			{
				# We do not need the detailed (date) version
				sub( ",REV=.*", "", $9 );
				printf( "%s:%s:%s\n", $1, $7, $9 );
			}
			next;
		}
	/\.cur:fix:software:installed-aix-filesets::/	{
			# Format of the input is:
			# scc.host.cur:fix:software:installed-aix-filesets::/usr/lib/objrepos:IMNSearch.rte.httpdlite:2.0.0.1::COMMITTED:I:NetQuestion Web Server
			printf( "%s:%s:%s\n", $1, $7, $8 );
			next;
		}
	/\.cur:fix:software:installed-BSD-packages::/	{
			# Format of the input is:
			# scc.host.cur:fix:software:installed-BSD-packages::scc-1.6.3	System Conf...
			# scc.host.cur:fix:software:installed-BSD-packages::scc-srv-1.3.25-OpenBSD  ....
			sub( "[ 	].*", "", $6 );		# erase description
			sub( "-OpenBSD$", "", $6 );		# erase OS
			cnt = split( $6, parts, "-" );
			version = parts[ cnt ];
			name = parts[ 1 ];
			for ( i = 2; i < cnt; i++ )
			{
				name = sprintf( "%s-%s", name, parts[ i ] );
			}
			printf( "%s:%s:%s\n", $1, name, version );
			next;
		}
	/\.cur:fix:software:installed Debian packages::/	{
			# Format of the input is:
			# scc.host.cur:fix:software:installed Debian packages::ii  scc   1.6.3  System Conf...
			cnt = split( $6, parts, " " );
			name = parts[ 2 ];
			version = parts[ 3 ];
			printf( "%s:%s:%s\n", $1, name, version );
			next;
		}
	/\.cur:fix:software:installed pisi packages::/	{
			# Format of the input is:
			# scc.host.cur:fix:software:installed pisi packages::scc:1.8.9:System Configuration Collector
			printf( "%s:%s:%s\n", $1, $6, $7 );
			next;
		}
	/\.cur:fix:software:installed CRUX packages::/	{
			# Format of the input is:
			# scc.host.cur:fix:software:installed CRUX packages::autoconf:2.61-1
			printf( "%s:%s:%s\n", $1, $6, $7 );
			next;
		}
	/\.cur:fix:software:installed software::/	{
			# Suggested by Jacco Dunweg:
			# This classification is not produced by scc_0600_s_software,
			# but added to provide a mechanism for software that is not installed
			# by one of the supported package management software in the client.
			# To add other software to the summaries of scc-smt, add data to
			# the snapshot with classification: fix:software:installed software::<name>:<version>

			# Format of the input is:
			# scc.host.cur:fix:software:installed software::autoconf:2.61-1
			printf( "%s:%s:%s\n", $1, $6, $7 );
			next;
		}
	/\.cur:fix:software:installed-source:/		{
			# This is a specific hack in the client to registrate the
			# version of scc installed from source.
			# Format of input is:
			# "scc.host.cur:fix:software:installed-source::scc:1.6.3
			printf( "%s:%s:%s\n", $1, $6, $7 );
			next;
		}
	/\.cur:fix:software:product:.*::Version[ 	]/	{
			# This is for Windows hosts, format of the input is:
			# scc.host.cur:fix:software:product:QuickTime::Version                  : 7.1
			# For some products, the version is absent. 
			# We need a value to display the systems per version.
			if ( $8 ~ "^[ 	]*$" )
			{
				$8 = "-";
			}
			printf( "%s:%s:%s\n", $1, $5, $8 );
			next;
		}
	/\.cur:fix:software:installed-rpms:/		{
			# Format of input is:
			# scc.host.cur:fix:software:installed-rpms:%{GROUP}::%{NAME}:%{VERSION}-%{RELEASE}
			printf( "%s:%s:%s\n", $1, $7, $8 );
			next;
		}'					|
sed	-e 's@^\./scc\.@smt-data:@'	\
	-e 's/\.cur//'					|
sort -f -u >${SMT_VERSIONS}
chown "${new_owner_group}" ${SMT_VERSIONS}

now=$(date '+%Y-%m-%d %H:%M:%S')

# Build all the scc.<sys>.smt.html files
awk -F: 'BEGIN	{
			c[ 0 ] = "Even";
			c[ 1 ] = "Odd";
		}
	/^general_data:/	{
		# Format of scc-summary.data is:
		#general_data:<host>:<model>:<os>:<release>:<last_day>:<last_time>

		curr_smt = sprintf( "./scc.%s.smt.html", $2 );
		visited[ $2 ] = 1;

		print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">" >curr_smt;
		print "<HTML>"								>>curr_smt;
		print "<HEAD>"								>>curr_smt;
		printf( "<LINK HREF=\"%s/%s/custom/style.css\" REL=\"stylesheet\" TYPE=\"text/css\">\n",\
			d, r )								>>curr_smt;
		printf( "<TITLE>System Tools: %s</TITLE>\n", $2 )			>>curr_smt;
		print "</HEAD>"								>>curr_smt;
		printf( "<BODY%s>\n", b )						>>curr_smt;
		printf( "<H1>System Tools: %s</H1>\n", $2 )				>>curr_smt;
		printf( "%s\n", h )							>>curr_smt;
		snapshot = sprintf( "scc.%s.html", $2 );
		printf( "<A HREF=\"%s/%s/%s\">Configuration</A>&nbsp;&nbsp;&nbsp;&nbsp;",\
			d, r, snapshot )						>>curr_smt;
		logbook = sprintf( "scc.%s.log.html", $2 );
		printf( "<A HREF=\"%s/%s/%s\">Logbook</A>\n", d, r, logbook )		>>curr_smt;
		printf( "<P>Last update on '"${now}"'</P>\n"  )				>>curr_smt;

		print "<PRE>"								>>curr_smt;
		print "Model   : " $3							>>curr_smt;
		print "OS      : " $4							>>curr_smt;
		print "Release : " $5							>>curr_smt;
		print "</PRE>"								>>curr_smt;

		print "<TABLE CLASS=SCC BORDER SUMMARY=SMT-summary CELLSPACING=1 CELLPADDING=4>"	>>curr_smt;

		print "<THEAD>"								>>curr_smt;
		print "	<TR class=Odd align=left>"					>>curr_smt;
		printf( "		<TH>%s</TH>\n", "Product" )			>>curr_smt;
		printf( "		<TH>%s</TH>\n", "Version" )			>>curr_smt;
		print "	</TR>"								>>curr_smt;
		print "</THEAD>"							>>curr_smt;

		print "<TBODY>"								>>curr_smt;

		close( curr_smt );
		tr_c = 2;

		next;
	}
	/^smt-data:/	{
		# Format of SMT_VERSIONS is:
		#smt-data:<host>:<software>:<version>
		if ( ! visited[ $2 ] )
		{
			next;			# Ignore when absent in scc-summary.data
		}

		curr_smt = sprintf( "./scc.%s.smt.html", $2 );
		if ( length( prev ) && ( curr_smt != prev ) )
		{
			print "</TBODY>"						>>prev;
			print "</TABLE>"						>>prev;
			print "</BODY>"							>>prev;
			print "</HTML>"							>>prev;
			close( prev );

			tr_c = 1;
		}
		prev = curr_smt;

		printf( "<TR class=%s align=left>\n", c[ tr_c++ % 2 ] )			>>curr_smt;
		printf( "	<TD class=Even>%s</TD>\n", $3 )				>>curr_smt;
		printf( "	<TD class=Odd>%s</TD>\n", $4 )				>>curr_smt;
		print "</TR>"								>>curr_smt;
	}
END	{
		if ( length( curr_smt ) )
		{
			print "</TBODY>"						>>curr_smt;
			print "</TABLE>"						>>curr_smt;
			print "</BODY>"							>>curr_smt;
			print "</HTML>"							>>curr_smt;
		}
	}'	b="${bg_color}"		\
		d="${scc_web_path_dir}"	\
		h="${HOME_URL}"		\
		l="${logo_tag}"		\
		r="${realm}"		\
			scc-summary.data ${SMT_VERSIONS}

# From now on, these files are accessible again by the web server.
# Ignore files in sub-directories (with more than one '/' in the name).
find . -name "scc.*.smt.html"		|
sed -e '/\/.*\//d'			|
xargs chown "${new_owner_group}" 2>/dev/null

find . -name "scc.*.smt.html"		|
sed -e '/\/.*\//d'			|
xargs chmod "${new_mode}" 2>/dev/null

# Build the start-table of scc-smt-index.html, containing a
# summary of all the System Tools and their versions.
rm -f scc-smt-index.html
cat >scc-smt-index.html <<-EndOfTxt
	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
	<HTML>
	<HEAD>
		<LINK HREF="${web_realm_dir}/custom/style.css" REL="stylesheet" TYPE="text/css">
		<TITLE>System Tools for ${realm}</TITLE>
	</HEAD>
	<BODY${bg_color}>
	<A NAME=cfg_top></A>
	<CENTER>
	<A HREF="${scc_web_path_dir}/scc-help/scc-smt-index.html">${logo_tag}</A>
	<H4>
		${HOME_URL}
		<A HREF="#cfg">Configuration</A>&nbsp;&nbsp;&nbsp;&nbsp;
		System Tools for ${realm}, last update on: ${now}
	</H4>

	<TABLE CLASS=SCC BORDER SUMMARY=SMT-summary CELLSPACING=1 CELLPADDING=4>

	<THEAD>
		<TR class=Odd align=left>
			<TH>Product</TH>
			<TH>Version</TH>
			<TH align=right>Count</TH>
		</TR>
	</THEAD>

	<TBODY>
EndOfTxt

sort -t: -f -k 3 -k 4 -k 2 ${SMT_VERSIONS}			|
awk -F: '{
	# Format of SMT_VERSIONS is:
	#smt-data:<host>:<software>:<version>

	# This script counts all the systems for each version of each tool.
	id = sprintf( "%s:%s", $3, $4 );
	count[ id ] += 1;
	prev=id;
}
END	{
	for ( s in count )
	{
		# Format of the output is: <name>:<version>:<count>
		printf( "%s:%d\n", s, count[ s ] );
	}
}'							|
sort -t: -f -k 1 -k 2 -k 3n					|
awk -F":" 'BEGIN	{
			c[ 0 ] = "Even";
			c[ 1 ] = "Odd";
			tr_c = 2;		# TR class; TR from THEAD already done
		}
	{
	printf( "<TR class=%s align=left>\n", c[ tr_c++ % 2 ] );
	if ( $1 != prev )
	{
		if ( total > 0 )
		{

			print "	<TD class=Even align=right>&nbsp;</TD>";
			print "	<TD class=Odd>total</TD>";
			print "	<TD class=Even align=right>" total "</TD>"

			print "</TR>";

			total = 0;

			printf( "<TR class=%s align=left>\n", c[ tr_c++ % 2 ] );
		}
		print "	<TD class=Even>" $1 "</TD>";
		prev=$1;
	}
	else
	{
		print "	<TD class=Even align=right>" "&nbsp;" "</TD>";
	}
	# Format of the input is: <name>:<version>:<count>
	url = sprintf( "%s_%s", $1, $2 );
	gsub( /[^A-Za-z0-9_.-]/, "_", url );		# W3C restrictions and no ":".
	printf( "	<TD class=Odd><A HREF=\"#%s\">%s</A></TD>\n", url, $2 );
	print "	<TD class=Even align=right>" $3 "</TD>";
	total += $3;
	print "</TR>";
}
END	{
	if ( total > 0 )
	{
		printf( "<TR class=%s align=left>\n", c[ tr_c++ % 2 ] );
		print "	<TD class=Even align=right>&nbsp;</TD>";
		print "	<TD class=Odd>total</TD>";
		print "	<TD class=Even align=right>" total "</TD>"
		print "</TR>";
	}

	print "</TBODY>";
	print "</TABLE>";
}' >>scc-smt-index.html
chown "${new_owner_group}" scc-smt-index.html

# Build the additional tables for each version of each tool.
sort -f -t: -k 3 -k 4 -k 1 ${SMT_VERSIONS}		|
awk -F: 'BEGIN	{
			c[ 0 ] = "Even";
			c[ 1 ] = "Odd";
			tr_c = 1;		# TR class 
		}
	{
	# Format of SMT_VERSIONS is:
	#smt-data:<host>:<software>:<version>

	# Format of scc-summary.data is:
	#general_data:<host>:<model>:<OS>:<release>:<date last run>:<time last run>

	if ( NF == 7 )
	{
		if ( length( $3 ) )
		{
			model[ $2 ] = $3;
		}
		else
		{
			model[ $2 ] = "&nbsp;"
		}
		os[ $2 ] = $4;
		release[ $2 ] = $5;
		next;
	}

	id = sprintf( "%s_%s", $3, $4 );
	if ( id != prev )
	{
		if ( length( prev ) )
		{
			print "</TBODY>";
			print "</TABLE>";
		}
		print "<BR><BR>";
		url = sprintf( "%s_%s", $3, $4 );
		gsub( /[^A-Za-z0-9_.-]/, "_", url );		# W3C restrictions and no ":".
		printf( "<H4>%s<A NAME=\"%s\">Product: %s, version: %s</A></H4>\n",	\
			"<A HREF=\"#cfg_top\">Top</A>&nbsp;&nbsp;&nbsp;&nbsp;", url, $3, $4 );
		prev = id;

		print "<TABLE CLASS=SCC BORDER SUMMARY=SMT-summary CELLSPACING=1 CELLPADDING=4>";

		print "<THEAD>";
		printf( "<TR class=%s align=left>\n", c[ tr_c++ % 2 ] );
		printf( "		<TH>%s</TH>\n", "System" );
		printf( "		<TH>%s</TH>\n", "Model" );
		printf( "		<TH>%s</TH>\n", "OS" );
		printf( "		<TH>%s</TH>\n", "Release" );
		print "	</TR>";
		print "</THEAD>";

		print "<TBODY>";
	}
	printf( "<TR class=%s align=left>\n", c[ tr_c++ % 2 ] );
	# to open this in a new window, add the attribute: TARGET="_blank"
	printf( "	<TD class=Even><A HREF=\"%s/%s/scc.%s.smt.html\">%s</A></TD>\n", d, r, $2, $2 );
	printf( "	<TD class=Odd>%s</TD>\n", model[ $2 ] );
	printf( "	<TD class=Even>%s</TD>\n", os[ $2 ] );
	printf( "	<TD class=Odd>%s</TD>\n", release[ $2 ] );
	print "</TR>";
}
END	{
	print "</TBODY>";
	print "</TABLE>";
	print "</CENTER>";
}' d="${scc_web_path_dir}" r="${realm}" scc-summary.data - >>scc-smt-index.html

{
	echo "	<HR>"
	echo "	<A NAME=\"cfg\"></A>"
	echo "	<H4><A HREF=\"#cfg_top\">Top</A>&nbsp;&nbsp;&nbsp;&nbsp;Configuration files</H4>"
	echo "	<P>The program scc-smt uses the following configuration file for this realm:</P>"

	echo "	<H4>scc-smt-select</H4>"
	echo "	<PRE>"
	sed	-e '/^#/d'		\
		-e '/^[ 	]*$/d'	\
		-e 's/&/\&amp;/g'	\
		-e 's/</\&lt;/g'	\
		-e 's/>/\&gt;/g'	\
		-e "s/'/\&#39;/g"	\
		-e 's/"/\&quot;/g' custom/scc-smt-select
	echo "	</PRE>"

	echo "	</BODY>"
	echo "</HTML>"
} >>scc-smt-index.html

exit 0
