#!/bin/sh
#
#  Copyright (c) 1999 Michael Merten <mikemerten@yahoo.com>
#
#  License:  This script is distributed under the terms of version 2
#            of the GNU GPL. See the LICENSE file included with the package.
#
#  $Id: apt-move,v 3.0 1999/08/20 22:03:18 ironfoot Exp $
#
#  The apt-move(8) manpage contains the most up-to-date documentation
#     for this script.  Also, see the README file.
#
#  Configuration for this script can be found in /etc/apt-move.conf
#
if [ ! -f /etc/apt-move.conf ]; then
    echo -e "\nCould not find configuration. Aborting."
    exit 1
fi
. /etc/apt-move.conf

# Global variables - Do not change these.  Config is in /etc/apt-move.conf -
# these are the temporary files...
TMPPKG=`tempfile -p MOVE_`   # master package list
TMPOVR=`tempfile -p MOVE_`   # master override list
TMPDEL=`tempfile -p MOVE_`   # files to delete
TMPLOC=`tempfile -p MOVE_`   # local package list
TMPEXC=`tempfile -p MOVE_`   # master exclude list
TMPINS=`tempfile -p MOVE_`   # include list
TMPSRC=`tempfile -p MOVE_`   # master source package list

# these are not temporary, they have to exist so the local options will work.
LS=$LOCALDIR/.apt-move/LS       # file containing remote debian/dists ls
BLS=$LOCALDIR/.apt-move/LS.bak  # backup for ls file

# these are the current distribution names
# these are set automatically by the script
DEBSTABLE=           # the name for stable
DEBUNSTABLE=         # the name for unstable
DEBFROZEN=           # the name for frozen
DEBNAME=             # the name for the DIST you selected
#
TEST=                # test run flag (-t)
FORCE=               # force delete flag (-f)
BKGRD=               # background run flag (-b)
VERBOSE=             # verbose flag for rsync
#
GET_BINARY=          # binary distribution flag
GET_SOURCE=          # source distribution flag
# End Globals ---------------------------------------------------------------

showusage () {
    revision='$Id: apt-move,v 3.0 1999/08/20 22:03:18 ironfoot Exp $'
    # display a 'usage' message.
    cat <<- EOF

	$revision
	
	Usage:    apt-move { stop | [-bftv] OPTION... }
	
	Options:
	       get      - update your master lists from the net.
	       move     - move cache files into mirror tree.
	       delete   - delete obsolete packages and excluded files.
	       packages - Create new local Packages.gz files.
	       update   - Alias for 'get move delete packages'.
	       local    - Alias for 'move delete packages'.
	       mirror   - Update your local mirror from remote rsync site.
	       sync     - same as mirror, but only gets packages that
	                     you currently have installed on your system.
	       exclude  - prints a list of all packages EXCLUDED from the
	                     mirror by the .exclude file.  (Ignores -t)
	       stop     - stops any apt-move process running in the background
	                     (Ignores all other options)

	  -b  Execute option(s) in background with logging.
	  -f  Override the MAXDELETE setting (use with caution).
	  -t  Show what apt-move would do, but do not actually do anything.
	  -v  Show additional output from rsync(1).

	Options may be given in any order, but will be processed to remove
	duplication and rearranged to execute in a sane manner.  If stop is
	given, all other options are ignored.  See the apt-move(8) manpage 
	for further details.

	EOF
    exit 1
}

setnames () {
    # error if we don't have the LS file
    [ -f $LS ] || return 15
    # parse the directory listing returned by rsync (LS file)
    # this gets the dist names from the actual mirror links.
    DEBUNSTABLE=`grep -- " unstable ->" $LS | awk '{ print $7 }'`
    DEBFROZEN=`grep -- " frozen ->" $LS | awk '{ print $7 }'`
    DEBSTABLE=`grep -- " stable ->" $LS | awk '{ print $7 }'`
    # figure which one we're using and set DEBNAME accordingly.
    case "$DIST" in
        stable) DEBNAME=$DEBSTABLE ;;
        frozen) DEBNAME=$DEBFROZEN ;;
        unstable) DEBNAME=$DEBUNSTABLE ;;
        "$DEBUNSTABLE"|"$DEBSTABLE"|"$DEBFROZEN") DEBNAME=$DIST ;;
        *) return 7 ;;  
    esac
    return 0
}

