#! /bin/sh

# Fetch, build, install, and start a new version of the DCC just
#   as it was configured last time.

# This script should only be used after the DCC has been correctly
#   configured and installed.

# This script should usually not be used if configuration changes are needed.
#   Instead use `./configure ...; make install` as usual.  That will create
#   a new version of this script with the ./configure settings captured.
#
#   However, -eENV=VAL and -cCONF=VAL can be used to tweak an installation,
#   as in `updatedcc -c--with-uid=dcc` or `updatedcc -c--without-uid`

#   -e ENV=VAL	set environment variable ENV to VAL before running ./configure

#   -c CONF=VAL	add "CONF=VAL" to the end of the settings given ./configure

#   -s base-URL	fetch the tarball using base-URL instead of the default.
#		    The name of the tarball is appended to base-URL.

#   -V x.y.z	try to fetch version x.y.z of the tarball instead of the
#		    the most recent verison

#   -C pfile	fetch theDCC source using parameters in pfile

#   -T make-tgt	target for `make` instead of "install"

#   -U		only fetch, unpack, and configure the tarball


# The following environment variables are set by this script to their values
#   when ./configure or this script was last run:
# NOMAN DCC_SUID DCC_OWN DCC_GRP DCC_MODE MANOWN MANGRP CFLAGS DCC_CFLAGS PTHREAD_CFLAGS LDFLAGS DCC_LDFLAGS PTHREAD_LDFLAGS LIBS PTHREAD_LIBS CC INSTALL DCCD_MAX_FLOODS DBGFLAGS

# This script should be run as root, but can be run as the non-root
# user that runs dccm and dccd.  If not run as root, it cannot install
# man pages or user commands such cdcc and dccproc.


# Copyright (c) 2006 by Rhyolite Software, LLC
#
# This agreement is not applicable to any entity which sells anti-spam
# solutions to others or provides an anti-spam solution as part of a
# security solution sold to other entities, or to a private network
# which employs the DCC or uses data provided by operation of the DCC
# but does not provide corresponding data to other users.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# Parties not eligible to receive a license under this agreement can
# obtain a commercial license to use DCC and permission to use
# U.S. Patent 6,330,590 by contacting Commtouch at http://www.commtouch.com/
# or by email to nospam@commtouch.com.
#
# A commercial license would be for Distributed Checksum and Reputation
# Clearinghouse software.  That software includes additional features.  This
# free license for Distributed ChecksumClearinghouse Software does not in any
# way grant permision to use Distributed Checksum and Reputation Clearinghouse
# software
#
# THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
# BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.

# Rhyolite Software DCC 1.3.45-1.74 $Revision$
# Generated automatically from updatedcc.in by configure.

exec </dev/null

DCC_HOMEDIR=/etc/dcc
DCC_LIBEXEC=/usr/libexec/dcc	    # in case dcc_conf has disappeared
. $DCC_HOMEDIR/dcc_conf
BDIR=$DCC_HOMEDIR/build
BURLS=
VERSION=

USAGE=`basename $0`': [-xvU] [-e ENV=VAL] [-c CONF=VAL] [-s base-URL] [-V x.y.z]\\
	[-C pfile] [-T make-tgt]'
CQUIET='--quiet'
WGETQUIET='-nv'
MQUIET=
DEBUG=
UNPACK=
EVALS=
EVARS=
CONFS=
PFILE=""
MAKE_TGT=install
while getopts "xvUe:c:s:V:p:C:T:" c; do
    case $c in
    x) set -x; DEBUG=-x; CQUIET= MQUIET='#';;
    v) CQUIET= MQUIET='#' WGETQUIET=;;
    U) UNPACK=yes;;
    e) EVAR=`expr "X$OPTARG" : 'X\([_a-zA-Z0-9][_a-zA-Z0-9]*\)='`
	if test -z "$EVAR"; then
	    echo "$USAGE" 1>&2; exit 1
	fi
	EVARS="$EVARS $EVAR"
	EVALS="$EVALS $OPTARG"
	;;
    c) CONFS="$CONFS $OPTARG";;
    s) BURLS="$BURLS $OPTARG";;
    V) VERSION=`expr "X$OPTARG" : 'X\([1-9]\.[1-9][0-9]*\.[1-9][0-9]*\)'`
	if test "$VERSION" != "$OPTARG"; then
	    echo "invalid -V $OPTARG" 1>&2; exit 1;
	fi
	;;
    C) PFILE="$OPTARG";;
    T) MAKE_TGT="$OPTARG";;
    p) echo "All 3 DCC tarballs are now the same";;
    *) echo "$USAGE" 1>&2; exit 1;;
    esac
