#!/bin/sh
# Stephen.n.turner@gmail.com 2015
# All works released under public domain license "unlicense"
# where applicable. License details at http://unlicense.org

#To use, run this script in a sub folder such as /home/testing
#This script will create the folder structure and download sources
#needed to build a chroot environment. Obviously internet access is
#assumed and a GCC equivelent Development environment capable of
#compiling static binaries. Tested on Debian linux.

udhcpc

# Halt at first error
set -e

# Get Root working directory
RWD=$PWD

# Create the folder structure in a generic widely supported way
# Hopefully a easier way is found that is widely acceptable
mkdir -pv code/downloads
mkdir -pv targetfs/bin
mkdir -pv targetfs/boot
mkdir -pv targetfs/home
mkdir -pv targetfs/mnt
mkdir -pv targetfs/proc
mkdir -pv targetfs/root
mkdir -pv targetfs/sbin
mkdir -pv targetfs/dev
mkdir -pv targetfs/tmp
mkdir -pv targetfs/sys
mkdir -pv targetfs/etc/init.d
mkdir -pv targetfs/etc/network
mkdir -pv targetfs/usr/lib
mkdir -pv targetfs/usr/bin
mkdir -pv targetfs/var/run
mkdir -pv targetfs/usr/sbin
mkdir -pv targetfs/usr/share/udhcpc
ln -s /usr/lib targetfs/lib
chmod 0750 targetfs/root
chmod 1777 targetfs/tmp

wget -P ./code/downloads/ http://ftp.barfooze.de/pub/sabotage/tarballs/kernel-headers-3.12.6-5.tar.xz --no-check-certificate
wget -P ./code/downloads/ ftp://ftp.gnu.org/gnu/binutils/binutils-2.24.tar.gz --no-check-certificate
wget -P ./code/downloads/ http://www.linuxfromscratch.org/patches/downloads/binutils/binutils-2.24-configure_ash-1.patch --no-check-certificate
wget -P ./code/downloads/ ftp://ftp.gnu.org/gnu/make/make-4.0.tar.gz --no-check-certificate
wget -P ./code/downloads/ ftp://invisible-island.net/byacc/byacc-20141128.tgz --no-check-certificate
wget -P ./code/downloads/ http://sourceforge.net/projects/flex/files/flex-2.5.39.tar.gz --no-check-certificate
wget -P ./code/downloads/ http://www.musl-libc.org/releases/musl-1.1.8.tar.gz --no-check-certificate
wget -P ./code/downloads/ http://haddonthethird.net/m4/m4-2.tar.bz2 --no-check-certificate
wget -P ./code/downloads/ ftp://pcc.ludd.ltu.se/pub/pcc-libs/pcc-libs-$(date +%Y%m%d).tgz --no-check-certificate
wget -P ./code/downloads/ ftp://pcc.ludd.ltu.se/pub/pcc/pcc-$(date +%Y%m%d).tgz --no-check-certificate

# Unpack code from downloads to code directory
echo "tar -xf linux-*.tar.*"
tar -xf code/downloads/kernel-headers-*.tar.* -C code/

echo "tar -xf binutils-*.tar.*"
tar -xf code/downloads/binutils-*.tar.* -C code/

echo "tar -xf make-*.tar.*"
tar -xf code/downloads/make-*.tar.* -C code/

echo "tar -xf byacc*.tar.*"
tar -xf code/downloads/byacc*.tgz -C code/

echo "tar -xf flex-*.tar.*"
tar -xf code/downloads/flex-*.tar.* -C code/

echo "tar -xf musl-*.tar.*"
tar -xf code/downloads/musl-*.tar.* -C code/

echo "tar -xf m4-*.tar.*"
tar -xf code/downloads/m4-*.tar.* -C code/

echo "tar -xf pcc-libs"
tar -xf code/downloads/pcc-libs-*.tgz -C code/

echo "tar -xf pcc"
tar -xf code/downloads/pcc-????????.tgz -C code/

