#! /bin/bash

function drop_shell () {
	while true; do
		/bin/sh
	done
}

function abort_install () {
	echo 'INSTALLATION FAILED, PLEASE REMOVE THE CD AND REBOOT'
	while true; do
		sleep 3600
	done
}

function find_plugged_in_dev () {
	local dev start_rx_pkts end_rx_pkts numpkts gateway
	gateway="$2"

	while true; do
		for dev in $1; do
			# Bring up the device
			ifconfig "${dev}" up >/dev/null 2>/dev/null

			# Look for a simple "Link detected"
			if ethtool "${dev}" | grep 'Link detected: yes' >/dev/null 2>/dev/null; then
				echo "${dev}"
				return
			fi

			# ARPPING the default gateway if one is specified
			if test -n "${gateway}"; then
				if ! arping -c 2 -D -I "${dev}" "${gateway}" >/dev/null 2>/dev/null; then
					echo "${dev}"
					return
				fi
			fi
		done
	done
}

PATH="/bin:/sbin"
export PATH

(
	while true; do
		/bin/sh >/dev/tty2 2>/dev/tty2 </dev/tty2
	done
) &

mount -n -t proc proc /proc
mount -n -t tmpfs tmpfs /tmp

# Give the user the chance to abort this
echo "Welcome to the Joe Everyone Remote Sensor Installation."
echo ""
echo "*** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***"
echo "*** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***"
echo "*** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***"
echo ""
echo "THIS TOOL WILL *PERMANENTLY* *DELETE* EVERYTHING ON THIS SYSTEM"
echo ""
echo "*** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***"
echo "*** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***"
echo "*** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***"
echo ""
echo -n "Are you sure you want to proceed (N/y) ? "
read YESNO
## Only respond to a lowercase "y", otherwise abort the whole thing
if test "${YESNO}" = "shell"; then
	drop_shell
fi
if test "${YESNO}" != "y"; then
	exit
fi

# Step 1: Locate the local CD-ROM
echo -n "  * Looking for a CD-ROM drive ..."
mkdir /tmp/mnt
mkdir /tmp/mnt/cdrom
for dev in /dev/hd{c,d,b,a} /dev/sd{a,b,c,d,e,f}; do
	mount -n -t iso9660 "${dev}" /tmp/mnt/cdrom >/dev/null 2>/dev/null || continue
	if test -f "/tmp/mnt/cdrom/installfs.tgz"; then
		echo "${dev}" > /tmp/install-cd
		break
	fi
	umount /tmp/mnt/cdrom
done
if test ! -f /tmp/install-cd; then
	echo ' NOT FOUND!'
	abort_install
fi
SRCDEV="$(cat /tmp/install-cd)"
echo " found."
echo "  * Installing from ${SRCDEV} ..."

# Step 2: Locate an installable hard-disk
echo -n "  * Looking for a hard disk to install onto ..."
grep '^ *[0-9]* [0-9]* .*[a-z]$' /proc/partitions | while read major minor size dev; do
	# Only install onto a SCSI or IDE hard disk
	if test "${major}" != "8" -a "${major}" != "3" -a "${major}" != "22"; then
		continue
	fi

	echo "${dev}|($[${size} / 1024]_MB)"
done > /tmp/install-hds

## Step 2.a: Determine the number of hard-disks found
##           If only one is found, use it
NUMHDS=$(wc -l /tmp/install-hds | awk '{ print $1 }')
if test "${NUMHDS}" = "0"; then
	echo " NOT FOUND!"
	abort_install
elif test "${NUMHDS}" = "1"; then
	DESTDEV="/dev/$(cat /tmp/install-hds | cut -f 1 -d '|')"
	echo " found."
else
	## Step 2.b: If more than one found, get the user to select one.
	echo " found more than one..."
	IFS="|"
	select dev in $(sed 's@|@ - @g;s@_@ @g' /tmp/install-hds | tr "\n" '|'); do
		if test -z "${dev}"; then
			echo "Invalid selection, try again."
			continue
		fi
		unset IFS
		DESTDEV="/dev/$(echo "${dev}" | sed 's@ - .*$@@')"
		break
	done
	unset IFS
fi
if test -z "${DESTDEV}"; then
	echo "ERROR: Unable to find a device to install onto!"
	abort_install
fi

# Minimum disk size is 512MB
DESTDEVDISKSIZE="$(sfdisk -s "${DESTDEV}" 2>/dev/null)"
if test "${DESTDEVDISKSIZE}" -lt 524288; then 
	echo "ERROR: Disk is too small!"
	abort_install
fi
echo "  * Installing onto ${DESTDEV} ..."

# Step 3: Find and configure NICs
## Step 3.a: Read user configuration data
echo -n 'IP address (dhcp) ? '
read IPADDR
if test -z "${IPADDR}"; then
	IPADDR="dhcp"
fi