done
shift `expr $OPTIND - 1 || true`
if test "$#" -ne 0; then
    echo "$USAGE" 1>&2; exit 1
fi

if test -z "$PFILE"; then
    if test -n ""; then
	CONFS="--without-updatedcc-pfile $CONFS"
    fi
    # quietly use $DCC_HOMEDIR/.updatedcc_pfile if it exists
    if test -s "$DCC_HOMEDIR/.updatedcc_pfile"; then
	PFILE=$DCC_HOMEDIR/.updatedcc_pfile
    fi
else
    PFILE=`echo $PFILE | sed "s@^[^/]@$DCC_HOMEDIR/&@"`
    # do not configure it if it is the default
    if test "$PFILE" != "$DCC_HOMEDIR/.updatedcc_pfile"; then
	CONFS="--with-updatedcc-pfile=$PFILE $CONFS"
    fi
fi
if test -n "$PFILE"; then
    . $PFILE
fi

if test -z "$BURLS"; then
    if test -n "$SERVER"; then
	BURLS="$SERVER"
    else
	BURLS="http://www.dcc-servers.net/dcc/source http://www.rhyolite.com/anti-spam/dcc/source ftp://ftp.dcc-servers.net/src/dcc ftp://ftp.rhyolite.com/src/dcc"
    fi
fi

if test -z "$VERSION"; then
    DLTBALL="dcc.tar.Z"
    TBALL=
    TBALL_PATH="$DLTBALL"
else
    DLTBALL="dcc-$VERSION.tar.Z"
    TBALL="$DLTBALL"
    TBALL_PATH="old/$DLTBALL"
fi
# don't blab the password needlessly
print_url () {
    PURL=`echo "$2" | sed -e 's%^\([fhtp]*://\)[^/@:]\{1,\}:[^/@:]\{1,\}@%\1%'`
    echo "using $1 to get $PURL"
}

# unsetting variables that are not set often yields a non-zero exit status
unset NOMAN DCC_SUID DCC_OWN DCC_GRP DCC_MODE MANOWN MANGRP DCC_CFLAGS PTHREAD_CFLAGS LDFLAGS DCC_LDFLAGS PTHREAD_LDFLAGS LIBS PTHREAD_LIBS CC INSTALL DCCD_MAX_FLOODS DBGFLAGS

if test -z "$UNPACK"; then
    # start stopping dccd in the hope that it will have released the sockets
    #   and database files by the time we need to restart it.
    RESTART="trap 0 1 2 15; $DCC_LIBEXEC/rcDCC $DEBUG start"
    trap "$RESTART" 0 1 2 15

    sh $DCC_LIBEXEC/stop-dccd $DEBUG
    # switch to a backup DCC server
    /usr/bin/cdcc rtt >/dev/null 2>&1
fi

set -e

if test ! -d $BDIR; then
    mkdir $BDIR
fi
cd $BDIR


# use fetch, wget, curl, or ftp that understands URLs
#	notice '-c --with-fetch_cmd=X'
PGM=`echo "X $confs" | sed -n -e 's/.*--with-fetch[-_]cmd=\([^ ]*\)/\1/p'`
if test -z "$PGM"; then
    PGM=ftp