# Patch binutils to compile without bash
cd code/binutils-2.24
patch -Np1 -i ../downloads/binutils-2.24-configure_ash-1.patch
cd ../../

# Download Busybox-i686 bin
wget -P ./targetfs/bin/ http://busybox.net/downloads/binaries/latest/busybox-i686 --no-check-certificate
chmod +x ./targetfs/bin/busybox-i686

# Create links for busybox
echo "creating busybox links"
cd targetfs
for i in $(bin/busybox-i686 --list-full)
do
ln -s /bin/busybox-i686 $i
done
cd ../
echo "downloads completed"

# Make and install headers
cd $RWD/code/kernel-headers-*
make ARCH=i386 prefix=/usr DESTDIR=$RWD/targetfs install

# Set common compile variables
export CFLAGS="-march=i486"
#export MAKEFLAGS=-j

# Detect compiler specifics
if command -v pcc >/dev/null 2>&1; then
export CC="pcc -O2 -fno-stack-protector"
else
export CFLAGS="$CFLAGS --static -O2"
export LDFLAGS=-static
fi

# Make and install musl-libc
cd $RWD/code/musl-*
./configure --prefix=/usr --target=i486-linux-musl --disable-gcc-wrapper && make
make DESTDIR=$RWD/targetfs/ install

# Ensure musl link is present
ln -s /usr/lib/libc.so $RWD/targetfs/usr/lib/ld-musl-i386.so.1

# Create ldd link
ln -s /usr/lib/libc.so $RWD/targetfs/bin/ldd

# Make and install make
cd $RWD/code/make-*
./configure --prefix=/usr && make
make DESTDIR=$RWD/targetfs/ install

# Make byacc
cd $RWD/code/byacc-*
./configure --prefix=/usr && make
make DESTDIR=$RWD/targetfs/ install

# Make Binutils
cd $RWD/code/binutils-2.24
./configure --disable-werror --prefix=/usr && make
make DESTDIR=$RWD/targetfs install

# Make flex
cd $RWD/code/flex-*
./configure --prefix=/usr && make
make DESTDIR=$RWD/targetfs install

# Build M4
cd $RWD/code/m4*
sed -i 's/local//g' Makefile
#./configure --prefix=/usr && make
make && make DESTDIR=/$RWD/targetfs/ install

# Make pcc
cd $RWD/code/pcc-????????
./configure --enable-native --target=i486-linux-musl --prefix=/usr && make
make DESTDIR=$RWD/targetfs install

# Make pcc-libs
cd $RWD/code/pcc-libs-*
./configure --prefix=/usr && make
make DESTDIR=$RWD/targetfs/ install

# fix pcc libs
mv $RWD/targetfs/usr/lib/pcc/*-gnu*/1.2.0.DEVEL/* $RWD/targetfs/usr/lib/pcc/i486-*/1.2.0.DEVEL/

# make init initramfs compatible
ln -s /bin/busybox-i686 $RWD/targetfs/init

#------------
# create rcS
#------------
cat <<'eof' > $RWD/targetfs/etc/init.d/rcS
#!/bin/sh
# Start all scripts in /etc/init.d

for i in /etc/init.d/S??* ;do
   # Ignore dangling symlinks
   [ ! -f "$i" ] && continue

   # Start Subprocess
   $i start
done
eof

chmod +x $RWD/targetfs/etc/init.d/rcS

#------------------------
# Create Network Service
#------------------------
cat <<'eof' > $RWD/targetfs/etc/init.d/S40Network
#!/bin/sh

# Start Network Service

case "$1" in
  start)
    echo "Starting network..."
    /sbin/ifup -a
    ;;
  stop)
    echo -n "Stopping Network..."
    /sbin/ifdown -a
    ;;
  restart|reload)
    "$0" stop
    "$0" start
    ;;
  *)
    echo $"Usage: $0 {start|stop|restart}"
    exit 1
esac
exit $?
eof

