#!/bin/bash
#
# This is a script to bootstrap `packager' onto an existing Linux system.
# To run, it requires the following programs to be installed:
#    - bash
#    - chmod
#    - gzip
#    - ls
#    - mkdir
#    - perl (version 5 or later) and h2ph
#    - tar (GNU tar)
#    - tcsh
#    - touch
#    - everything else packager requires (FIXME) EXCEPT make and patch
#
# This script performs the following operations:
#     1. Creates /pkg, /pkg/base, /pkg/base/.version, and the /pkg/packager
#           hierarchy.  If /pkg already exists, the script aborts.
#     2. Creates /usr/local/save to hold copies of all files that will be
#           overwritten, and copies those files/directories (see the file
#           "bootstrap.files").  Also, for files in /bin, /sbin, /usr/bin,
#           and /usr/sbin, copies any file not in the standard location (as
#           listed in "bootstrap.files") to /usr/local/save and moves the
#           original to its standard location.
#     3. Runs `h2ph' on system includes
#           (/usr/include{,/{sys,bits,linux,asm}}/*.h).
#     4. Removes all existing source files (files with names of the form
#           "<package>-[0-9]*.tar.gz") for the following packages (unless
#           the "-n" option is given):
#           bash, bin86, binutils, bison, bzip2, coreutils, findutils,
#           gawk, gcc, gettext, glibc, grep, gzip, m4, make, ncurses,
#           patch, perl, procps, sash, sed, shadow, sysvinit, tar, tcsh,
#           texinfo, util-linux, zlib
#     5. Downloads (using `packager d') the packages listed in step 5.
#           This is the only point at which an Internet connection is
#           necessary.
#     6. Installs precompiled versions of the make and patch programs,
#           needed by `packager' itself.
#     7. Installs the binutils package (recent versions of GCC do not
#           compile with old versions of binutils), then installs the C
#           compiler part of the gcc package.
#     8. Installs the m4 (needed for bison), bison (needed for texinfo),
#           texinfo (needed for glibc), and zlib (needed for sash)
#           packages, in that order.
#     9. Installs the sash package (a StandAlone SHell with common commands
#           built in, in case something goes wrong when installing glibc).
#    10. Installs the glibc package.
#    11. Reinstalls everything installed in steps 6 through 9, to link
#           against the new libc.  (The only difference in order is that
#           gcc is installed before binutils rather than after; also, the
#           C++ compiler is installed alongside the C compiler.)
#    12. Reinstalls the make and patch packages from source code.
#    13. Installs the ncurses (required for less) and less (required for
#           perl) packages, then installs the perl package itself.
#    14. Installs gettext and readline, which are used by packages below.
#    15. Installs the remaining packages, in alphabetical order:
#           bash, bin86, bzip2, coreutils, findutils, gawk, grep, gzip,
#           procps, sed, shadow, sysvinit, tar, tcsh, util-linux
#
# If given the "-n" option, this script will not remove already-existing
# source tarballs before checking for and downloading new ones.
#
# If given the "-s" option, this script will do all package installs with
# the "-s" option passed to `packager', which will cause all installed
# libraries to be stripped (and thus undebuggable).
#
# If given a numeric command-line argument, skips directly to that step.

###########################################################################

set -e
PATH=/usr/bin:/usr/sbin:/bin:/sbin
ORIGDIR=`pwd`
OPT_N=
OPT_S=
START=0
export OPT_N OPT_S
while test `echo "x$1" | cut -c1-2` = x- ; do
    opt=`echo "x$1" | cut -c3`
    if [ "x$opt" = "xn" ] ; then
	OPT_N=1
    elif [ "x$opt" = "xs" ] ; then
	OPT_S=-s
    else
	if [ "x$opt" != "xh" ] ; then
	    echo >&2 "Unrecognized option -$opt"
	fi
	echo >&2 Usage: $0 [-n] [-s] [starting-step-number]
	exit 1
    fi
    shift
done
if [ "x$1" != "x" ] ; then
    START=$1
