#!/usr/bin/perl -w
##
## Copyright (c) 2001, 2002, Amnon BARAK (amnon@MOSIX.org).
## All rights reserved.
## This software is subject to the MOSIX SOFTWARE LICENSE AGREEMENT.
##
## THIS SOFTWARE IS PROVIDED IN ITS "AS IS" CONDITION, WITH NO WARRANTY
## WHATSOEVER. NO LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING
## FROM THE USE OF THIS SOFTWARE WILL BE ACCEPTED.
##
##
## Author(s): Shlomo Matichin , A. Spanier
##

# This script adds a compiled kernel to the lilo configuration.

# Default arguments currently compatible with all linux distributions. 
# That is, if lilo is used.

use FindBin;
use Getopt::Long;
use lib "$FindBin::Bin";
use common;

$kernel_dir	= "";
$boot_dir	= "/boot";
$lilo_conf	= "/etc/lilo.conf";

GetOptions( 	"kernel_dir=s" ,	\$kernel_dir ,
		"kernel_on_location" ,	\$kernel_on_location ,
		"dont_delete_files" ,	\$dont_delete_files ,
		"boot_dir=s" ,		\$boot_dir ,
		"lilo_conf=s" ,		\$lilo_conf ,
		"nodefault" ,		\$nodefault ,
		"help" ,		\$usage ,
		"uninstall" ,		\$uninstall );

$kernel_dir =~ s/\/$// ;
$boot_dir =~ s/\/$// ;

usage() if defined $usage;
-w $boot_dir or dead "You do not have write permissions on $boot_dir\n";
-w $lilo_conf or dead "You do not have write permissions on $lilo_conf\n";
uninstall() and exit 1 if defined $uninstall ;
$kernel_on_location or $kernel_dir or dead "You must specify the compiled kernel's source tree root. Use --kernel_dir (--help for usage)";
$kernel_on_location or -r "$kernel_dir/arch/i386" or dead "You do not have read permissions on $kernel_dir\n";
install();
exit 1;
    
sub install
{
	`grep MOSIX $lilo_conf 2>&1` =~ /MOSIX/ and
		dead "Please Uninstall MOSIX before reinstalling";
	$kernel_name = "MOSIX-$mosix_version";
	$kernel_on_location and goto skip_kernel_copy;
	-d "$kernel_dir/mos" or
		dead "Kernel in $kernel_dir does not look like a MOSIX kernel";
	#copy kernel to boot directory
	-e ($kernel_image = "$kernel_dir/arch/i386/boot/bzImage") or
	-e ($kernel_image = "$kernel_dir/arch/i386/boot/zImage") or
	-e ($kernel_image = "$kernel_dir/arch/i386/boot/Image") or
		dead "Kernel image was not found in $kernel_dir/arch/i386/boot/" ;
	system( "cp -f $kernel_image $boot_dir/$kernel_name" ) and 
		dead "Unable to copy $kernel_image to $boot_dir/$kernel_name";
	system( "cp -f $kernel_dir/System.map $boot_dir/System.map-$kernel_name" ) and
		dead "Unable to copy $kernel_dir/System.map to $boot_dir";
skip_kernel_copy:
	system( "ln -sf $boot_dir/System.map-MOSIX-$mosix_version $boot_dir/System.map" ) and
		dead "Unable to link $boot_dir/System.map-MOSIX-$mosix_version to $boot_dir/System.map";
	#tamper with lilo configuration file
	system( "/sbin/lilo -t -C $lilo_conf > /dev/null 2>&1" ) and
		dead "Your current $lilo_conf file is not working currectly with lilo. Fix it and try again\n"; 
	system( "cp -f $lilo_conf $lilo_conf.pre_mosix" ) and
		dead "Unable to backup old $lilo_conf. Aborting";
	open( LILO , $lilo_conf ) or
		dead "Unable to open $lilo_conf for reading";
	@lilo = <LILO> ;
	close( LILO );
	@kernel_arguments = default_kernel_arguments( @lilo );
      
	$root_dev = find_root_dev();
	$root_dev or dead "unable to determine your root device please edit grub.conf manually";

	open( LILO , ">>$lilo_conf" ) or
		dead "Unable to open $lilo_conf for writing";
	print LILO "# The following image was added by the MOSIX installer.\n";
	print LILO "# Do not remove manually. Please use the --uninstall\n";
	print LILO "# option of the installer\n";
	print LILO "# MOSIX IMAGE: $kernel_name\n";
	print LILO "image=$boot_dir/$kernel_name\n";
	print LILO "\tlabel=mosix-$mosix_version\n";
	print LILO "\tappend=\"root=$root_dev\"\n";
	print LILO "",join( "\n" , @kernel_arguments ) ;

	close( LILO );
	#make mosix the default kernel
	make_default( "mosix-$mosix_version" ) if not defined $nodefault;
	#run lilo
	system( "/sbin/lilo -C $lilo_conf" ) and
		dead "Lilo failed. please check your new $lilo_conf file";
	exit ;
}