chmod +x $RWD/targetfs/etc/init.d/S40Network

#----------------------------------
# Create needed empty script files
#----------------------------------
touch $RWD/targetfs/etc/network/if-up.d
touch $RWD/targetfs/etc/network/if-pre-up.d
touch $RWD/targetfs/etc/network/if-down.d
touch $RWD/targetfs/etc/network/if-post-down.d
touch $RWD/targetfs/var/run/ifstate
touch $RWD/targetfs/etc/resolv.conf


#--------
# S10Filesystem
#--------
cat <<'eof' > $RWD/targetfs/etc/init.d/S10Env
#!/bin/sh
mount -t tmpfs -o size=64k,mode=0755 tmpfs /dev
mkdir /dev/pts
mount -t devpts devpts /dev/pts
mount -t proc proc /proc
mount -t sysfs sysfs /sys
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
eof

chmod +x $RWD/targetfs/etc/init.d/S10Env

#--------
# S20Env
#--------
cat <<'eof' > $RWD/targetfs/etc/init.d/S20Env
#!/bin/sh
export CC=pcc
#export LDFLAGS=-static
export PATH=/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin
eof
chmod +x $RWD/targetfs/etc/init.d/S20Env

#-----------------
# Create Hostfile
#-----------------
cat <<'eof' > $RWD/targetfs/etc/hosts
127.0.0.1	localhost.localdomain	localhost
eof


#-------------------
# Create interfaces
#-------------------
cat <<'eof' > $RWD/targetfs/etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
eof

#----------------
# create inittab
#----------------
cat <<'eof' > $RWD/targetfs/etc/inittab
::sysinit:/etc/init.d/rcS
tty1::askfirst:/bin/ash
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
tty2::askfirst:/bin/ash
tty3::askfirst:/bin/ash
eof

#-----------------------------
# Create udhcpc script/config
#-----------------------------
cat <<'eof' > $RWD/targetfs/usr/share/udhcpc/default.script
#!/bin/sh

# udhcpc script edited by Tim Riker <Tim@Rikers.org>

[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1

RESOLV_CONF="/etc/resolv.conf"
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
[ -n "$subnet" ] && NETMASK="netmask $subnet"

case "$1" in
	deconfig)
		grep -q -v ip= /proc/cmdline
		if [ $? -eq 0 ]; then
			/sbin/ifconfig $interface up
		fi
		grep -q -v nfsroot= /proc/cmdline
		if [ $? -eq 0 ]; then
			/sbin/ifconfig $interface 0.0.0.0
		fi
		if [ -x /usr/sbin/avahi-autoipd ]; then
			/usr/sbin/avahi-autoipd -k $interface
		fi
		;;

	leasefail|nak)
		if [ -x /usr/sbin/avahi-autoipd ]; then
			/usr/sbin/avahi-autoipd -wD $interface --no-chroot
		fi
		;;

	renew|bound)
		if [ -x /usr/sbin/avahi-autoipd ]; then
			/usr/sbin/avahi-autoipd -k $interface
		fi
		/sbin/ifconfig $interface $ip $BROADCAST $NETMASK

		if [ -n "$router" ] ; then
			echo "deleting routers"
			while route del default gw 0.0.0.0 dev $interface ; do
				:
			done

			for i in $router ; do
				route add default gw $i dev $interface
			done
		fi

		echo -n > $RESOLV_CONF
		[ -n "$domain" ] && echo search $domain >> $RESOLV_CONF
		for i in $dns ; do
			echo adding dns $i
			echo nameserver $i >> $RESOLV_CONF
		done
		;;
esac

exit 0
eof
chmod +x $RWD/targetfs/usr/share/udhcpc/default.script

# Automate Boot image creation
mkdir -p $RWD/targetfs/absentos/code/
cp /absentos/code/bootstrap.sh $RWD/targetfs/absentos/code/

# Chroot and rebuild
chroot $RWD/targetfs/ /absentos/code/bootstrap.sh

echo " Bootstrap complete"