getfiles () {
    echo -e "\nUpdating Packages and override files..."
    # make sure target directory exists.
    [ -d $LOCALDIR/.apt-move ] || install -d $LOCALDIR/.apt-move || return 5 
    # get the distribution names
    echo "Getting: distribution names"
    # get rsync list of debian/dists directory
    # since an error here will destroy the existing $LS file, (and the offline
    # functions will stop working) I'll back it up first.
    cp $LS $BLS
    rsync -nl $USSITE::debian/dists/* > $LS
    if [ -z "`cat $LS`" ]; then
        # rsync failed, restore old $LS file
        cp $BLS $LS
    fi
    # set the distribution names from that
    setnames || return $?
    # rsync the lists
    ROPTS="-t -L --timeout=180"
    if [ $VERBOSE ]; then
        ROPTS="-v -v $ROPTS"
    else
        ROPTS="-q $ROPTS"
    fi
    [ $TEST ] && ROPTS="-n $ROPTS"
    for sect in $SECTIONS; do
        # determine the rsync site to use for this section.
        if [ "`dirname $sect`" = "non-US" ]; then
            site=$NONUSSITE
            suf="-non-US"
            pre="non-us"
        else
            site=$USSITE
            suf=
            pre="us"
        fi
        bsect=`basename $sect`
        # give an error if a needed site is not configured.
        [ -z "$site" ] && return 2
        # get the section package and override file
        #
        # wrote this to handle the nonstandard slink/non-US
        # directory... will rewrite it when potato goes stable.
        #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
        if [ "$DEBNAME" = "slink" -a "$site" = "$NONUSSITE" ]; then
            case $sect in
                non-US/main)
                    pd=non-US/binary-$ARCH
                    sd=non-US/source
                    ;;
                non-US/contrib) continue ;;
                non-US/non-free) continue ;;
            esac
        else
            pd=$sect/binary-$ARCH
            sd=$sect/source
        fi
        # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        if [ $GET_BINARY ]; then 
            echo "Getting: $DIST $sect Packages.gz"
            SOURCE="$site::debian$suf/dists/$DIST/$pd/Packages.gz"
            DEST="$LOCALDIR/.apt-move/$pre.$bsect.Packages.gz"
            rsync $ROPTS $SOURCE $DEST
            [ -f $LOCALDIR/.kill ] && return 16
        fi
        if [ $GET_SOURCE ]; then 
            echo "Getting: $DIST $sect Sources.gz"
            SOURCE="$site::debian$suf/dists/$DIST/$sd/Sources.gz"
            DEST="$LOCALDIR/.apt-move/$pre.$bsect.Sources.gz"
            rsync $ROPTS $SOURCE $DEST
            [ -f $LOCALDIR/.kill ] && return 16
        fi
        #
        if [ "$bsect" = "main" ]; then
            SOURCE="$site::debian$suf/indices$suf/override.$DEBNAME.gz"
        else
            SOURCE="$site::debian$suf/indices$suf/override.$DEBNAME.$bsect.gz"
        fi
        DEST="$LOCALDIR/.apt-move/$pre.$bsect.override.gz"
        echo "Getting: $DIST $sect override.gz"
        rsync $ROPTS $SOURCE $DEST
        [ -f $LOCALDIR/.kill ] && return 16
    done
    return 0
}

makelist () {
    echo -e "\nCreating Lists..."
    # return an error if we're killing the script manually
    [ -f $LOCALDIR/.kill ] && return 16
    # make sure we have a master set of files to work with
    [ -z "`ls $LOCALDIR/.apt-move/*.override.gz 2>/dev/null`" ] && return 8
    [ $GET_BINARY ] && \
        [ -z "`ls $LOCALDIR/.apt-move/*.Packages.gz 2>/dev/null`" ] && return 14
    [ $GET_SOURCE ] && \
        [ -z "`ls $LOCALDIR/.apt-move/*.Sources.gz 2>/dev/null`" ] && return 17
    # check on our dist name
    setnames || return $?
    # make the override file
    zcat $LOCALDIR/.apt-move/*.override.gz > $TMPOVR
    # if your mirror follows the actual dist name, we have to convert
    # it in the master packages file
    if [ "$DIST" = "$DEBNAME" ]; then
        [ $GET_BINARY ] && zcat $LOCALDIR/.apt-move/*.Packages.gz \
            | awk '/^Filename\:/ { print $2 }' \
            | sed -e "s/\/\(unstable\|frozen\|stable\)\//\/$DIST\//g" > $TMPPKG 
        [ $GET_SOURCE ] && zcat $LOCALDIR/.apt-move/*.Sources.gz \
            | awk '/^Directory\:/ { path=$2 }; /^[ ]./ { print path "/" $3 }' \
            | sed -e "s/\/\(unstable\|frozen\|stable\)\//\/$DIST\//g" > $TMPSRC
    else 
        [ $GET_BINARY ] && zcat $LOCALDIR/.apt-move/*.Packages.gz \
            | awk '/^Filename\:/ { print $2 }' > $TMPPKG 
        [ $GET_SOURCE ] && zcat $LOCALDIR/.apt-move/*.Sources.gz \
            | awk '/^Directory\:/ { path=$2 }; /^[ ]./ { print path "/" $3 }' \
            > $TMPSRC
    fi
    # create temporary exclude file from .exclude modified to
    # work with grep (remove comment lines and strip the '*'
    # characters from the patterns)  rsync allows using '#' or
    # ';' at the beginning of # a line to indicate comments.
    if [ -f $LOCALDIR/.exclude ]; then
        grep -v '^[#;]' $LOCALDIR/.exclude | sed -e 's/\*//g' > $TMPEXC
    fi
    return 0
}

