#!/usr/bin/env perl #-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- # Boot manager configurator. Designed to be architecture and distribution independent. # # Copyright (C) 2000-2001 Ximian, Inc. # # Authors: Tambet Ingo # Arturo Espinosa # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Library General Public License as published # by the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU Library General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. $SCRIPTSDIR = "@scriptsdir@"; if ($SCRIPTSDIR =~ /^@scriptsdir[@]/) { $SCRIPTSDIR = "."; $DOTIN = ".in"; } require "$SCRIPTSDIR/general.pl$DOTIN"; require "$SCRIPTSDIR/util.pl$DOTIN"; require "$SCRIPTSDIR/file.pl$DOTIN"; require "$SCRIPTSDIR/xml.pl$DOTIN"; require "$SCRIPTSDIR/util.pl$DOTIN"; require "$SCRIPTSDIR/parse.pl$DOTIN"; require "$SCRIPTSDIR/replace.pl$DOTIN"; require "$SCRIPTSDIR/boot-grub.pl$DOTIN"; require "$SCRIPTSDIR/boot-lilo.pl$DOTIN"; # ---------------------------------------------------------------------------- # Fix functions. # # The main reason for these functions is to add default values to xml so the # frontend doesn't have to know anything about lilo or its defaults. sub gst_boot_fix_default { my ($hash) = @_; my ($entries, $found, $entry); $entries = $$hash{"entry"}; return unless $entries; # 'default' if (exists ($$hash{"default"})) { # Check if valid foreach $entry (@$entries) { if ($$hash{"default"} eq $$entry{"label"}) { $found = 1; last; } } delete $$hash{"default"} unless $found; } if (not exists ($$hash{"default"})) { # No 'default', let's add foreach $entry (@$entries) { if ($$hash{"key"} == 0) { $$hash{"default"} = $$entry{"label"}; last; } } } } # Internal. Should be run after fix_entries. sub gst_boot_fix_globals { my ($hash) = @_; return unless $hash; &gst_boot_fix_default ($hash); } # Internal sub gst_boot_fix_entry { my ($entry) = @_; my ($name); return unless $entry; $name = $$entry{"image"} if exists $$entry{"image"}; $name = $$entry{"other"} if (!$name && exists $$entry{"other"}); # Remove entries without entry identifier 'entry' or 'other'. unless ($name) { undef $entry; return; } # Add 'label' field which is optional in lilo.conf unless (exists $$entry{"label"}) { $$entry{"label"} = $1 if ($name =~ /\S+\/(\S+)$/); } } # Internal sub gst_boot_fix_entries { my ($hash) = @_; my ($entries, $entry); return unless $hash; $entries = $$hash{"entry"}; return unless $entries; foreach $entry (@$entries) { &gst_boot_fix_entry ($entry); } } sub gst_boot_fix { my ($hash) = @_; return unless $hash; &gst_boot_fix_entries ($hash); &gst_boot_fix_globals ($hash); } # -------------------------------------------------------- sub gst_boot_bootloader_get { my ($current_tool, $current_date, $tool, $date); $current_date = 0; $tool = gst_file_locate_tool ("lilo"); if ($tool ne "") { $date = (stat ($tool))[8]; if ($date > $current_date) { $current_date = $date; $current_tool = "lilo"; } } $tool = gst_file_locate_tool ("grub-install"); if ($tool ne "") { $date = (stat ($tool))[8]; if ($date > $current_date) { $current_date = $date; $current_tool = "grub"; } } if ($current_date eq 0) { &gst_report ("platform_no_bootloader", $main::gst_dist); return undef; } return $current_tool; } sub gst_boot_entries_get { my ($partition) = @_; my (%dist_attrib, @res, %fn, @entries, $entry); my ($dist, $value, $file, $proc); my ($entry, $j, $key, $tmp); %dist_attrib = &gst_boot_get_entry_parse_table (); %fn = %{$dist_attrib{"fn"}}; $proc = $dist_attrib{"entries_get"}; @entries = &$proc (\%fn); $ {$dist_attrib{"fn"}}{"PARTITION"} = $partition; $key = 0; foreach $entry (@entries) { foreach $j (keys (%fn)) { $tmp = &gst_parse_expand ($fn{$j}, "key", $key); $ {$dist_attrib{"fn"}}{$j} = &gst_parse_expand ($tmp, "label", $entry); } $entry = &gst_parse_from_table ($dist_attrib{"fn"}, $dist_attrib{"table"}); # if the entry doesn't contain any of these fields, then we can't understand it, just ignore it if (exists ($$entry {"image"}) || exists ($$entry {"other"})) { push @res, $entry; } $key++; } return \@res; } sub gst_boot_conf_get { my ($tool) = &gst_boot_bootloader_get (); my $config_file = &gst_boot_grub_get_config_file (); my %tool_tables = ( "lilo" => { fn => { LILO_CONF => "/etc/lilo.conf" }, table => [ [ "partitions", \&gst_partition_scan_info ], # [ "pixmapsup", \&gst_parse_trivial, 0 ], [ "timeout", \&gst_boot_lilo_parse_global, LILO_CONF, "delay" ], [ "prompt", \&gst_boot_lilo_parse_global_kw, LILO_CONF, "prompt" ], [ "default", \&gst_boot_lilo_parse_global, LILO_CONF, "default" ], [ "boot", \&gst_boot_lilo_parse_global, LILO_CONF, "boot" ], # [ "root", \&gst_boot_lilo_parse_global, LILO_CONF, "root" ], [ "entry", \&gst_boot_lilo_parse_entries, LILO_CONF, "%partitions%" ], ] }, "grub" => { fn => { GRUB_CONF => $config_file, DEVICE_MAP => "/boot/grub/device.map", # MTAB => "/etc/mtab" }, table => [ [ "partitions", \&gst_partition_scan_info ], # [ "pixmapsup", \&gst_parse_trivial, 1 ], # [ "pixmap", \&gst_boot_grub_parse_pixmap, [GRUB_CONF, DEVICE_MAP, MTAB] ], [ "timeout", \&gst_boot_grub_parse_timeout, GRUB_CONF ], [ "prompt", \&gst_boot_grub_parse_prompt, GRUB_CONF ], [ "default", \&gst_boot_grub_parse_default, GRUB_CONF ], [ "entry", \&gst_boot_entries_get, "%partitions%" ], ] } ); return &gst_parse_from_table ($ {$tool_tables{$tool}}{"fn"}, $ {$tool_tables{$tool}}{"table"}); } sub gst_boot_get_entry_parse_table { my $config_file = &gst_boot_grub_get_config_file (); my %tool_tables = ( entries_get => \&gst_boot_grub_get_entries_fn, fn => { KEY => "#key#", LABEL => "#label#", GRUB_CONF => $config_file, DEVICE_MAP => "/boot/grub/device.map", MTAB => "/etc/mtab" }, table => [ ["key", \&gst_parse_trivial, [KEY]], ["label", \&gst_parse_trivial, [LABEL]], ["root", \&gst_boot_grub_parse_root, [GRUB_CONF, DEVICE_MAP, KEY]], ["type", \&gst_boot_grub_parse_type, [GRUB_CONF, KEY, PARTITION], "%root%"], ["image", \&gst_boot_grub_parse_image, [GRUB_CONF, DEVICE_MAP, MTAB, KEY]], ["other", \&gst_boot_grub_parse_other, [GRUB_CONF, DEVICE_MAP, MTAB, KEY]], ["append", \&gst_boot_grub_parse_append, [GRUB_CONF, KEY]], ["initrd", \&gst_boot_grub_parse_initrd, [GRUB_CONF, DEVICE_MAP, MTAB, KEY]], ["module", \&gst_boot_grub_parse_module, [GRUB_CONF, DEVICE_MAP, MTAB, KEY]], ["password", \&gst_boot_grub_parse_password, [GRUB_CONF, KEY]] ] ); return %tool_tables; &gst_report ("platform_no_table", $gst_dist); return undef; } sub gst_boot_entry_set { my ($dist_attrib, $values_hash) = @_; my ($j, %fn, $res); %fn = %{$$dist_attrib{"fn"}}; foreach $j (keys (%fn)) { $fn{$j} = &gst_parse_expand ($ {$$dist_attrib{"fn"}}{$j}, "key", $$values_hash{"key"}); } return &gst_replace_from_table (\%fn, $$dist_attrib{"table"}, $values_hash); } sub gst_boot_entries_set { my ($entries) = @_; my (%dist_attrib, %fn, @old, @new, @del); my ($i, $proc, $entry); my ($tmp, $res); %dist_attrib = &gst_boot_get_entry_replace_table (); %fn = %{$dist_attrib{"fn"}}; foreach $entry (@$entries) { $new[$$entry{"key"}] = $entry; } $proc = $dist_attrib{"entries_get"}; @old = &$proc (\%fn); for ($i = 0; $i < &gst_max (scalar @old, scalar @$entries); $i++) { if ($new[$i] ne undef) { $tmp = &gst_boot_entry_set (\%dist_attrib, $new[$i]); $res = $tmp if !$res; } else { push @del, $i; } } # Delete all old entries that are not in the hash. $proc = $dist_attrib{"entries_del"}; $tmp = &$proc (\%fn, \@del); $res = $tmp if !$res; return $res; } sub gst_boot_conf_set { my $values_hash = $_[0]; my $config_file = &gst_boot_grub_get_config_file (); $tool = &gst_boot_bootloader_get (); my %tool_tables = ( "lilo" => { fn => { LILO_CONF => "/etc/lilo.conf"}, table => [ [ "boot", \&gst_boot_lilo_replace_global, LILO_CONF, "boot" ], # [ "root", \&gst_boot_lilo_replace_global, LILO_CONF, "root" ], [ "timeout", \&gst_boot_lilo_replace_global, LILO_CONF, "timeout" ], [ "timeout", \&gst_boot_lilo_replace_global, LILO_CONF, "delay" ], [ "prompt", \&gst_boot_lilo_replace_global_kw, LILO_CONF, "prompt" ], [ "default", \&gst_boot_lilo_replace_global, LILO_CONF, "default" ], [ "entry", \&gst_boot_lilo_entries_set, LILO_CONF ], ] }, "grub" => { fn => { GRUB_CONF => $config_file, DEVICE_MAP => "/boot/grub/device.map", MTAB => "/etc/mtab" }, table => [ # [ "pixmap", \&gst_boot_grub_replace_pixmap, [GRUB_CONF, DEVICE_MAP, MTAB] ], [ "timeout", \&gst_boot_grub_replace_timeout, GRUB_CONF ], [ "prompt", \&gst_boot_grub_replace_prompt, GRUB_CONF ], [ "default", \&gst_boot_grub_replace_default, GRUB_CONF , "%entry%"], [ "entry", \&gst_boot_grub_entries_set, [GRUB_CONF, DEVICE_MAP, MTAB] ], ] } ); return &gst_replace_from_table ($ {$tool_tables{$tool}}{"fn"}, $ {$tool_tables{$tool}}{"table"}, $values_hash); } sub gst_boot_get_entry_replace_table { my $config_file = &gst_boot_grub_get_config_file (); my %tool_tables = ( entries_get => \&gst_boot_grub_get_entries_fn, entries_del => \&gst_boot_grub_remove_entries, fn => { KEY => "#key#", GRUB_CONF => $config_file, DEVICE_MAP => "/boot/grub/device.map", MTAB => "/etc/mtab" }, table => [ # label has to go first, because it creates the entry if non-existent. ["label", \&gst_boot_grub_replace_label, [GRUB_CONF, KEY]], # ["type", \&gst_boot_grub_replace_type, [GRUB_CONF, KEY]], ["root", \&gst_boot_grub_replace_root, [GRUB_CONF, DEVICE_MAP, KEY, "%type%"]], ["image", \&gst_boot_grub_replace_image, [GRUB_CONF, DEVICE_MAP, MTAB, KEY]], ["other", \&gst_boot_grub_replace_other, [GRUB_CONF, DEVICE_MAP, KEY]], ["append", \&gst_boot_grub_replace_append, [GRUB_CONF, DEVICE_MAP, KEY]], ] ); return %tool_tables; }