#!/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: win4lin-fix-bootloader,v 1.8 2002/10/29 05:49:37 rwb Exp $

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

# get root device
RDEV=`$rdev |cut -d' ' -f1`; export 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
grubloc1=/boot/grub/grub.conf # this overrides 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
	SYSTEM_MAP=/boot/System.map
	if [ ! -f ${SYSTEM_MAP} -a ! -L ${SYSTEM_MAP} ]
	then
	    RELEASE="`uname -r`"
	    ALT_SYSTEM_MAP=${SYSTEM_MAP}-${RELEASE}
	    if [ -f ${ALT_SYSTEM_MAP} -o -L ${ALT_SYSTEM_MAP} ]
	    then
	    	SYSTEM_MAP=$ALT_SYSTEM_MAP
	    fi
	fi
	mv -f ${SYSTEM_MAP} ${SYSTEM_MAP}.pre-win4lin
	ln -s /boot/System.map.win4lin ${SYSTEM_MAP}
    else
	echo "Warning: no /boot/System.map.win4lin found"
    fi
}

# relink the /boot/System.map file to be the original one
RestoreSystemMap() {
    SYSTEM_MAP=/boot/System.map
    if [ ! -L ${SYSTEM_MAP} ]
    then
	RELEASE="`uname -r`"
	ALT_SYSTEM_MAP=${SYSTEM_MAP}-${RELEASE}
	if [ -L ${ALT_SYSTEM_MAP} ]
	then
	    SYSTEM_MAP=$ALT_SYSTEM_MAP
	fi
    fi
    if [ -e ${SYSTEM_MAP}.pre-win4lin ]
    then
	if [ -L ${SYSTEM_MAP} ]
	then
	    rm ${SYSTEM_MAP}
	else
	    echo "Warning: no ${SYSTEM_MAP} link found"
	fi
	mv -f ${SYSTEM_MAP}.pre-win4lin ${SYSTEM_MAP}
    else
	echo "Warning: no ${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|\
    	grep -v 'failsafe'                   >> ${liloloc}.new
    grep "[ 	]vga *=" ${liloloc}| head -1| \
   	grep -v 'append'                     >> ${liloloc}.new
    #grep "initrd" ${liloloc}| head -1        >> ${liloloc}.new
    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`
    oldinitrd=`grep '^[ 	]*initrd' ${grubloc}|head -1`
    newkernel=`echo $oldkernel|sed -e's:/boot/[^ ]* :/boot/win4lin :'`
    echo $newkernel | grep win4lin >/dev/null 2>&1
    if [ $? != 0 ]
    then
	newkernel=`echo $oldkernel|sed -e's:/[^ ]* :/win4lin :'`
    	echo $newkernel | grep win4lin >/dev/null 2>&1
    	if [ $? != 0 ]
	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}
    echo $newkernel | grep "kernel (" >/dev/null 2>&1
    if [ $? != 0 -a "_$oldroot" != "_" ]
    then
        echo "$oldroot"                   >> ${grubloc}
    fi
    newkernel=`echo $newkernel |sed -e 's/root=[^ ]*//'`
    echo "$newkernel root=$RDEV"          >> ${grubloc}
    echo "$addend"                        >> ${grubloc}
    FixSystemMap
    echo "grub has been updated."
}


# check for lilo
if [ -r ${liloloc} ]
then
  if [ -w ${liloloc} ]
  then
    if [ "_$1" = "_-r" ]
    then
	RestoreLilo
    else
	FixLilo
    fi
  else
    echo "lilo.conf is not writable."
    ERROR=1
  fi
else
  # check for grub
  if [ -r ${grubloc} -o ${grubloc1} ]
  then
    if [ -r ${grubloc1} ]
    then
      grubloc=${grubloc1}
    fi
    if [ -w ${grubloc} ]
    then
	if [ "_$1" = "_-r" ]
	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 [ "_$1" = "_-r" ]
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
