#!/bin/sh
#
# @(#)sdist.sh,v 1.16 2011/09/02 14:44:12 kim Exp
#
# David M. Siegel Mon Oct 26, 1992 at 10:30:29
# Kimmo Suominen 1995-05-20, 1996-02-16
# Christos Zoulas Wed Sep 18 16:32:58 EDT 1996
# Kimmo Suominen 1998-10-09, 1999-08-30, 2009-11-10
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. The name of the author may not be used to endorse or promote
#    products derived from this software without specific prior
#    written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

PATH=/usr/local/bin:/bin:/usr/bin:/usr/sbin:/usr/etc:/usr/ucb
PATH=${PATH}:/usr/pkg/bin:/usr/pkg/sbin
export PATH

noarch=false
norel=false
world=false

allmasters=
servers=
destdir=

maxkids=4
extras=

PAWD=pwd
RDIST=rdist6
RSH=rsh
SRSH=/usr/pkg/bin/srsh

# ropts and rargs are given to the local rdist
ropts=
rargs=

# sopts and sargs get passed along to sdist via RSH in an 'sdist -A'
sopts=
sargs=

# local logging options; default taken from rdist6 source
logopts="stdout=all:notify=all:syslog=nerror,ferror"

# Who to notify
notify=logs-rdist

# default timeout for rdist -- 2 minutes instead of 15
timeout=120

# Override from configuration file if there.
if [ -f /etc/sdist.conf ]
then
	. /etc/sdist.conf
fi

domain=$(netname -d)
cwd=$(${PAWD})

while getopts AD:M:RScd:f:gh:l:no:qrst:vx:yz opt
do
	case "${opt}" in
	A)	# Don't propagate -A
		world=true
		;;
	f) 	# No need to remember this -- incompatible with -A
		if [ ! -s "${OPTARG}" ]
		then
			echo "${0}: No file ${OPTARG}" 1>&2
			exit 1
		fi
		for i in $(cat "${OPTARG}")
		do
			x=$(netgroup "${i}")
			case "${x}" in
			'')	# Must be a hostname
				x="${i}"
				;;
			*)	# Aha, was a netgroup after all
				;;
			esac
			servers="${servers} ${x}"
		done
		;;
	h) 	# No need to remember this -- incompatible with -A
		x=$(netgroup "${OPTARG}")
		case "${x}" in
		'')	# Must be a hostname
			x="${OPTARG}"
			;;
		*)	# Aha, was a netgroup after all
			;;
		esac
		servers="${servers} ${x}"
		;;
	l)
		sargs="${sargs} -${opt} '${OPTARG}'"
		logopts="${OPTARG}"
		;;
		
	[DMdotx])
		sargs="${sargs} -${opt} '${OPTARG}'"
		case "${opt}" in
		D)	destdir="${OPTARG}";;
		M)	maxkids="${OPTARG}";;
		t)	timeout="${OPTARG}";;
		x)	extras="${extras} ${OPTARG} ; ";;
		*)	rargs="${rargs} -${opt} ${OPTARG}";;
		esac
		;;
	*)
		sopts="${sopts}${opt}"
		case "${opt}" in
		c)	norel=true;;
		g)	noarch=true;;
		r)	ropts="${ropts}R";;
		[sS])	export RDIST_RSH
			RDIST_RSH="${SRSH}"
			RSH=ssh
			rargs="${rargs} -P ${SRSH}"
			;;
		*)	ropts="${ropts}${opt}";;
		esac
		;;
	esac
done
shift $(expr ${OPTIND} - 1)

if [ -z "${servers}" ]
then
	case ${noarch} in
	true)	case ${norel} in
		true)	netgroup=dist-$(osname) ;;
		*)	netgroup=dist-$(osname -release);;
		esac
		;;
	*)	case ${norel} in
		true)	netgroup=dist-$(osname -group);;
		*)	netgroup=dist-$(osname -relgroup);;
		esac
		;;
	esac

	# Always dist to local domain.
	servers=$(netgroup "${netgroup}")
	if [ -z "${servers}" ]
	then
		echo "${0}: No netgroup ${netgroup}" 1>&2
		exit 1
	fi

	case ${world} in
	true)	remotes=$(netgroup "${netgroup}-masters")
		if [ -z "${remotes}" ]
		then
			echo "${0}: No netgroup ${netgroup}-masters" 1>&2
			exit 1
		fi

		# Add the masters to the first pass of rdist. Doing the
		# local servers and remotes in the first pass optimises
		# distribution time as remotes are often behind a slow
		# link. Now we get the local domain updated faster than
		# if we waited for the second round of rdist processes
		# run on each master.
		servers="${servers} ${remotes}"

		# Pull current domain out of list of domains-to-push-to
		# since they should be in the (non-master) netgroup
		# already.
		allmasters=
		for i in ${remotes}
		do
			if [ $(netname -d "${i}") != "${domain}" ]
			then
				allmasters="${allmasters} ${i}"
			fi
		done
		;;
	esac
fi

case $# in
0)	set -- ${cwd};;
esac

for directory
do
	case "${destdir}" in
	'')	case "${directory}" in
		/*)	;;
		*)	directory="${cwd}/${directory}";;
		esac
		;;
	*)	;;
	esac
	dirs="${dirs} ${directory}"
done

if [ -n "${ropts}" ]
then
	ropts="-${ropts}"
fi

if [ -n "${sopts}" ]
then
	sopts="-${sopts}"
fi

# Use an rdist file for multiple directories and parallel updates.
${RDIST} -t ${timeout} -l ${logopts} -M ${maxkids} \
    ${ropts} ${rargs} -f - << __EOF || exit $?
	(${dirs})	-> (${servers})
			${extras}
			install ${destdir} ;
			notify ${notify} ;
__EOF

if [ -n "${allmasters}" ]
then
	for i in ${allmasters}
	do
		echo "Initiatiating remote updates to ${i}"
		${RSH} -n ${i} "sdist ${sopts}${sargs} ${dirs}" || exit $?
	done
	wait
fi

exit 0
