#!/usr/bin/perl
#
# /usr/sbin/liloconfig	configure lilo automatically
#
# Author:	Bruce Perens <bruce@Pixar.com>
# Maintainer:	Bernd Eckenfels <ecki@debian.org>
#
# Updated on 1999/01/24 -- Vincent Renardias <vincent@ldsol.com>
#  - never return 0 on error.
#  - updated the template to produce a more helpfull (commentwise)
#      resulting lilo.conf
#
# This script is from Bruce's debian.postinst and need to be more
# intelligent. It should be possible to install lilo in the MBR, too.
#

$|=1;

if ( ! (-f "/etc/fstab") ) {
	print "Huh, bad karma: file /etc/fstab is missing!\n";
	exit(1);
}
print "LILO, the LInux LOader, sets up your system to boot Linux directly\n";
print "from your hard disk, without the need for a boot floppy.\n";

@header = (
	"# Generated by liloconfig\n",
	"\n",
	"# Specifies the boot device\n"
	);

@rootheader = (
	"\n",
	"# Specifies the device that should be mounted as root.\n",
	"# If the special name CURRENT is used, the root device is set to the\n",
	"# device on which the root file system is currently mounted. If the root\n",
	"# has been changed with  -r , the respective device is used. If the\n",
	"# variable ROOT is omitted, the root device setting contained in the\n",
	"# kernel image is used. It can be changed with the rdev program.\n"
	);

@boilerplate = (
	"\n",
	"# Enables map compaction:\n",
	"# Tries to merge read requests for adjacent sectors into a single\n",
	"# read request. This drastically reduces load time and keeps the map\n",
	"# smaller. Using COMPACT is especially recommended when booting from a\n",
	"# floppy disk.\n",
	"compact\n",
	"\n",
	"# Install the specified file as the new boot sector.\n",
	"# If INSTALL is omitted, /boot/boot.b is used as the default.\n",
	"install=/boot/boot.b\n",
	"\n",
	"# Specifies the number of _tenths_ of a second LILO should\n",
	"# wait before booting the first image.  LILO\n",
	"# doesn't wait if DELAY is omitted or if DELAY is set to zero.\n",
	"delay=20\n",
	"\n",
	"# Specifies the location of the map file. If MAP is\n",
	"# omitted, a file /boot/map is used.\n",
	"\nmap=/boot/map\n",
	"\n",
	"# Specifies the VGA text mode that should be selected when\n",
	"# booting. The following values are recognized (case is ignored):\n",
	"#   NORMAL  select normal 80x25 text mode.\n",
	"#   EXTENDED  select 80x50 text mode. The word EXTENDED can be\n",
	"#     abbreviated to EXT.\n",
	"#   ASK  stop and ask for user input (at boot time).\n",
	"#   <number>  use the corresponding text mode. A list of available modes\n",
	"#     can be obtained by booting with  vga=ask  and pressing [Enter].\n",
	"vga=normal\n",
	"\n",
	"image=/vmlinuz\n",
	"	label=Linux\n",
	"	read-only\n",
	"\n",
	"# If you have another OS on this machine (say DOS),\n",
	"# you can boot if by uncommenting the following lines\n",
	"# (Of course, change /dev/hda2 to wherever your DOS partition is.)\n",
	"# other=/dev/hda2\n",
	"#   label=dos\n",
	"\n"
);

sub asky {
	print @_,"? [Yes] ";
	$answer=<STDIN>;
	return ( !($answer =~ /^[nN].*/) );
}

sub askn {
	print @_,"? [No] ";
	$answer=<STDIN>;
	return ( $answer =~ /^[yY].*/ );
}

