#!/bin/ash
#
# disklessrc file for initrd (Initial Ram Disk) 
#
# Copyright (C) 2003 Daniel Walsh <dwalsh@redhat.com>
#
# Taken in part from James A. McQuillan <jam@McQuil.Com> linuxrc for LTSP
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#
PCITABLE="/usr/share/hwdata/pcitable"
MODULE=""
PCICLASS="0200 0280"
#
# This function is used to load the ETHERNET module
#
loadmodules() {
    for MODULE in $1; do { 
        echo -n "Loading $MODULE module... "
        if ! `grep "^$MODULE" /proc/modules > /dev/null`; then
            modprobe $MODULE && echo "" 
        else
            echo "module already loaded" 
        fi
    } done
}

#
# This function is used to find the correct ETHERNET module
#
findhardware() {
    for CLASSNUM in $1; do
    {
        CARDLIST=""
        PCIID=""
        MODULE=""

        CARDLIST=`lspci -n | grep "Class $CLASSNUM"` &&
        PCIID=`echo $CARDLIST | cut -d ' ' -f 4 | sed -e 's/:/	0x/'` && 
        echo -n "Looking for hardware... " &&
        MODULE=`cat $PCITABLE | grep "0x$PCIID" | cut -d'"' -f2 | sed -e 's/\"//g'`  &&
        if [ -z $MODULE  ]; then
                return 13;
        else
#            echo "found suggestion ($MODULE)"
	    return
        fi
    } done
}

#
# This function is used to mount files/directories from the snapshot directory 
#  over the root directory.
#
mountfile () {
    snapshotfile=/.snapshot/${2}${1}
    dir=`dirname $snapshotfile`
#
#  Check if file already exists in snapshot directory.  If not attempt to copy
#    from root directory to snapshot directory.
#
    if [ ! -e $snapshotfile ]; then
	mkdir -p $dir
	echo "${1} missing from client specific area."
	if [ -e ${1} ] ; then 
	    echo "Copying ${1}"
	    rsync -a ${1} $dir
	else 
	    echo "Creating ${1}"
	    touch $snapshotfile
	fi
    else
#  If dev directory already exists in snapshot directory, check if the root 
#   /dev directory is newer.  If it is rsync the root directory over the 
#   snapshot directory.
	if [ ${1} == "/dev" -a ${1} -nt ${dir}/dev ]; then
	    rsync -a ${1} $dir
	fi
    fi
#
#  Mount the snapshotfile over the root file so the client will have r/w access
#
    mount -n -o bind /.snapshot/${2}${1} ${1} 
}

echo "==============================================================================="
echo "Running /disklessrc"

echo "Mounting /proc"
/bin/mount -n -t proc /proc /proc

if [ "${INITRD_DBG}" = "1" ]; then exec /bin/ash; fi
if [ -w /proc/progress ]; then echo 40 "Detecting network card" >/proc/progress; fi
if [ -z "${ETHERNET}" ]; then export ETHERNET="eth0"; fi
#
#  Attempt to find and load the network card module
#
findhardware "$PCICLASS" 
loadmodules $MODULE 
#
#  load the NFS module
#
loadmodules nfs

echo "Mounting /"
mount -n -o remount,rw /
/bin/mount -n -t tmpfs /dev/shm /tmp

if [ "${INITRD_DBG}" = "2" ]; then exec /bin/ash; fi

#
#  Setup dhclient to retrieve IP address
#
cat <<EOF >/tmp/dhclient.conf
interface "$ETHERNET" {
    request subnet-mask,
            broadcast-address,
            routers,
            domain-name,
            domain-name-servers,
            host-name, 
            root-path;
}
EOF

#
# dhclient runs as a daemon.  Once it acquires the info from the
# server, it runs a script called /sbin/dhclient-script.  That script
# will take care of configuring the interface.
#
if [ "${INITRD_DBG}" = "3" ]; then exec /bin/ash; fi
if [ -w /proc/progress ]; then echo 50 "Sending DHCP request" >/proc/progress; fi

