#!/bin/sh

# Shell script to update SCC-data in website.
# 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.78 $


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 SCC_WWW=${SCC_DATA}/www

export SHELL=/bin/sh
export LANG=C

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

umask 077

# Some systems do not have the nice program.
nice_e="$(which nice 2>/dev/null)"
if [ ! -x "${nice_e}" ]
then
	alias nice=""
fi

# 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

if [ ! -d ${SCC_WWW} ]
then
	exit 0
fi

export TMP_FILE_1=${SCC_TMP}/scc_update_1_$$
rm -f ${TMP_FILE_1}

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

scc_auto_realm()
{
	config="${1}"

	# Global steps to perform:
	#
	# 1: Get the data of the hosts in realm All
	# 2: Produce matching actions from config file
	# 3: Check and add/remove host from realm

	# Syntax of this file is:
	# general_data:<hostname>:<model>:<OS>:<OS-release>:<last_run>:<last_change>:<domain>
	awk -F: '{ printf( "%s:%s:%s:%s\n", $2, $8, $4, $5 ) }' ${SCC_WWW}/All/scc-summary.data	|
	while read data
	do
		# 2: Produce matching actions from config file

		#data is: host:domain:os:release
		# Catch awk-messages and report them at the end.
		awk -F:	'/^[ 	]*#/	{ next }
			/^[ 	]*$/	{ next }
					{
						# Syntax of this file is:
						# <action>:<hostname>:<domain>:<OS>:<OS-release>
						pattern = sprintf( "^%s:%s:%s:%s$", $2, $3, $4, $5 );
						if ( p ~ pattern )
						{
							cnt = split( p, parts, ":" );
							print $1, parts[ 1 ];
							exit;		# Stop processing as soon as a match has been found.
						}
					}'					\
						p="${data}"			\
							<${config}		\
							2>${TMP_FILE_1}
	done											|
	while read action host
	do
		# 3: Check and add/remove host from realm

		case "${action}" in
		add)	# when the host is absent, add it to the realm
			if [ ! -f ${SCC_WWW}/${realm}/scc.${host}.cur ]
			then
				${SCC_BIN}/scc-realm -q -a ${host} ${realm}
			fi
			;;

		skip)	# when host is present, delete it from the realm
			if [ -f ${SCC_WWW}/${realm}/scc.${host}.cur ]
			then
				${SCC_BIN}/scc-realm -q -d ${host} ${realm}
			fi
			;;
		esac
	done

	if [ -s ${TMP_FILE_1} ]
	then
		echo "${ProgName}: configuration errors in ${config}:" >&2
		cat ${TMP_FILE_1} >&2
		exit 2
	fi
}

cd ${SCC_WWW}
lock_cfg="${SCC_WWW}/lock"
if [ -f "${lock_cfg}" ]
then
	echo "${ProgName}: another instance is active, check process ID in ${lock_cfg}" >&2
	exit 2
fi
echo "$$" >"${lock_cfg}"

# Do not install the traps earlier, as the above exit will remove the
# lock file from the other, running invocation of this program.
trap "rm -f ${lock_cfg}" 0
trap "exit 2" 1 2 3 15

conf_scc_web_path="$(sed -n 's/^SCC_WEB_PATH=//p' ${SCC_CONF}/scc.conf 2>/dev/null)"

SYNTAX="Syntax error, use: ${ProgName} [ -d <scc_web_path> ] [ -f ] [ -m <mail_ug> ] [ -w <web_usr> ] [ <dir> ]"

opt_scc_web_path=""
force_summary=""
new_owners=""
www_user="${www_user:-}"