### If not DHCP, ask for additional parameters.
if test "${IPADDR}" != "dhcp"; then
	echo -n 'Netmask (255.255.255.0) ? '
	read NETMASK
	if test -z "${NETMASK}"; then
		NETMASK="255.255.255.0"
	fi

	GATEWAY_DEFAULT="$(echo "${IPADDR}" | cut -f 1-3 -d .).1"
	echo -n "Gateway (${GATEWAY_DEFAULT}) ? "
	read GATEWAY
	if test -z "${GATEWAY}"; then
		GATEWAY="${GATEWAY_DEFAULT}"
	fi

	NAMESERVER_DEFAULT="10.0.130.34"
	echo -n "Domain name server (${NAMESERVER_DEFAULT}) ? "
	read NAMESERVER
	if test -z "${NAMESERVER}"; then
		NAMESERVER="${NAMESERVER_DEFAULT}"
	fi
fi

## Step 3.b: Coorelate the physical cards with their devices
### Step 3.b.i: Make sure the user has unplugged all NICs
echo "Please unplug all network cards from the network"
for time in {2,1,0}{9,8,7,6,5,4,3,2,1,0}; do
	echo -en "Waiting $time\\r"
	sleep 1
done
echo 'Done                 '

### Step 3.b.ii: Find the Management NIC
ip -o link show | grep '^[0-9]*: eth' | sed 's@^[0-9]*: \(eth[0-9]*\):.*link/ether \([0-9A-Fa-f:]*\) .*$@\1|\2@' > /tmp/install-nics
NUMNICS=$(wc -l /tmp/install-nics | awk '{ print $1 }')
if test "${NUMNICS}" -lt "2"; then
	echo "ERROR: Need atleast 2 network cards, only found ${NUMNICS}..."
	cat /tmp/install-nics
	abort_install
fi
ETHDEVS=$(cat /tmp/install-nics | cut -f 1 -d '|')
echo -n "Please plug the MANAGEMENT network card into the network ..."
MGMTDEV=$(find_plugged_in_dev "${ETHDEVS}" "${GATEWAY}")
echo " found (${MGMTDEV})"

### Step 3.b.iii: Find the Sniffer NIC
NUMNICS=$[${NUMNICS} - 1]
ETHDEVS=$(cat /tmp/install-nics | cut -f 1 -d '|' | grep -v "^${MGMTDEV}$")
if test "${NUMNICS}" -eq "1"; then
	SNIFFERDEV=${ETHDEVS}
else
	echo -n "Please plug the SNIFFER/MIRROR/MONITOR/SPAN network card into the network ..."
	SNIFFERDEV=$(find_plugged_in_dev "${ETHDEVS}")
	echo " found (${SNIFFERDEV})"
fi

## Step 3.c: Convert devices into MAC addresses
MGMTMAC="$(grep "^${MGMTDEV}|" /tmp/install-nics | cut -f 2 -d '|')"
SNIFFERMAC="$(grep "^${SNIFFERDEV}|" /tmp/install-nics | cut -f 2 -d '|')"

# *-* End of User Interaction *-*
# Step 4: Partition disk
echo -n 'Creating partitions ...'
## Step 4.a:
## First, completely erase the first 2M of disk to ensure that no extraneous
## bootloader/OS code can be a problem.
dd if=/dev/zero of="${DESTDEV}" bs=1024 count=2048 >/dev/null 2>/dev/null

## Step 4.b: Create an MS-DOS bootlabel
echo wq | fdisk "${DESTDEV}" >/dev/null 2>/dev/null

## Step 4.c: Create the new partition table
sfdisk -uM "${DESTDEV}" << __EOF__ >/dev/null 2>/dev/null
0,15,83,*
,128,82
,,83
;
__EOF__
echo ' done.'

# Step 5: Install
## Step 5.a: Create swap space
echo -n 'Enabling swap space ...'
mkswap "${DESTDEV}2" >/dev/null 2>/dev/null || abort_install
swapon "${DESTDEV}2" >/dev/null 2>/dev/null || abort_install
echo ' done.'

## Step 5.b: Create filesystem
echo -n 'Creating filesystem ...'
mke2fs "${DESTDEV}1" >/dev/null 2>/dev/null || abort_install
mke2fs -j "${DESTDEV}3" >/dev/null 2>/dev/null || abort_install
echo ' done.'

## Step 5.c: Mount filesystem onto target
mkdir /tmp/mnt/target
mount -t ext3 "${DESTDEV}3" /tmp/mnt/target || abort_install
mkdir /tmp/mnt/target/boot
mount -t ext2 "${DESTDEV}1" /tmp/mnt/target/boot || abort_install