domove () {
    # well, atleast we can skip this one for the source packages...
    [ -z "`ls $FILECACHE/*.deb 2> /dev/null`" ] && return 0
    echo -e "\nFixing mangled package names..."
    [ $TEST ] || dpkg-name -a $FILECACHE/*.deb
    echo -e "\nMoving Packages..."
    for path in $FILECACHE/*.deb; do
        [ -f $LOCALDIR/.kill ] && return 16
        # dpkg-name has fixed everything but the epochs, so I still have
        # to remove them to match the file names in the packages file.
        # (the leading / prevents partial matches)
        pname=/`basename $path | sed -e "s/_[0-9]\+\:/_/g"`
        # locate name in the packages file
        newpath=`grep $pname $TMPPKG`
        if [ -n "$newpath" ]; then
            # move the file
            if [ $TEST ]; then
                echo "Move:      $pname"
                continue
            fi
            if install -d `dirname $LOCALDIR/$newpath` ;then
                if install -m 0444 $path $LOCALDIR/$newpath; then
                    rm -f $path
                    echo "Moved:     $pname"
                else
                    echo "Error:     $pname"
                fi
            else
                return 5
            fi
        else
            echo "Skipping:  $pname"
        fi
    done
    return 0
}

dodeletes () {
    if [ "$DELETE" != "yes" ]; then
        echo -e "\nFile deletes disabled, skipping."
        return 0
    fi
    # return an error if we're killing the script manually
    [ -f $LOCALDIR/.kill ] && return 16
    # change to $LOCALDIR... all deletes done from there because the
    # paths stored in the packages files are relative to debian/
    cd $LOCALDIR
    echo -e "\nRemoving obsolete packages..."
    # list all .deb files in the mirror
    if [ $GET_BINARY ]; then
        nice find dists/$DIST -name "*.deb" -print > $TMPLOC 
        for file in `cat $TMPLOC`; do
            [ -f $LOCALDIR/.kill ] && return 16
            if [ -z "`grep $file $TMPPKG`" ]; then
                echo $file >> $TMPDEL
            fi
        done
    fi
    loccount=`grep -c ".*" $TMPLOC`
    if [ $GET_SOURCE ]; then
        nice find dists/$DIST -regex ".*\(\(diff\|tar\)\.gz\|\.dsc\)" -print \
            > $TMPLOC
        for file in `cat $TMPLOC`; do
            [ -f $LOCALDIR/.kill ] && return 16
            if [ -z "`grep $file $TMPSRC`" ]; then
                echo $file >> $TMPDEL
            fi
        done
    fi
    loccount=$(($loccount+`grep -c ".*" $TMPLOC`))
    if [ -f $LOCALDIR/.exclude ]; then
        # delete excluded files (done here to take care of .exclude
        # additions, and also because the rsync --delete-excluded option
        # doesn't work) ** don't care about $MAXDELETE here **
        echo "(Exclude file found... removing excluded files also.)"
        # note: the exclude patterns will match both binary and source
        nice find dists/$DIST -type f -print | grep -v Packages > $TMPLOC
        # can reset locount here, since it will now include all files
        loccount=`grep -c ".*" $TMPLOC`
        cat $TMPLOC | grep -f $TMPEXC >> $TMPDEL
        sort -u -o $TMPDEL $TMPDEL
        [ -f $LOCALDIR/.kill ] && return 16
    fi
    # I do this just because a bug caused there to be a total of 0 files
    # in the distribution, and bc had a heart-attack.
    [ $loccount -eq 0 ] && return 0
    delcount=`grep -c ".*" $TMPDEL`
    # check the results
    case `echo "scale=2; (($delcount/$loccount)*100) <= $MAXDELETE" | bc` in
        0) [ -z "$FORCE" ] && return 13
            echo -e "\nToo many files, but FORCE used... deleting anyway!"
            ;;
        1) ;;
        *) return 12 ;;
    esac
    # we are either ok, or forced...
    for path in `cat $TMPDEL`; do
        echo "removing:  $path"
        [ $TEST ] || rm -f $path
    done
    return 0
}

excluded () {
    # print list of excluded files
    # return an error if we're killing the script manually
    [ -f $LOCALDIR/.kill ] && return 16
    echo "The following files are EXCLUDED from the mirror:"
    # if a $LOCALDIR/.exclude file exists, also find the files that
    # match one of the exclude patterns in that file.
    if [ -f $LOCALDIR/.exclude ]; then
        [ $GET_BINARY ] && cat $TMPPKG | grep -f $TMPEXC >> $TMPDEL
        [ $GET_SOURCE ] && cat $TMPSRC | grep -f $TMPEXC >> $TMPDEL
        sort -u -o $TMPDEL $TMPDEL
    fi
    cat $TMPDEL
    return 0
}

dopackages () {
    echo -e "\nCreating Packages.gz files..." 
    # build our own local Packages.gz files
    # paths stored in packages files are relative to debian/
    cd $LOCALDIR
    for sect in $SECTIONS; do
        # return an error if we're killing the script manually
        [ -f $LOCALDIR/.kill ] && return 16
        # added the following for slink non-US necessary due to non-
        # standard directory structure on the mirror site.
        # will need to be rewritten when potato goes stable.
        #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
        if [ "$DEBNAME" = "slink" -a "`dirname $sect`" = "non-US" ]; then
            case $sect in
                non-US/main)
                    pd=dists/$DIST/non-US/binary-$ARCH
                    sd=dists/$DIST/non-US/source
                    ;;
                non-US/contrib) continue ;;
                non-US/non-free) continue ;;
            esac
        else
            pd=dists/$DIST/$sect/binary-$ARCH
            sd=dists/$DIST/$sect/source
        fi
        #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        [ $GET_BINARY ] && [ -d $pd ] || install -d $LOCALDIR/$pd || return 5
        [ $GET_SOURCE ] && [ -d $sd ] || install -d $LOCALDIR/$sd || return 5
        if [ $GET_BINARY ]; then
            echo "Building: $DIST $sect Packages.gz"
            [ $TEST ] || nice dpkg-scanpackages $pd $TMPOVR > $pd/Packages
            [ $TEST ] || gzip -f $pd/Packages
        fi
        # return an error if we're killing the script manually
        [ -f $LOCALDIR/.kill ] && return 16
        if [ $GET_SOURCE ]; then
            echo "Building: $DIST $sect Sources.gz"
            [ $TEST ] || nice dpkg-scansources $sd $TMPOVR > $sd/Sources
            [ $TEST ] || gzip -f $sd/Sources
        fi
    done
    return 0
}

runmirror () {
    # grab copy of all non-excluded files for the configured distribution.
    echo -e "\nUpdating mirror..."
    # run mirror for $DIST (by section)
    ROPTS="-v -t -r -L --temp-dir=/var/tmp --partial --timeout=180"
    [ $VERBOSE ] && ROPTS="-v $ROPTS"
    [ $TEST ] && ROPTS="-n $ROPTS"
    for sect in $SECTIONS; do
        # return an error if we're killing the script manually
        [ -f $LOCALDIR/.kill ] && return 16
        # determine the rsync site to use for this section.
        if [ "`dirname $sect`" = "non-US" ]; then
            site=$NONUSSITE
            suf="-non-US"
        else
            site=$USSITE
            suf=
        fi
        # give an error if a needed site is not configured.
        [ -z "$site" ] && return 2
        # rsync the files
        # wrote the following for stable/non-US due to 
        # non-standard directory structure on the mirror sites
        # it will have to be rewritten when potato goes stable
        #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
        if [ "$DEBNAME" = "slink" -a "$site" = "$NONUSSITE" ]; then
            case $sect in
                non-US/main)
                    pd=/non-US/binary-$ARCH
                    sd=/non-US/source
                    ;;
                non-US/contrib) continue ;;
                non-US/non-free) continue ;;
            esac
        else
            pd=$sect/binary-$ARCH
            sd=$sect/source
        fi
        #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        if [ $GET_BINARY ]; then
            SOURCE="$site::debian$suf/dists/$DIST/$pd/"
            DEST=$LOCALDIR/dists/$DIST/$pd
            [ -d $DEST ] || install -d $DEST || return 5
            echo "Getting: $DIST $pd"
            if [ -f $LOCALDIR/.exclude ]; then
                rsync $ROPTS --exclude-from=$LOCALDIR/.exclude $SOURCE $DEST
            else
                rsync $ROPTS $SOURCE $DEST
            fi
        fi
        # return an error if we're killing the script manually
        [ -f $LOCALDIR/.kill ] && return 16
        if [ $GET_SOURCE ]; then
            SOURCE="$site::debian$suf/dists/$DIST/$sd/"
            DEST=$LOCALDIR/dists/$DIST/$sd
            [ -d $DEST ] || install -d $DEST || return 5
            echo "Getting: $DIST $sd"
            if [ -f $LOCALDIR/.exclude ]; then
                rsync $ROPTS --exclude-from=$LOCALDIR/.exclude $SOURCE $DEST
            else
                rsync $ROPTS $SOURCE $DEST
            fi
        fi
        # return an error if we're killing the script manually
        [ -f $LOCALDIR/.kill ] && return 16
    done
    return 0
}

runsync () {
    # grab copy of all the packages you currently have installed
    echo -e "\nSyncing mirror..."
    # run mirror for $DIST for US and NONUS (if configured)
    ROPTS="-t -v -r -L --temp-dir=/var/tmp --partial --timeout=180"
    [ $VERBOSE ] && ROPTS="-v $ROPTS"
    [ $TEST ] && ROPTS="-n $ROPTS"
    # compile a list of packages installed on your system
    dpkg --get-selections | awk '{ print "**/"$1"_*" }' > $TMPINS
    # return an error if we're killing the script manually
    [ -f $LOCALDIR/.kill ] && return 16
    # rsync the files
    for sect in $SECTIONS; do
        #
        if [ "`dirname $sect`" = "non-US" ]; then
            site=$NONUSSITE 
            suf="-non-US"
        else
            site=$USSITE
            suf=
        fi
        [ -z "$site" ] && return 2
        # this is for slink/non-US.. it will have to be rewritten
        # when potato goes stable.
        if [ "$DEBNAME" = "slink" -a "$site" = "$NONUSSITE" ]; then
            case sect in
                non-US/main)
                    pd="/non-US/binary-$ARCH"
                    sd="/non-US/source"
                    ;;
                non-US/contrib) continue ;;
                non-US/non-free) continue ;;
            esac
        else
            pd="$sect/binary-$ARCH"
            sd="$sect/source"
        fi
        #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        if [ $GET_BINARY ]; then
            SOURCE="$site::debian$suf/dists/$DIST/$pd/"
            DEST="$LOCALDIR/dists/$DIST/$pd"
            echo "Getting: $DIST $pd"
            [ -d $DEST ] || install -d $DEST || return 5
            if [ -f $LOCALDIR/.exclude ]; then
                rsync $ROPTS --include "*/" --exclude-from=$LOCALDIR/.exclude \
                    --include-from=$TMPINS --exclude "*" $SOURCE $DEST
            else
                rsync $ROPTS --include "*/" --include-from=$TMPINS \
                    --exclude "*" $SOURCE $DEST
            fi
        fi
        # return an error if we're killing the script manually
        [ -f $LOCALDIR/.kill ] && return 16
        if [ $GET_SOURCE ]; then
            SOURCE="$site::debian$suf/dists/$DIST/$sd/"
            DEST="$LOCALDIR/dists/$DIST/$sd"
            echo "Getting: $DIST $sd"
            [ -d $DEST ] || install -d $DEST || return 5
            if [ -f $LOCALDIR/.exclude ]; then
                rsync $ROPTS --include "*/" --exclude-from=$LOCALDIR/.exclude \
                    --include-from=$TMPINS --exclude "*" $SOURCE $DEST
            else
                rsync $ROPTS --include "*/" --include-from=$TMPINS \
                    --exclude "*" $SOURCE $DEST
            fi
        fi
        # return an error if we're killing the script manually
        [ -f $LOCALDIR/.kill ] && return 16
    done 
    return 0
}