fi
if ! test "$START" -ge 0 || test "$START" -gt 15 ; then
    echo >&2 "Bad starting step number: "\`"$START'"
    exit 1
fi

if [ $START -le 0 ] ; then
    if [ -e /pkg ] ; then
	echo "/pkg exists, aborting."
	exit 1
    elif [ -e /usr/local/save ] ; then
	echo "/usr/local/save exists, aborting."
	exit 1
    fi
fi

if [ $START -le 1 ] ; then
    echo "******** STEP 1: Create /pkg tree ********"
    mkdir /pkg /pkg/base
    touch /pkg/base/.version
    chmod a+rX /pkg
    tar Cxzfp /pkg `pwd`/bootstrap.tar.gz
fi

if [ $START -le 2 ] ; then
    echo "******** STEP 2: Back up old files to /usr/local/save ********"
    mkdir /usr/local/save
    chmod 755 /usr/local/save
    LIST=
    export LIST
    for i in `cat bootstrap.files` ; do
	if [ -f $i ] ; then
	    LIST="$LIST $i"
	fi
    done
    # FIXME: bug in tar causes hardlinked files to not be copied
    (tar cf - $LIST | tar Cxvfp /usr/local/save -) || true
    for i in `egrep '^/(|usr/)(|s)bin/[^/]*$' bootstrap.files` ; do
	d=`dirname "$i"`
	f=`basename "$i"`
	if test -h "$i" ; then
	    echo rm -f \""$i"\"
	    rm -f "$i"
	fi
	for j in /bin /sbin /usr/bin /usr/sbin ; do
	    if test $j != $d && test -f "$j/$f" && ! grep -q \^"$j/$f"\$ bootstrap.files ; then
		echo cp -af \""$j/$f"\" \""/usr/local/save$j/$f"\"
		cp -af "$j/$f" "/usr/local/save$j/$f"
		echo mv -f \""$j/$f"\" \""$i"\"
		mv -f "$j/$f" "$i"
	    fi
	done
    done
fi

if [ $START -le 3 ] ; then
    echo "******** STEP 3: Run h2ph ********"
    cd /usr/include
    h2ph *.h
    h2ph sys/*.h
    h2ph bits/*.h
    for i in linux/*.h ; do h2ph "$i" ; done
    for i in asm/*.h ; do h2ph "$i" ; done
fi

if [ $START -le 4 ] ; then
    echo "******** STEP 4: Remove old source tarballs ********"
    if [ "$OPT_N" ] ; then
	echo "*** Skipping this step because -n was specified."
    else
	mkdir -p /usr/local/save/usr/src
	for i in bash bin86 binutils bison bzip2 coreutils findutils gawk gcc gettext glibc grep gzip less m4 make ncurses patch perl procps readline sash sed shadow sysvinit tar tcsh texinfo util-linux zlib ; do
	    for j in /usr/src/$i-[0-9]*.tar.gz ; do
		if test -f "$j" ; then
		    mv -f "$j" /usr/local/save/usr/src/
		fi
	    done
	done
    fi
fi

if [ $START -le 5 ] ; then
    echo "******** STEP 5: Download packages ********"
    rm -rf /usr/sbin/packager
    ln -s /pkg/packager/sbin/packager /usr/sbin/packager
    mkdir -p /usr/src
    packager -a d bash bin86 binutils bison bzip2 coreutils findutils gawk gcc gettext glibc grep gzip less m4 make ncurses patch perl procps readline sash sed shadow sysvinit tar tcsh texinfo util-linux zlib
fi

if [ $START -le 6 ] ; then
    echo "******** STEP 6: Install precompiled make and patch ********"
    cp -pf "$ORIGDIR/make" /usr/bin/
    cp -pf "$ORIGDIR/patch" /usr/bin/
fi

if [ $START -le 7 ] ; then
    echo "******** STEP 7: Install binutils and minimal gcc ********"
    DID_MKDIR=
    DID_TOUCH=
    if [ ! -d /pkg/gcc ] ; then
	mkdir /pkg/gcc
	DID_MKDIR=y
    fi
    if [ ! -f /pkg/gcc/.version ] ; then
	touch /pkg/gcc/.version
	DID_TOUCH=y
    fi
    packager $OPT_S -a i binutils
    if [ "$DID_TOUCH" ] ; then
	rm -f /pkg/gcc/.version
    fi
    if [ "$DID_MKDIR" ] ; then
	rmdir /pkg/gcc
    fi
    if [ "$DID_TOUCH" ] ; then
	# If we didn't touch .version, it means GCC was already installed
	packager $OPT_S -a -ominimal i gcc
    fi
fi

if [ $START -le 8 ] ; then
    echo "******** STEP 8: Install m4, bison, texinfo, and zlib ********"
    packager $OPT_S -a i m4 bison texinfo zlib
fi

if [ $START -le 9 ] ; then
    echo "******** STEP 9: Install sash ********"
    packager $OPT_S -a i sash
fi

if [ $START -le 10 ] ; then
    echo "******** STEP 10: Install glibc ********"
    packager $OPT_S -a i glibc
fi

if [ $START -le 11 ] ; then
    echo "******** STEP 11: Reinstall gcc, binutils, etc. ********"
    packager $OPT_S -a r gcc binutils m4 bison texinfo zlib sash
fi

if [ $START -le 12 ] ; then
    echo "******** STEP 12: Install make and patch from source ********"
    packager $OPT_S -a i make patch
fi

if [ $START -le 13 ] ; then
    echo "******** STEP 13: Install ncurses, less, and perl ********"
    packager $OPT_S -a i ncurses less perl
fi

if [ $START -le 14 ] ; then
    echo "******** STEP 14: Install gettext and readilne ********"
    packager $OPT_S -a i gettext readline
fi

if [ $START -le 15 ] ; then
    echo "******** STEP 15: Install everything else ********"
    packager $OPT_S -a i bash bin86 bzip2 coreutils findutils gawk grep gzip procps sed shadow sysvinit tar tcsh util-linux
fi

echo "******** Finished. ********"