## Step 5.d: Install files onto target filesystem
echo -n 'Installing ...'
cd /tmp/mnt/target
gzip -dc /tmp/mnt/cdrom/installfs.tgz | tar -xf - >/dev/null 2>/dev/null || abort_install
yes n | cp -ai /dev/* /tmp/mnt/target/dev/ >/dev/null 2>/dev/null
mkdir -p /tmp/mnt/target/boot/extlinux/
cp /tmp/mnt/cdrom/boot/isolinux/message.txt /tmp/mnt/target/boot/extlinux/
chown -R 0:0 /tmp/mnt/target
cd /
echo ' done.'

# Step 6: Install Bootloader
## Step 6.a: Prepare
echo -n 'Installing bootloader ...'
mkdir -p /tmp/mnt/target/proc
mount -n -t proc proc /tmp/mnt/target/proc

## Step 6.b: Create configuration file
mkdir -p /tmp/mnt/target/boot/extlinux
cat <<__EOF__ > /tmp/mnt/target/boot/extlinux/extlinux.conf
default JESNIFFER
prompt 1
allowoptions 0
timeout 50
display message.txt
label JESNIFFER
  kernel /bzImage
  append root=${DESTDEV}3 quiet ro
label DEBUG
  kernel /bzImage
  append root=${DESTDEV}3 ro
__EOF__

## Step 6.c: Install Bootloader
extlinux --install /tmp/mnt/target/boot/extlinux/ >/dev/null 2>/dev/null || \
extlinux /tmp/mnt/target/boot/extlinux/ >/dev/null 2>/dev/null || abort_install

## Step 6.d: Install Master Boot Record Loader
dd if=/sbin/mbr.bin of="${DESTDEV}" >/dev/null 2>/dev/null

## Step 6.e: Cleanup
umount -n /tmp/mnt/target/proc
echo ' done.'

# Step 7: Post-install
## Step 7.a: fstab
echo "${DESTDEV}2        swap             swap        defaults         0   0" > /tmp/mnt/target/etc/fstab
echo "${DESTDEV}3        /                ext3        defaults         1   1" >> /tmp/mnt/target/etc/fstab
echo "${DESTDEV}1        /boot            ext2        defaults,ro      2   2" >> /tmp/mnt/target/etc/fstab
echo "${SRCDEV}         /mnt/cdrom       auto        noauto,ro        0   0" >> /tmp/mnt/target/etc/fstab
echo "tmpfs              /tmp             tmpfs       defaults         0   0" >> /tmp/mnt/target/etc/fstab
echo "procfs             /proc            proc        defaults         0   0" >> /tmp/mnt/target/etc/fstab
echo "devpts             /dev/pts         devpts      gid=5,mode=620   0   0" >> /tmp/mnt/target/etc/fstab

## Step 7.b: iftab/udev rule
echo "eth0 mac ${MGMTMAC}" > /tmp/mnt/target/etc/iftab
echo "mon0 mac ${SNIFFERMAC}" >> /tmp/mnt/target/etc/iftab
echo "SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"?*\", ATTR{address}==\"${MGMTMAC}\", ATTR{type}==\"1\", KERNEL==\"eth*\", NAME=\"eth0\"" > /tmp/mnt/target/etc/udev/rules.d/70-persistent-net.rules
echo "SUBSYSTEM==\"net\", ACTION==\"add\", DRIVERS==\"?*\", ATTR{address}==\"${SNIFFERMAC}\", ATTR{type}==\"1\", KERNEL==\"eth*\", NAME=\"mon0\"" >> /tmp/mnt/target/etc/udev/rules.d/70-persistent-net.rules

## Step 7.c: hostname
NEWHOSTNAME="jesensor-$(echo ${MGMTMAC} | sed 's/://g')"
echo "${NEWHOSTNAME}.security.example.com" > /tmp/mnt/target/etc/HOSTNAME
sed "s@darkstar\.example\.net darkstar@${NEWHOSTNAME}.security.example.com ${NEWHOSTNAME}@" /tmp/mnt/target/etc/hosts > /tmp/hosts
cat /tmp/hosts > /tmp/mnt/target/etc/hosts

## Step 7.d: random-seed
gen-random /tmp/mnt/target/etc/random-seed

## Step 7.e: rc.inet1.conf
if test "${IPADDR}" = "dhcp"; then
	cat << __EOF__ > /tmp/mnt/target/etc/rc.d/rc.inet1.conf
IPADDR[0]=""
NETMASK[0]=""
USE_DHCP[0]="yes"
DHCP_HOSTNAME[0]=""
GATEWAY=""
DEBUG_ETH_UP="no"
__EOF__
else
	cat << __EOF__ > /tmp/mnt/target/etc/rc.d/rc.inet1.conf
IPADDR[0]="${IPADDR}"
NETMASK[0]="${NETMASK}"
USE_DHCP[0]="no"
DHCP_HOSTNAME[0]=""
GATEWAY="${GATEWAY}"
DEBUG_ETH_UP="no"
__EOF__

	## Step 7.f: Configure DNS
	cat << __EOF__ > /tmp/mnt/target/etc/resolv.conf
# Note: If you change this you will also need to restart the firewall
#    /etc/rc.d/rc.firewall stop
#    /etc/rc.d/rc.firewall start

search example.com
nameserver ${NAMESERVER}
__EOF__
fi

## Step 7.g: Disable unneeded services
chmod -x /tmp/mnt/target/etc/rc.d/rc.mysqld /tmp/mnt/target/etc/rc.d/rc.wireless /tmp/mnt/target/etc/rc.d/rc.saslauthd

# Step 8: Reboot
umount -n /tmp/mnt/target/boot
umount -n /tmp/mnt/target
umount -n /tmp/mnt/cdrom
eject "${SRCDEV}" >/dev/null 2>/dev/null
reboot

drop_shell