printerr () {
    # print error message and exit with appropriate status
    case "$2" in
        1)  # this is used by the 'usage' function... should get none of
            # these here.
            ;;
	2)  echo "Error: $1: You must configure a non-US mirror site if "
	    echo "       you include non-US sections.  Check the"
	    echo "       SECTIONS and NONUSSITE settings in"
	    echo "       /etc/apt-move.conf."
	    echo "       Your current settings are:"
	    echo "             NONUSSITE=$NONUSSITE"
	    echo "             SECTIONS=$SECTIONS"
	    echo "       Aborting script."
	    ;;
	3)  echo "Error: $1: You specified an invalid mirror section.  Check"
	    echo "       the SECTIONS setting in /etc/apt-move.conf."
	    echo "       Your current settings are:"
	    echo "             SECTIONS=$SECTIONS"
	    echo "       Aborting script."
	    ;;
	4)  echo "Error: $1: You must specify a USSITE in /etc/apt-move.conf."
	    ;;
	5)  echo "Error: $1: Could not create directory.  Aborting script." ;;
	6)  echo "Error: $1: You failed to select a distribution.  Check the"
	    echo "       DIST setting in /etc/apt-move.conf. Aborting script."
	    ;;
	7)  echo "Error: $1: The name you configured for DIST does not exist"
	    echo "       on the mirror site.  Aborting script."
	    echo "       Aborting script."
	    ;;
	8)  echo "Error: $1: No master override files exist!" ;;
        12) echo "Error: $1: bc calculation returned invalid result" ;;
        13) echo "Error: $1: too many files to delete!  Your current limit"
            echo "       is set to $MAXDELETE%.  To change that, see the"
            echo "       MAXDELETE setting in /etc/apt-move.conf.  You can"
            echo "       override this safety using the 'force' parameter,"
            echo "       but be careful!  Aborting script."
            ;;
        14) echo "Error: $1: No master Package files exist!" ;;
        15) echo "Error: $1: No master ls file exists!" ;;
        16) echo "This run was stopped with the 'stop' command."
            echo "All Done."
	    ;;
	17) echo "Error: $1: No master Source files exist!" ;;
	18) echo "Error: $1: You specified an invalid package type."
	    echo "       See the PKGTYPE setting in /etc/apt-move.conf."
	    echo "       Your current setting is:"
	    echo "           PKGTYPE=$PKGTYPE"
	    echo "       Aborting script."
	    ;;
    esac
    exit $2
}