fi
PGM_B=`basename $PGM`
set +e
oldTZ=$TZ; TZ=GMT; export TZ		# Solaris FTP is confused by dates
if test "$PGM_B" = wget; then
    for BURL in $BURLS; do
	URL="$BURL/$TBALL_PATH"
	print_url "$PGM_B" "$URL"
	$PGM $WGETQUIET -nd --no-host-directories --mirror --retr-symlinks \
	    --passive-ftp  "$URL"
	if test -s $DLTBALL; then
	    if test -z "`sed -n -e 2q -e 's/.*DOCTYPE.*/HTML/p' $DLTBALL`"; then
		break;
	    fi
	    # do not leave a broken file
	    rm $DLTBALL
	fi
	echo
    done
    PGM_B=
fi

if test "$PGM_B" = fetch; then
    for BURL in $BURLS; do
	URL="$BURL/$TBALL_PATH"
	HTTP_REFERER=DCC-script; export HTTP_REFERER
	print_url "$PGM_B" "$URL"
	$PGM -p -q -m "$URL"
	if test -s $DLTBALL; then
	    break;
	fi
	echo
    done
    PGM_B=
fi

if test "$PGM_B" = curl; then
    for BURL in $BURLS; do
	URL="$BURL/$TBALL_PATH"
	print_url "$PGM_B" "$URL"
	$PGM  --connect-timeout 30 --max-time 600 \
	    "$URL" -o $DLTBALL
	# --fail does not work on at least some versions of curl
	if test -s $DLTBALL; then
	    if test -z "`sed -n -e 2q -e 's/.*DOCTYPE.*/HTML/p' $DLTBALL`"; then
		break;
	    fi
	    # do not leave a broken file
	    rm $DLTBALL
	fi
	echo
    done
    PGM_B=
fi

# try FTP if it is the right choice or the right choice has not worked
if test "$PGM_B" = ftp -o ! -s $DLTBALL; then
    if test "$PGM_B" != ftp ; then
	PGM_B=ftp
	PGM=ftp
    fi
    for BURL in $BURLS; do
	URL="$BURL/$TBALL_PATH"
	print_url "$PGM_B" "$URL"
	$PGM -p "$URL"
	if test -s $DLTBALL; then
	    break;
	fi
	echo
    done
    # if that did not work, try ancient anonymous FTP
    if test ! -s $DLTBALL; then
	for URL in $BURLS; do
	    HOST=`expr "$URL" : "ftp://\([^/]*\)/"`
	    SRC=`expr "$URL" : "ftp://[^/]*/\(.*\)"`
	    if test -z "$HOST" -o -z "$SRC"; then
		continue
	    fi
	    USR=`expr "$HOST" : "\([^/:]*\):"`
	    if test -z "$USR"; then
		USR=anonymous
		PASSWD=`hostname`
	    else
		PASSWD=`expr "$HOST" : "$USR:\(.*\)@.*"`
		HOST=`expr "$HOST" : ".*@\(.*\)"`
	    fi
	    echo "try old anonymous FTP with $HOST and $SRC"
	    (echo "user $USR $PASSWD ";				\
			echo "binary";				\
			echo "get $SRC/$DLTBALL $DLTBALL")	\
		| ftp -n $HOST
	    if test -s $DLTBALL; then
		break;
	    fi
	    # some versions of ftp like to leave empty files
	    rm -f $DLTBALL
	done
    fi
    PGM_B=
fi

if test -n "$PGM_B"; then
    echo "unrecognized fetch program $PGM_B" 1>&2; exit 1
fi
if test -z "$oldTZ"; then
    unset TZ
else
    TZ=$oldTZ
fi
if test ! -s $DLTBALL; then
    echo
    echo "failed to fetch $DLTBALL" 1>&2
    if test -n "$PFILE"; then
	echo "is $PFILE correct?" 1>&2
    fi
fi
set -e

# pick the newest tarball, possibly one copied manually instead of the
#   official tarball copied by this script.
if test -z "$TBALL"; then
    TBALL=`ls -Lt dcc*.tar.Z | head -1`
