#!/bin/sh

# Shell script pull scc-data from clients.
# 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.25 $


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 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

# On some systems remsh does not exist, use rsh instead.
which remsh >/dev/null 2>/dev/null
if [ $? -eq 1 ]
then
	alias remsh="$(which rsh 2>/dev/null)"
fi
alias ovdeploy=/opt/OV/bin/ovdeploy

client_list()
{
	case ${client_select_method} in
	file)	sed	-e "/^#/d"		\
			-e "/^[ 	]*$/d"	\
				<"${client_select_arg}"
		;;

	list)	echo "${client_select_arg}"		|
		tr "," "\012"
		;;

	realm)	ls "${client_select_arg}"		|
		sed -n	-e "s@scc.@@"		\
			-e "s@\.cur@@p"
		;;
	esac
}

SYNTAX="Syntax error, use: ${ProgName} [ -B <bin> ] [ -c <remark> ] [ -D <data> ] [ -d <delay> ] [ -I <ident> ] [ -n ] [ -p <prog> ] [ -s <dest> ] [ -e <module> ] [ -m <max> ] [ -u <user> ] [ -R <realm> | -L <list> | -S <systems> ]"

client_bin_dir="$(echo ${SCC_BIN} | sed -e 's/scc-srv/scc/')"
client_data_dir="$(echo ${SCC_DATA}/transfer | sed -e 's/scc-srv/scc/')"

delay=600
do_run=1
client_options=" -p pull "

dest=${SCC_DATA}/transfer/cp
ident_file=""

client_select_method="realm"
client_select_arg="${SCC_WWW}/All"
prog="ssh"
# Remote activation of scc is alway done by root.
# The following user transfers the files from the clients to the server.
# This feature has been suggested by Sven Weise.
remote_user="root"
user="$(id | sed -e 's/).*//' -e 's/.*(//')"
if [ "${user}" != "root" ]
then
	remote_user="${user}"
fi
while [ $# -gt 1 ]
do
	if [ $# -eq 1 ]
	then
		# All options, except the ones in the following list, should have an argument.
		if [ "x${1}" != "x-n" ]
		then
			echo "${ProgName}: Syntax error, missing argument for option: $1" 
			exit 2
		fi
	fi

	case "${1}" in
	-L)	if [ ! -f "${2}" ]
		then
			echo "${ProgName}: cannot find file ${2}" >&2
			exit 2
		fi
		client_select_method="file"
		client_select_arg="${2}"
		shift 2
		;;

	-R)	if [ ! -d "${SCC_WWW}/${2}" ]
		then
			echo "${ProgName}: cannot find realm ${2}" >&2
			exit 2
		fi
		client_select_method="realm"
		client_select_arg="${SCC_WWW}/${2}"
		shift 2
		;;

	-S)	client_select_method="list"
		client_select_arg="${2}"
		shift 2
		;;

	-B)	client_bin_dir="${2}"
		shift 2
		;;

	-D)	client_data_dir="${2}"
		shift 2
		;;

	-d)	delay="${2}"
		shift 2
		;;

	-I)	if [ ! -f "${2}" ]
		then
			echo "${ProgName}: cannot find file ${2}" >&2
			exit 2
		fi
		ident_file=" -i ${2} "
		shift 2
		;;

	-n)	do_run=0
		shift 1
		;;

	-p)	case "${2}" in
		ssh|rsh)	prog="${2}";;
		ovdeploy)	if [ ! -x /opt/OV/bin/ovdeploy ]
				then
					echo "${ProgName}: cannot find ovdeploy" >&2
					exit 2
				fi
				prog=ovdeploy
				;;
		*)		echo "${ProgName}: unsupported method: ${2}" >&2
				exit 2
				;;
		esac
		shift 2
		;;

	-s)	if [ ! -d "${2}" ]
		then
			echo "${ProgName}: cannot find directory ${2}" >&2
			exit 2
		fi
		dest="${2}"
		shift 2
		;;

	-m|-e|-c)	client_options="${client_options} ${1} \"${2}\""
		shift 2
		;;

	-u)	client_options="${client_options} ${1} \"${2}\""
		remote_user=${2}
		shift 2
		;;

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

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