killback () {
  	# stop the background apt-move process by killing any running rsync,
  	# touch a file .kill in the mirror root which will cause
  	# the mirror script to abort.
  	touch $LOCALDIR/.kill
  	killall -q rsync
  	exit 0
}

getout () {
    # called when one of the main functions returns an error.
    # clean up temp files
    rm -f $TMPPKG $TMPOVR $TMPLOC $TMPDEL $TMPEXC $TMPINS $TMPSRC $LOCALDIR/.kill
    # display the appropriate message
    # $1 should be the function name, and $2 should be the error code
    printerr $1 $2
}

# START main program logic -----------------------------------------------

# read the options
while getopts ":bftv" flag; do
    case $flag in
        b) BKGRD=yes ;;
        t) TEST=yes ;;
        f) FORCE=yes ;;
        v) VERBOSE=yes ;;
        *) showusage ;;
    esac
done
shift $(($OPTIND-1))
# if -b (BKGRD), then we basically need to reexecute the command line
# in the background with logging enabled, and exit.
if [ $BKGRD ]; then
    # start building the command
    cmd="apt-move"
    # add the switches
    sw=
    [ $FORCE ] && sw=f
    [ $TEST ] && sw=${sw}t
    [ $sw ] && sw="-"$sw
    cmd="$cmd $sw $@"
    # Check $LOGFILE
    if [ -n "$LOGFILE" ]; then
        # make the $LOGFILE directory if it doesn't exist
        path=`dirname $LOGFILE`
        [ -d $path ] || install -d $path || exit 5
    else
        # no logfile specified, dump the output
        LOGFILE=/dev/null
    fi    
    # check $MONITOR
    if [ -n "$MONITOR" ]; then
        # make the $MONITOR directory if it doesn't exist
        path=`dirname $MONITOR`
        [ -d $path ] || install -d $path || exit 5
    else
        # no monitor specified, dump the output
        MONITOR=/dev/null
    fi    
    # start entry in log file
    sepline="\n-----------------------------------------------------------"
    dateline="\napt-move: `date` options: $@"
    echo -e $sepline 2>&1 | tee -a $LOGFILE >> $MONITOR
    echo -e $dateline 2>&1 | tee -a $LOGFILE >> $MONITOR
    # rerun this script in the background
    $cmd 2>&1 | tee -a $LOGFILE >> $MONITOR &
    exit 0
