#!/usr/bin/perl
# -*- Mode: cperl -*-
#--------------------------------------------------------------------
# Copyright (C) 2000, 2001, 2002 by MandrakeSoft.
# Stew Benedict <sbenedict@mandrakesoft.com>
#
# Redistribution of this file is permitted under the terms of the GNU
# Public License (GPL)
#--------------------------------------------------------------------
# $Id: yaboot,v 1.8 2002/03/12 15:12:22 sbenedict Exp $
#--------------------------------------------------------------------
## description:
#	      Add/check entry for yaboot bootloader.

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

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

my $debug = 0;

while ( $ARGV[0] =~ /^-/ ) {
    $_ = shift;
    if (m/^-n/) {
        $nolaunch++;
    } elsif (m/^-r/) {
	$remove++;
    } else {
	print STDERR "Unknown option $_";
    }
}

sub getboot_from_fstab {
    my $part;
    local *F;
    open F, '/etc/fstab';
    while (<F>) {
        my @s = split ' ';
        $part = $s[0] if $s[1] =~ m|/boot$| and not $part;
    }
    close F;
    return "boot=" . $part;
}

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

my $glabel = common::sanitize_ver("vmlinuz-${version}");

my $yaboot_conf = $ENV{YABOOT_CONF} ? $ENV{YABOOT_CONF} : "/etc/yaboot.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('1');
my $boot_device = getboot_from_fstab();
my @root_parts = split("=", $root_device);
my @boot_parts = split("=", $boot_device);
my $real_root = $root_parts[1];
my $real_boot = $boot_parts[1];
my $of_root = '';
my $boot = '';
if ($real_boot) {
    $of_root = `/usr/sbin/ofpath $real_boot`; chomp $of_root;
} else {
    $of_root = `/usr/sbin/ofpath $real_root`; chomp $of_root;
    $boot = '/boot'
}

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

#first we parse the files and get all entry.
open F, $yaboot_conf or die "Can't open $yaboot_conf\n";
while (<F>) {

    next if /^\s*#/;

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

    $initrd = $1 if /initrd=(.*)/;
    $root = $1 if /root=(.*)/;

    if ( /^(image|other)=/ || eof ) {
	$entry{$label}{initrd} = $initrd if not $entry{$label}{initrd};
	$entry{$label}{root} = $root if not $entry{$label}{root};
	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}{root}=$root;
    }
}
close F;

(my $boot_image = $1) = common::cat_("/proc/cmdline") =~ /BOOT_IMAGE=(\S+)/;

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

if ($remove) {

    my $tmp = $debug ? "true" : "mktemp";
    my $output = `$tmp /tmp/.yaboot.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, $yaboot_conf;
    open O, ">$output";
    select O unless $debug;

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

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

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

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