#!/bin/bash
#
# This script will attempt to add "/boot/win4lin" and 
# "/boot/System.map-win4lin" to the system bootloader
# with an entry that closely matches the first one in the file 
# It will exit with a non-zero status if it cannot figure out how.
#
# $Id$

if [ "_$1" = "_-r" ]
then
  restore=1
else
  restore=0
fi
# pass in the name of the initrd if needed 
if [ "_$1" != "_" ]
then
  initrd=$1
fi

# get rdev path or a default
rdev=`which rdev 2>/dev/null || echo /usr/sbin/rdev`

# these lines are used to delimit changes in the boot files. Don't 
# change them without adding detection for these lines in the new script
# for uninstall
addstart="# added by NeTraverse - DO NOT REMOVE THIS LINE, it's used for uninstall"
addend="# end added by NeTraverse - DO NOT REMOVE THIS LINE, it's used for uninstall"

# boot loader config file default locations
liloloc=/etc/lilo.conf
grubloc=/boot/grub/menu.lst

# used to hold error numbers
ERROR=0

if [ ! -r /boot/win4lin ]
then
    echo "There is no win4lin kernel in /boot!"
    exit 100
fi

# relink the /boot/System.map file to be win4lin's system map
FixSystemMap() {
    if [ -e /boot/System.map.win4lin ];
    then
	# save original
	mv -f /boot/System.map /boot/System.map.pre-win4lin
	ln -s /boot/System.map.win4lin /boot/System.map
    else
	echo "Warning: no /boot/System.map.win4lin found"
    fi
}

# relink the /boot/System.map file to be the original one
RestoreSystemMap() {
    if [ -L /boot/System.map ];
    then
	rm /boot/System.map
    else
	echo "Warning: no /boot/System.map link found"
    fi
    if [ -e /boot/System.map.pre-win4lin ];
    then
	mv -f /boot/System.map.pre-win4lin /boot/System.map
    else
	echo "Warning: no /boot/System.map.pre-win4lin found"
    fi
}

# restore a lilo config to a pre-win4lin state (save any changes since)
RestoreLilo() {
    grep "$addstart" ${liloloc} >/dev/null 2>&1
    if [ $? != 0 ]
    then
	echo "No old lilo configuration exists, check ${liloloc} manually"
	ERROR=4
	return $ERROR
    fi
    mv -f ${liloloc} ${liloloc}.win4lin.old
    echo "default=linux" >${liloloc}
    cat ${liloloc}.win4lin.old | sed -e"/$addstart/,/$addend/d" >>${liloloc}
    rm -f ${liloloc}.win4lin.old  ${liloloc}.win4lin
    RestoreSystemMap
    # Run lilo to restore original system
    /sbin/lilo
    return $?
}

# Add win4lin entry to a lilo config and make it the default
FixLilo() {
    if [ -r ${liloloc}.win4lin ]
    then
	echo "an old ${liloloc}.win4lin exists, bailing out!"
	ERROR=4
	return $ERROR
    fi
    cp ${liloloc} ${liloloc}.win4lin
    # remove the default line if it's there
    grep -v 'default=' ${liloloc}             > ${liloloc}.new
    echo "$addstart"                         >> ${liloloc}.new
    echo "image = /boot/win4lin"             >> ${liloloc}.new
    echo "	label = win4lin"             >> ${liloloc}.new
    grep "append *=" ${liloloc}|head -1      >> ${liloloc}.new
    grep "[ 	]vga *=" ${liloloc}| head -1 >> ${liloloc}.new
    if [ "_$initrd" = "_" ]
    then
      grep "initrd" ${liloloc}| head -1      >> ${liloloc}.new
    else
      echo "	initrd=$initrd"              >> ${liloloc}.new
    fi
    RDEV=`$rdev |cut -d' ' -f1`
    echo "	root=$RDEV"                  >> ${liloloc}.new
    echo "	read-only"                   >> ${liloloc}.new
    echo "$addend"                           >> ${liloloc}.new

    echo "$addstart"             >${liloloc}
    echo "default=win4lin"      >>${liloloc}
    echo "$addend"              >>${liloloc}
    cat ${liloloc}.new          >>${liloloc}
    rm ${liloloc}.new
    #run lilo
    /sbin/lilo
    ERROR=$?
    if [ "_$ERROR" != "_0" ]
    then
	echo "lilo failed!"
	echo -n "removing changes..."
	mv -f ${liloloc} ${liloloc}.failed 
	mv -f ${liloloc}.win4lin ${liloloc}
	echo "done."
	echo "saved failed lilo config in ${liloloc}.failed"
    else
	FixSystemMap
	echo "lilo has been updated."
    fi
}