fi
# check $DIST
[ -z "$DIST" ] && getout "apt-move" "6"
# check $PKGTYPE
case "$PKGTYPE" in
    binary) GET_BINARY=yes;;
    source) GET_SOURCE=yes;;
    both) GET_BINARY=yes ; GET_SOURCE=yes ;;
    *) getout "apt-move" "18"
esac
# check $SECTIONS
for sect in $SECTIONS; do
    case $sect in
        main|contrib|non-free|non-US/main|non-US/contrib|non-US/non-free) ;;
        *) getout "apt-move" "3";;
    esac
done
# check the USSITE (it's not optional)
[ -z "$USSITE" ] && getout "apt-move" "4"
# if nothing on command line, 
[ -z "$1" ] && showusage

# build a list of options to run (and make sure they're valid)
# also, put them in a sensible order, and remove duplicate options
# we have 4 basic functions, and 4 combo functions, and a couple
# of special options.
# If we find a basic function, put them in 1-4 (get move delete packages)
# If we find a combo function, put them in 5-8 (mirror sync update local)
# if exclude, execute excluded() and exit
# if stop, execute killback() function and exit.
O1= ; O2= ; O3= ; O4= ; O5= ; O6= ; O7= ; O8=  ; O9=
while [ "$1" ]; do
    case "$1" in
        get) O1=$1 ;;
        move) O2=$1 ;;
        delete) O3=$1 ;;
        packages) O4=$1 ;;
        mirror) O5=$1 ;;
        sync) O6=$1 ;;
        update) O7=$1 ;;
        local) O8=$1 ;;
        exclude) O9=$1 ;;
        stop) killback ;;
        *) showusage ;;
    esac
    shift