system('grep -qv "^#" /etc/lilo.conf');
if ( $? == 0 ) {
	# Trust and use the existing lilo.conf.
	# FIX: If the current lilo.conf installs a master boot record, ask
	#	to edit it to a partition boot record and install the master boot
	#	record to chain to that.
	print "\n";
	print "You already have a LILO configuration in the file /etc/lilo.conf\n";
	if ( &asky("Install a boot block using your current LILO configuration") ) {
		print "\nchecking your /etc/lilo.conf for incompatible options...\n\n";
		system('egrep "^[^#]*any_" /etc/lilo.conf');
		if ( $? == 0 ) {
			print "WARNING: You have an old incompatible Configuration Line\n";
			print "         Read the File /usr/doc/lilo/INCOMPAT.gz and restart\n";
			print "         /sbin/lilo to write the changes to your boot sectors\n\n";
			exit(1);
		} else {
			print "WARNING: Even if lilo runs successfully, see /usr/doc/lilo/INCOMPAT.gz\n";
                        print "         for changes in the usage of the /etc/lilo.conf file.\n";
			print "         If needed: edit /etc/lilo.conf and rerun '/sbin/lilo -v'\n\n";
		}
		print "Running lilo\n";
		system("/sbin/lilo -v") || exit(0);
		print "\nERROR: correct /etc/lilo.conf manually and rerun /sbin/lilo\n\n";
		exit(1);
	}
	else {
		print "\n";
		if ( &askn("Wipe out your old LILO configuration and make a new one") ) {
			print "Saving configuration in /etc/lilo.conf.OLD\n";
			rename("/etc/lilo.conf", "/etc/lilo.conf.OLD");
		}
		else {
			print "No changes made.\n";
			exit(0);
		}
	}
}

# Create a lilo.conf if one doesn't exist.
open(FSTAB, "</etc/fstab");
while ( $line=<FSTAB> ) {
	if ( $line =~ m/^\#/ ) {
		next;
	}
	($device,$filesystem)=split(/[ \t]+/, $line);
	if ( $filesystem =~ m:^/$: ) {
		last;
	}
}
if ( ! $filesystem =~ m:^/$: ) {
	exit(0);
}

$disk = $device;
$disk =~ s/[0-9]+$//;
$partition = $device;
$partition =~ s/$disk//;

print "\n";
print "You must do three things to make the Linux system boot from the\n";
print "hard disk. Install a partition boot record, install a master boot\n";
print "record, and set the partition active. You'll be asked to perform\n";
print "each of these tasks. You may skip any or all of them, and perform\n";
print "them manually later on.\n";
print "\n";
if ( &asky("Install a partition boot record to boot Linux from ", $device)) {
	print "Creating small lilo.conf and running lilo.\n";
	umask(022);
	open(CONF, ">/etc/lilo.conf");
	chown(0, 0, "/etc/lilo.conf");
	print CONF @header, "boot=".$device, "\n", @rootheader, "root=".$device, "\n", @boilerplate;
	close(CONF);
	system("/sbin/lilo") || exit(0);
	print "\nERROR: correct /etc/lilo.conf manually and rerun /sbin/lilo\n\n";
	exit(1);
}
print "\n";
print "A master boot record is required to run the paritition boot record.\n";
print "If you are already using a boot manager, and want to keep it,\n";
print "answer \"no\" to the following question. If you don't know\n";
print "what a boot manager is or whether you have one, answer \"yes\".\n";

if ( &askn("Install a master boot record on ", $disk) ) {
	print "Installing MBR on $disk\n";
	system("dd if=/boot/mbr.b of=$disk bs=444 count=1");
}
print "\n";
print "The master boot record will boot the active partition.\n";
print "If you want your system to boot another operating system,\n";
print "such as DOS or Windows, by default, answer \"no\" to the following\n";
print "question. You may still use your boot manager or the master\n";
print "boot record to boot Linux. If you want the system to boot Linux.\n";
print "by default, answer \"yes\".\n";

if ( &asky("Make ", $device, " the active partition") ) {
	print "Activating Partition $partition on disk $disk.\n";
	system("/sbin/activate $disk $partition");
}
else {
	print "\n";
	print "OK. If you installed the master boot record, and the partition\n";
	print "boot record, you may boot Linux by holding down the shift key\n";
	print "as the system boots, and then pressing the $partition key\n";
	print "when you see the \"1234F:\" prompt.\n";
	print "";
	print "For more information, see /usr/doc/mbr/README, and the files\n";
	print "in the /usr/doc/lilo directory.\n";
}
exit(0);