# restore a grub config to a pre-win4lin state (save any changes since)
RestoreGrub() {
    grep "$addstart" ${grubloc} >/dev/null 2>&1
    if [ $? != 0 ]
    then
	echo "No old grub configuration exists, check ${grubloc} manually"
	ERROR=4
	return $ERROR
    fi
    mv -f ${grubloc} ${grubloc}.win4lin.old
    cat ${grubloc}.win4lin.old | sed -e"/$addstart/,/$addend/d" >${grubloc}
    rm -f ${grubloc}.win4lin.old  ${grubloc}.win4lin
    RestoreSystemMap
}

# Add win4lin entry to a config and make it the default
FixGrub() {
    if [ -r ${grubloc}.win4lin ]
    then
	echo "an old ${grubloc}.win4lin exists, bailing out!"
	ERROR=4
	return $ERROR
    fi
    cp ${grubloc} ${grubloc}.win4lin
    entries=`grep '^title' ${grubloc}|wc -l`
    entry=$(( $entries + 0 ))
    oldroot=`grep '^ *root' ${grubloc}|head -1`
    oldkernel=`grep '^[ 	]*kernel' ${grubloc}|head -1`
    if [ "_$initrd" = "_" ]
    then
    oldinitrd=`grep '^[ 	]*initrd' ${grubloc}|head -1`
    else
      oldinitrd=`grep '^[ 	]*initrd' ${grubloc}|head -1|sed -e's:/[^ ]* :$initrd :'`
    fi
    oldinitrd=`grep '^[ 	]*initrd' ${grubloc}|head -1`
    newkernel=`echo $oldkernel|sed -e's:/boot/[^ ]* :/boot/win4lin :'`
    if [ "_$newkernel" = "_" ]
    then
	newkernel=`echo $oldkernel|sed -e's:/[^ ]* :/win4lin :'`
	if [ "_$newkernel" = "_" ]
	then
	    echo "Unable to parse ${grubloc}"
	    ERROR=5
	    return $ERROR
	fi
    fi

    rm ${grubloc}
    echo "$addstart"                      >  ${grubloc}
    echo "default $entry"                 >> ${grubloc}
    echo "$addend"                        >> ${grubloc}
    grep -v '^default' ${grubloc}.win4lin >> ${grubloc}
    echo " "                              >> ${grubloc}
    echo "$addstart"                      >> ${grubloc}
    echo "title Win4Lin"                  >> ${grubloc}
    if [ "_$oldroot" != "_" ]
    then
        echo "$oldroot"                   >> ${grubloc}
    fi
    echo "$newkernel"                     >> ${grubloc}
    echo "$oldinitrd"                     >> ${grubloc}
    echo "$addend"                        >> ${grubloc}
    FixSystemMap
    echo "grub has been updated."
}


# check for lilo
if [ -r ${liloloc} ]
then
  if [ -w ${liloloc} ]
  then
    if [ $restore = 1 ]
    then
	RestoreLilo
    else
	FixLilo
    fi
  else
    echo "lilo.conf is not writable."
    ERROR=1
  fi
else
  # check for grub
  if [ -r ${grubloc} ]
  then
    if [ -w ${grubloc} ]
    then
	if [ $restore = 1 ]
	then
	    RestoreGrub
	else
	    FixGrub
	fi
    else
	echo "${grubloc} is not writable."
	ERROR=2
    fi
  else
    echo "Unknown boot loader. Please update your bootloader to have"
    echo "an entry for /boot/win4lin with the same options as your"
    echo "default kernel"
    ERROR=3
  fi
fi

if [ "_$ERROR" != "_0" ]
then
    exit $ERROR
fi


if [ $restore = 1 ]
then
    echo "Bootloader config restored"
else
    echo "In order to run win4lin..."
    echo "You must first reboot the system."
    echo ""
    echo "      Please remove bootable CD-ROM's "
    echo "      and Floppies before you reboot "
    echo ""
fi

exit 0