fi
if test ! -s "$TBALL"; then
    echo "nothing to install" 1>&2
    exit 1
fi

NEW_DCC=`zcat "$TBALL" | tar -tf - | sed -e '2,$d' -e '1s@/.*@@'`


# Move the unpacked tarball into the build directory named dcc
#	while preserving any foreign files.
#   Empty the target build directory of old DCC source and generated files.
MNM=.manifest
if test -d dcc; then
    if test ! -f dcc/$MNM; then
	if test `find dcc -type f -print | wc -l` -gt 50; then
	# deal with old versions without .manifest files
	    echo delete $BDIR/dcc
	    rm -rf dcc
	fi
    else
	cd dcc
	set +e
	make purge >/dev/null 2>&1
	cd $BDIR
	rmdir dcc 2>/dev/null
	set -e
	if test -d dcc; then
	    find dcc -type f -print		\
		| sed -e '1s/./preserving &/' -e '2,$s/./	&/'
	    cd $BDIR
	fi
    fi
fi

echo "unpack $TBALL into $BDIR/dcc"
rm -rf $NEW_DCC
zcat $TBALL | tar -xf -

echo will configure and build $NEW_DCC
if test ! -d dcc; then
    rm -rf dcc
    mv $NEW_DCC dcc
else
    # install top directories for preserved files first
    find $NEW_DCC -name $MNM -print | LC_ALL=C sort | while read NM; do
	set +e
	DIR=`expr $NM : "$NEW_DCC/\(.*\)/$MNM"`
	set -e
	if test -z "$DIR"; then
	    DIR=.
	fi
	if test ! -d $NEW_DCC/$DIR; then
	    # we already moved this directory
	    continue
	fi
	# if we can, move the entire directory from the directory in the
	#	unpacked tarball to the corresponding build directory
	if test ! -d $BDIR/dcc/$DIR; then
	    mv $NEW_DCC/$DIR $BDIR/dcc/$DIR
	    continue
	fi
	# otherwise move individual files from the unpacked tarball directory
	cd $NEW_DCC/$DIR
	mv `cat $MNM` $BDIR/dcc/$DIR
	cd $BDIR
	done
    rm -rf $NEW_DCC
fi

CFLAGS=-O2\ -g\ -pipe\ -Wall\ -Wp,-D_FORTIFY_SOURCE=2\ -fexceptions\ -m32\ -march=i386\ -fasynchronous-unwind-tables 
export CFLAGS
if test -n "$EVARS"; then
    eval $EVALS
    export $EVARS
fi
cd $BDIR/dcc

# turn off FreeBSD blather about object directories
if test -z "$MAKEOBJDIRPREFIX"; then
    MAKEOBJDIRPREFIX=; export MAKEOBJDIRPREFIX
fi

# work around Linx/FSF Microstupid tendencies which otherwise break `sort`
#   and wreck error messages from gcc
LC_ALL=C; export LC_ALL

set -x
./configure  $CQUIET $CONFS

if test -n "$UNPACK"; then
    exit
fi

trap "$RESTART; cd $BDIR/dcc;  make purge >/dev/null 2>&1" 0 1 2 15

make $MAKE_TGT 2>&1						\
    | sed -e "$MQUIET/^[a-z0-9_]*.c: In function .*/d"			\
	-e "$MQUIET/ warning: .%.. yields only last 2 digits of year/d"	\
	-e "$MQUIET/^make.*is up to date/d"				\
	-e "$MQUIET/^make.*Nothing to be done for/d"			\
	-e "$MQUIET/^g*cc/s/-W[-a-z]*//g"				\
	-e "$MQUIET/^g*cc/s@-m[0-9a-z=]*@@g"				\
	-e "$MQUIET/^g*cc/s@-I[-a-zA-Z0-9/.]*@@g"			\
	-e "$MQUIET/^g*cc/s@[   ]\{1,\}@ @g"

# finally start the new version and switch back to the local server
eval "$RESTART"
/usr/bin/cdcc rtt >/dev/null 2>&1