done
#
# now, remove overlap between options
if [ -n "$O9" ]; then
    # just print the excluded list and exit
    opstring="exclude"
elif [ -n "$O5" ]; then
    # mirror runs everything
    opstring="mirror"
elif [ -n "$O6" ]; then
    # sync runs everything, 
    # except it doesn't get all the files that mirror does
    opstring="sync"
elif [ -n "$O7" ]; then
    # update runs everything,
    # but doesn't retrieve any mirror files
    opstring="update"
elif [ -n "$O8" ]; then
    # local doesn't do get, so will allow 'get local'
    # It doesn't make sense, but somebody will probably try it.
    opstring="$O1 local"
else
    # run the basic options in proper order
    opstring="$O1 $O2 $O3 $O4"
fi

for opt in $opstring; do
    # Put together the basic functions for each option
    case "$opt" in
        get) FUNCT="getfiles";;
        move) FUNCT="makelist domove";;
        delete) FUNCT="makelist dodeletes";;
        packages) FUNCT="makelist dopackages";;
        update) FUNCT="getfiles makelist domove dodeletes dopackages" ;;
        local) FUNCT="makelist domove dodeletes dopackages";;
        mirror) FUNCT="getfiles makelist domove dodeletes runmirror dopackages";;
        sync) FUNCT="getfiles makelist domove dodeletes runsync dopackages";;
        exclude) FUNCT="makelist excluded";;
    esac
    # do them
    for funct in $FUNCT; do
        $funct || getout "$funct" "$?"
    done
done
#
# normal exit
for path in `nice find . -type d -depth -print`; do
    if [ -z "`ls $path 2>/dev/null`" ]; then
        [ $TEST ] || rmdir $path
    fi
done
# clean up temp files
rm -f $TMPPKG $TMPOVR $TMPLOC $TMPDEL $TMPEXC $TMPINS $TMPSRC $LOCALDIR/.kill
# done (I think)
echo -e "\nAll done, exiting." 
exit 0