if [ ${do_run} -eq 1 ]
then
	SCC="${client_bin_dir}/scc"
	client_cmd="${SCC} ${client_options} </dev/null >\"${client_data_dir}/scc-pull.log\" 2>&1"
	client_list				|
	while read client
	do
		case "${prog}" in
		ovdeploy)	if [ ${delay} -gt 0 ]
			then
				ovdeploy -ovrg server -cmd nohup -par "${client_cmd} &" -host ${client}
			else
				ovdeploy -ovrg server -cmd "${SCC}" -par "${client_options}" -host ${client}
			fi
			;;

		rsh)	if [ ${delay} -gt 0 ]
			then
				remsh -n ${client} "nohup ${client_cmd} &" >/dev/null 2>&1
			else
				remsh -n ${client} "${client_cmd}" >/dev/null 2>&1
			fi
			;;

		ssh)	if [ ${delay} -gt 0 ]
			then
				ssh -n -q ${ident_file} ${client} "nohup ${client_cmd} &" >/dev/null 2>&1
			else
				ssh -n -q ${ident_file} ${client} "${client_cmd}" >/dev/null 2>&1
			fi
			;;

		esac
	done

	if [ ${delay} -gt 0 ]
	then
		sleep ${delay}
	fi
fi

# Make certain that we have an empty directory.
rm -rf ${dest}/scc-pull
mkdir -p ${dest}/scc-pull
cd ${dest}/scc-pull

# We cannot use a variable to indicate errors from within the loop, as the commands in the
# loop are executed by a sub-shell. Therefore we use a file to indicate errors.
exit_status=0
export MISSING_DATA=missing_data				# Not (yet) present in the emptied directory.
client_list					|
while read client
do
	case "${prog}" in
	ovdeploy)	ovdeploy -ovrg server -download -dir "${client_data_dir}" -targetdir ${dest}/scc-pull -host ${client} >/dev/null
		if [ $? -ne 0 ]
		then
			echo "${ProgName}: missing data for ${client}" >&2
			touch ${MISSING_DATA}				# Signal missing data from client
			continue
		fi
		# In contrast with the other methods, we downloaded not only the signal file(s), but also the data files.
		# Now we move them to the proper directory or remove them when the remote client was still running.
		for f in *.signal
		do
			host=${f%.signal}
			host=${host#scc.}
			if [ -s "${f}" ]
			then
				>${dest}/scc.${host}.signal
				mv scc.${host}.tar* ${dest}
				echo "done" >${dest}/scc.${host}.signal
				ovdeploy -ovrg server -cmd rm -par "-f ${client_data_dir}/scc.${host}.*" -host ${client}
			else
				echo "${ProgName}: missing data for ${host}" >&2
				touch ${MISSING_DATA}				# Signal missing data from host
			fi
			rm -f scc.${host}.signal scc.${host}.tar*
		done
		;;

	rsh)	rcp ${remote_user}@${client}:${client_data_dir}/*.signal . 2>/dev/null
		if [ $? -ne 0 ]
		then
			echo "${ProgName}: missing data for ${client}" >&2
			touch ${MISSING_DATA}				# Signal missing data from client
			continue
		fi
		for f in *.signal
		do
			host=${f%.signal}
			host=${host#scc.}
			if [ -s "${f}" ]
			then
				>${dest}/scc.${host}.signal
				rcp ${remote_user}@${client}:${client_data_dir}/scc.${host}.tar* ${dest}
				echo "done" >${dest}/scc.${host}.signal
				remsh "${client}" -l ${remote_user} "rm -f ${client_data_dir}/scc.${host}.*" </dev/null
			else
				echo "${ProgName}: missing data for ${host}" >&2
				touch ${MISSING_DATA}				# Signal missing data from host
			fi
			rm -f "${f}"
		done
		;;

	ssh)	scp -q ${ident_file} ${remote_user}@${client}:${client_data_dir}/*.signal . 2>/dev/null
		if [ $? -ne 0 ]
		then
			echo "${ProgName}: missing data for ${client}" >&2
			touch ${MISSING_DATA}				# Signal missing data from client
			continue
		fi
		for f in *.signal
		do
			# Each client can send data for several (virtual) hosts (using the -v option or a split-file).
			host=${f%.signal}
			host=${host#scc.}
			if [ -s "${f}" ]
			then
				>${dest}/scc.${host}.signal
				scp -q ${ident_file} ${remote_user}@${client}:${client_data_dir}/scc.${host}.tar* ${dest}
				echo "done" >${dest}/scc.${host}.signal
				ssh -n -q ${ident_file} "${remote_user}@${client}" "rm -f ${client_data_dir}/scc.${host}.*"
			else
				echo "${ProgName}: missing data for ${host}" >&2
				touch ${MISSING_DATA}				# Signal missing data from host
			fi
			rm -f "${f}"
		done
		;;

	esac
done
if [ -f ${MISSING_DATA} ]
then
	exit_status=3			# Indicate runtime-error.
fi

cd ${SCC_WWW}
rm -rf ${dest}/scc-pull

if [ "${user}" = "root" ]
then
	scc-update
fi

exit ${exit_status}