echo "Running dhclient"
/bin/dhclient -cf /tmp/dhclient.conf -pf /tmp/dhclient.pid $ETHERNET >/tmp/dhclient.out 2>&1
if [ $? -ne 0 ]; then
    exec /bin/ash
    if [ -w /proc/progress ]; then echo f >/proc/progress; fi
    echo
    cat /tmp/dhclient.out
    echo
    echo "ERROR! dhclient failed!"
    echo
    exit 1
fi

#
# Mount the NFS root-path from the diskless server
#
if [ "${INITRD_DBG}" = "4" ]; then exec /bin/ash; fi
if [ -z "${NFSROOT}" ]; then
    if [ -w /proc/progress ]; then echo f >/proc/progress; fi
    echo
    echo "ERROR!  No root-path.  Check your DHCP configuration, to make"
    echo "        sure that the 'option root-path' is specified"
    echo
    exit 1
fi

NFS_IP=` echo ${NFSROOT} | cut -d : -f 1`
NFS_DIR=`echo ${NFSROOT} | cut -d : -f 2`

if [ -w /proc/progress ]; then echo 55 "Mounting root filesystem" >/proc/progress; fi
echo "Mounting root filesystem: ${NFS_DIR} from: ${NFS_IP}"
mount -n -o nolock,ro ${NFS_IP}:${NFS_DIR}/root /mnt

if [ $? -ne 0 ]; then
    if [ -w /proc/progress ]; then echo f >/proc/progress; fi
    echo
    echo "ERROR!  Failed to mount the root directory via NFS!"
    echo "        Possible reasons include:"
    echo
    echo "        1) NFS services may not be running on the server"
    echo "        2) Workstation IP does not map to a hostname, either"
    echo "           in /etc/hosts, or in DNS"
    echo "        3) Wrong address for NFS server in the DHCP config file"
    echo "        4) Wrong pathname for root directory in the DHCP config file"
    echo
    exit 1
fi

#
# Now that the NFS root partition has been mounted do a pivot_root to switch
# the memory resident root with the NFS one.
#
if [ "${INITRD_DBG}" = "5" ]; then exec /bin/ash; fi
if [ -w /proc/progress ]; then echo 60 "Pivoting root" >/proc/progress; fi

umount /proc
echo "Doing the pivot_root"
cd /mnt
/sbin/pivot_root . .oldroot
cd /
mount -n -t proc /proc /proc

#
#  Mount the snapshot directory from the server and then mount files 
#  in the snapshot/files file over the the shared ones
#
IP=`/sbin/ifconfig $ETHERNET|grep inet|cut -f 2 -d ':'|cut -f 1 -d ' '`

#
# Setup the hostname for the diskless client. 
#
hostname `host $IP | cut -f 5 -d ' '` 2> /dev/null

if [ -z "${SNAPSHOT}" ]; then
SNAPSHOT=`hostname`
fi

if [ "${INITRD_DBG}" = "6" ]; then exec /bin/ash; fi
echo Mounting Snapshot directories
mount $NFS_IP:${NFS_DIR}/snapshot /.snapshot -o nolock &&
{
    for i in `grep -v "^#" /.snapshot/files`; do 
	mountfile $i ${SNAPSHOT}
    done
    if [ -e /.snapshot/files.custom ]; then
	for i in `grep -v "^#" /.snapshot/files.custom`; do 
	    mountfile $i ${SNAPSHOT}
	done
    fi
    RELEASE=`uname -r`
    for i in `ls /lib/modules/$RELEASE/modules.*`; do
	mountfile $i $SNAPSHOTNAME
    done
    /sbin/ifup lo
}

#if [ "${INITRD_DBG}" = "7" ]; then exec /bin/ash; fi
#echo "Mounting the devfs filesystem"
#mount -n -t devfs /devfs /dev


#
# Complete the network boot by killing the dhcp client.
# Umount file systems that are no longer used.
# Start the init process to run the NFS Roots bootup sequence.
#
if [ "${INITRD_DBG}" = "8" ]; then exec /bin/ash; fi
/bin/kill -TERM `cat /.oldroot/tmp/dhclient.pid`
echo "Running /sbin/init"
umount /proc
umount /.oldroot/tmp

exec /sbin/init --init
