#!/usr/bin/perl
# -*- Mode: cperl -*-
#--------------------------------------------------------------------
# Copyright (C) 2000, 2001 by MandrakeSoft.
# Chmouel Boudjnah <chmouel@mandrakesoft.com>.
#
# Redistribution of this file is permitted under the terms of the GNU 
# Public License (GPL)
#--------------------------------------------------------------------
# $Id: lilo,v 1.18 2001/10/17 14:26:45 chmouel Exp $
#--------------------------------------------------------------------
## description: 
#	      Add/check entry for lilo bootloader.

use strict;
use lib qw(/usr/share/loader/);
use common;

my ($memtest, $version, $nolaunch, $remove, $blank);

my $debug = 0;

while ( $ARGV[0] =~ /^-/ ) {
    $_ = shift;
    if (m/^-n/) {
	$nolaunch++;
    } elsif (m/^-m=(\S+)/) {
	$memtest=$1;
    } elsif (m/^-r/) {
	$remove++;
    } else {
	die "Unknow option $_";
    }
}

unless ($version = shift || $memtest) {
    print STDERR "No kernel version has been given using the current\n"; 
    $version = `uname -r`;chomp $version;
}

# Erase dots from label
(my $glabel = $version) =~ s|\.||g; 

# Erase distribution codes from label
$glabel =~ s|mdk||; 
$glabel =~ s|alt||;

# Shorten kernel flavour names
$glabel =~ s|secure|sec| if $glabel =~ /secure/; 
$glabel =~ s|enterprise|ent| if $glabel =~ /enterprise/;
$glabel =~ s|vanilla|vnl| if $glabel =~ /vanilla/;


my $lilo_conf = $ENV{LILO_CONF} ? $ENV{LILO_CONF} : "/etc/lilo.conf";

# we keep entry as hash for future use.
my (%main, %entry);
my ($label, $image);
my ($initrd, $root, $vga);

(my $options = common::getoptions('1'));$options = join(" ", split " ",$options); #Remove the unused space
my $root_device = common::getroot();

`cp -f $lilo_conf ${lilo_conf}.old` if -f $lilo_conf and not $debug;

#first we parse the files and get all entry.
open F, $lilo_conf or die "Can't open $lilo_conf\n";
while (<F>) {
    $blank = "\n" if eof and $_ !~ /^\s*$/;
    
    next if /^\s*#/;

    $main{default} = $1 if m/^default=(.*)/;
    $main{vga} = $1 if m/^vga=(.*)/;
    
    $initrd = $1 if /initrd=(.*)/;
    $root = $1 if /root=(.*)/;
    $vga = $1 if /vga=(.*)/;

    if ( /^(image|other)=/ || eof ) {
	$entry{$label}{initrd} = $initrd if not $entry{$label}{initrd};
	$entry{$label}{root} = $root if not $entry{$label}{root};
	$entry{$label}{vga} = $vga if not $entry{$label}{vga};
	undef $initrd;undef $root;
    }
	
    $image=$1 if /^image=(.*)/;
    if (/label=(.*)/) { 
	$label=$1; 
	$entry{$label}{label}=$label;
	$entry{$label}{kernel}=$image;
        $entry{$label}{initrd}=$initrd;
        $entry{$label}{vga}=$vga;
        $entry{$label}{root}=$root;
    }
}
close F;

(my $boot_image = $1) = common::cat_("/proc/cmdline") =~ /BOOT_IMAGE=(\S+)/;
if ($options =~ /vga=(\S+)/) {
    $vga = $1; $options =~ s/vga=(\S+)//;
} elsif ($entry{$boot_image}{vga}) {
    $vga = $entry{$boot_image}{vga};
}

common::check_default_entry(\%entry, \%main);
common::do_check($entry{$glabel}{label}, $version, $remove) unless $debug || $memtest;

if ($memtest && $entry{memtest86}{label} and not $remove and not $debug) {
    print("no adding entry, memtest86 entry already exist\n");
    exit;
}

if ($remove) {

    my $tmp = $debug ? "true" : "mktemp";
    my $output = `$tmp /tmp/.lilo.XXXXXX`;chomp($output);
    local $/; local *F; local *O;
    
    if ( -l $entry{$main{default}}{kernel}) {
	my $resolved_link = readlink($entry{$main{default}}{kernel});
	my $type = common::get_kernel_type($entry{$main{default}}{kernel});
	
	if ($resolved_link =~ m|vmlinuz-$version|) {
	    
	    my $first_kernel = common::get_first_boot($type, $resolved_link);
	    
	    system("ln -fs vmlinuz-$first_kernel /boot/vmlinuz$type");
	    system("ln -fs initrd-$first_kernel.img /boot/initrd$type.img") if -f "/boot/initrd$type.img";
	
	}
	
    }

    open F, $lilo_conf;
    open O, ">$output";
    select O unless $debug;
    
    while (<F>) {
	if ($memtest) {
	    if (m@image=$memtest.*label=memtest86.*(?=(image|other|$))@s) {
		if (m@image=$memtest.*(image|other)=@s) {
		    $_ =~ s@image=$memtest.*?(?=(image|other))@@s;
		} else {
		    $_ =~ s|image=$memtest.*||s;
		}
	    }
	} else {		
	    if (m@image=/boot/vmlinuz-$version.*label=$glabel.*?(?=(image|other|$))@s) {
		if (m@image=/boot/vmlinuz-$version.*(image|other)=@s) {
		    $_ =~ s@image=/boot/vmlinuz-$version.*?(?=(image|other))@@s;
		} else {
		    $_ =~ s|image=/boot/vmlinuz-$version.*||s;
		}
	    }
	}
	print;
    }
    close F;
    close O;
    select STDOUT;
    system("mv -f $output $lilo_conf") unless $debug;
} else {
    unless ($debug) {
	open F, ">>$lilo_conf" or die "Can't write to $lilo_conf\n";
	select F;
    }
    print "\n" if $blank;
    if ($memtest) {
	print << "EOF";
image=$memtest
	label=memtest86
EOF

    } else {
	print << "EOF";
image=/boot/vmlinuz-$version
	label=$glabel
	$root_device
	read-only
	optional
EOF

    }
    print "\tvga=$vga\n" if $vga;
    print "\tappend=\" $options\"\n" if $options;
    print "\tinitrd=/boot/initrd-$version.img\n" if -f "/boot/initrd-$version.img";
    unless ($debug) {
	close F;
	select STDOUT;
    }
}

unless ($debug) {
    `/sbin/lilo >/dev/null 2>/dev/null` unless $nolaunch;
}

die "There is an error when regenerating lilo, you may have to check your /etc/lilo.conf\n" if ($?);