while [ $# -gt 0 ]
do
	if [ $# -eq 1 ]
	then
		case "${1}" in
		-*)	# All options, except the ones in the following list, should have an argument.
			if [ "x${1}" != "x-f" ]
			then
				echo "${ProgName}: Syntax error, missing argument for option: $1" 
				exit 2
			fi;;
		*)	# Finished with options, goto argument
			break;;
		esac
	fi

	case "${1}" in
	-d)	opt_scc_web_path="${2}"
		shift 2;;

	-f)	force_summary="-f"
		shift 1;;

	-m)	chown -R "${2}" ${SCC_DATA}/transfer/mail ${SCC_DATA}/log/scc-transfer.log 2>/dev/null
		echo "${2}" >${SCC_DATA}/transfer/mail_user_group	# Record for upgrade of scc-srv
		if [ "${2#*:}" ]
		then
			chgrp "${2#*:}" ${SCC_DATA}/log
		fi
		new_owners="yes"
		shift 2;;

	-w)	www_user=${2%:*}
		chown -R ${www_user} ${SCC_DATA}/www/* ${SCC_CONF} ${SCC_DATA}/log/scc.cgi.log 2>/dev/null
		chown ${www_user} ${SCC_TMP} ${SCC_DATA}/log
		new_owners="yes"
		shift 2;;

	*)	break;;
	esac
done

if [ $# -gt 1 ]
then
	echo "${SYNTAX}" >&2
	exit 2
fi
single_realm=""
if [ $# -eq 1 ]
then
	single_realm="${1}"
	if [ ! -d "${single_realm}" ]
	then
		echo "${ProgName}: realm '${1}' not found" >&2
		exit 1
	fi
fi

# No -w option used. Use the owner of the existing website.
if [ ! "${www_user}" ]
then
	set dummy $(ls -ld All)
	www_user="${4}"
fi

new_scc_web_path=""
if [ "${opt_scc_web_path}" -a "${conf_scc_web_path}" != "${opt_scc_web_path}" ]
then
	# Only change the document-root in the config-file.
	cat <<-_X_ | ed -s ${SCC_CONF}/scc.conf 2>/dev/null
		1,$ s@^[# ]*SCC_WEB_PATH=.*@SCC_WEB_PATH=${opt_scc_web_path}@
		w
		q
	_X_

	# Check whether scc.conf contained SCC_WEB_PATH in the first place.
	grep -l "^SCC_WEB_PATH=" ${SCC_CONF}/scc.conf 2>/dev/null >/dev/null
	if [ $? -ne 0 ]
	then
		echo "SCC_WEB_PATH=${opt_scc_web_path}" >>${SCC_CONF}/scc.conf
	fi
	chown "${www_user}" ${SCC_CONF}/scc.conf	# Just in case it was removed?!?

	new_scc_web_path="yes"
	conf_scc_web_path="${opt_scc_web_path}"
fi

if [ ! "${single_realm}" ]
then
	nice ${SCC_BIN}/scc-transfer
	transfer_result=$?
	if [ ${transfer_result} -eq 1 -o ${transfer_result} -eq 2 ]
	then
		exit 1
	fi
else
	transfer_result=3
fi
NO_FILES=0

if [ "${new_scc_web_path}" -o -n "${force_summary}" ]
then
	# The following files use the document-root, but they are not produced by scc-summary, scc-smt or scc.cgi.
	# So, we update them.
	for f in index.html scc-help/*.html
	do
		if [ -f "${f}" ]
		then
			STYLE="/custom/style.css"
			LOGO="/custom/scc-logo.png"
			sed	-e "s@<A HREF=.*/scc-help/\([^>][^>\"]*\)\"*>@<A HREF=\"${conf_scc_web_path}/scc-help/\1\">@" \
				-e "s@<LINK HREF=.*${STYLE}.*REL=@<LINK HREF=\"${conf_scc_web_path}${STYLE}\" REL=@" \
				-e "s@<IMG SRC=.*${LOGO}\"@<IMG SRC=\"${conf_scc_web_path}${LOGO}\"@"			\
				<${f} >${f}.tmp
			mv -f ${f}.tmp ${f}
			chown "${www_user}" "${f}"
			chmod 440 "${f}"
		fi
	done
fi

# When no files have been transferred, the summaries do not need to be updated.
# Except when we are updating the ownership or the document-root, these updates have to 
# be done on the summaries too.
if [	${transfer_result} -ne ${NO_FILES}	-o	\
	"${new_owners}"				-o	\
	"${new_scc_web_path}"			-o	\
	-n "${force_summary}"					]
then
	# scc_auto_realm requires an uptodate file All/scc-summary.data, so process realm All first.
	# The second run for All (via the * in the loop) will be quick as no snapshots will be
	# more recent than the summary file.
	for realm in All *
	do
		if [ "${single_realm}" -a "${realm}" != "${single_realm}" ]
		then
			continue
		fi

		if [ -h "${realm}" ]
		then
			# Ignore a symbolic link. We will generate the summaries for the directory itself.
			continue
		fi

		if [ -d "${realm}" -a -f "${realm}/custom/scc-logo.png" -a -x "${realm}/cgi-bin/scc-wrapper.cgi" ]
		then
			# Check whether this realm uses a config file to automate populating the realm.
			# Changes should not be done on the All realm.
			# Adding is not a problem (the snapshot exists already), but removing the snapshot is not a good idea.
			auto_config="${SCC_WWW}/${realm}/custom/scc-auto-realm.conf"
			if [ "${realm}" != "All" -a -f "${auto_config}" ]
			then
				# Ignore comments and empty lines in the config file.
				data="$(sed -e '/^[ 	]*#/d' -e '/^[ 	]*$/d' ${auto_config} 2>/dev/null )"
				if [ "${data}" ]		# config data remaining?
				then
					scc_auto_realm "${auto_config}"
				fi
			fi

			if [ -f scc-summary.data ]
			then
				# Determine files newer than scc-summary.data and ignore sub-directories.
				newer="$(cd "${realm}"; find . -follow -newer scc-summary.data -name "scc.*.cur" |
					sed -e '/\/.*\//d')"
				if [ -z "${newer}" ]
				then
					# All snapshots are older then scc-summary.data.
					# Therefore all summaries are uptodate.
					continue;
				fi
			fi

			nice ${SCC_BIN}/scc-rules -d "${conf_scc_web_path}" "${realm}"
			nice ${SCC_BIN}/scc-summary -d "${conf_scc_web_path}" ${force_summary} "${realm}"
			nice ${SCC_BIN}/scc-smt -d "${conf_scc_web_path}" "${realm}"
		fi
	done
fi

exit 0