sub usage {
	print "Usage : add_kernel_to_lilo [OPTION]\n";
	print "--kernel_dir=   the compiled kernel source root directory (must specify!)\n";
	print "--boot_dir=     the binary kernels images directory (default: /boot)\n";
	print "--lilo_conf=    the current configuration file of lilo, to change (default: /etc/lilo.conf)\n";
	print "--nodefault     do not assign MOSIX to be the default kernel\n";
	print "--uninstall     uninstall\n";
	print "--help          this message\n";
	exit ;
}

sub uninstall {
	`grep MOSIX $lilo_conf 2>&1` =~ /MOSIX\ IMAGE\:\s(.*)\n/ or
		print "\nYour previous MOSIX kernel was either not included in '$lilo_conf',\n" and
		print "or it was included manually and cannot be removed automatically.\n" and
		system( "rm -f $lilo_conf.pre_mosix" ),
		exit ;
	$kernel_image = $1 ;
	if(not -f "$lilo_conf.pre_mosix") {
		print "\nSorry: could not find $lilo_conf.pre_mosix!\n" ;
		exit 1;
	}
	system( "mv -f $lilo_conf.pre_mosix $lilo_conf" ) and
		dead "Unable to restore old lilo.conf file from $lilo_conf.pre_mosix\n";
	$dont_delete_files and goto skip_delete_files;
	unlink "$boot_dir/$kernel_image" or
		print "\nFailed to delete $boot_dir/$kernel_image\n";
	unlink "$boot_dir/System.map-$kernel_image" or
		print "\nFailed to delete $boot_dir/System.map-$kernel_image\n";
skip_delete_files:
	system( "/sbin/lilo -C $lilo_conf" ) and
		dead "Lilo failed. Please check your new $lilo_conf file and retry\n";
	exit;
}

sub default_kernel_arguments {
	#parameters: list of lines of lilo.conf
	#return list of argument for of the default kernel in the file
	my $lilo_whole = join '' , @_ ;
	my @kernels = split /\n\s*image\s*=/ , $lilo_whole ;
	if( $kernels[0] =~ /\bdefault\s*=\s*(.+)/g ) {
		$default_kernel = $1;
		foreach $i( 1 .. $#kernels ) {
			$kernels[$i] =~ /\blabel\s*=\s*$default_kernel\b/ and
				$default_kernel_n = $i;
		}
	}
	defined $default_kernel_n or $default_kernel_n = 1;
	my @lines = split "\n" , $kernels[ $default_kernel_n ] ;
	
	splice @lines , 0 , 1;
	@lines = grep !/label\s*=/ , @lines ;
	@lines = grep !/root\s*=/ , @lines;

	return @lines;

}

sub make_default {
	#arguemt: name of kernel to make default
	my $lilo = `cat $lilo_conf`;
	$? and dead "Unable to cat $lilo_conf";
	@lilo = split /\bimage\s*=/ , $lilo ;
	$lilo[0] =~ s/\bdefault\s*=\s*(.*)\b/default\=$_[0]/g or
		$lilo[0] .= "\ndefault=$_[0]\n\n";
	$lilo = join 'image=' , @lilo ;
	open( LILO , ">$lilo_conf" );
	print LILO  $lilo ;
	close( LILO );
}
