Add new script liloconfig
[rrq/maintain_lilo.git] / debian / scripts / liloconfig
index ab470bd937a200780b1a11248f326a025855daf2..46a83f512d0ad44e55f8e29cf0b1f46a67cd1a3c 100644 (file)
-#!/usr/bin/perl
-#
-# /usr/sbin/liloconfig -- configure lilo automatically using debconf
-#
-# Author:      Bruce Perens <bruce@Pixar.com>
-#              Bernd Eckenfels <ecki@debian.org>
-#              Vincent Renardias <vincent@ldsol.com>
-#              Peter Maydell <pmaydell@chiark.greenend.org.uk>
-#              Russell Coker <russell@coker.com.au>
-#               Andrés Roldán <aroldan@debian.org>
-#               William Pitcock <nenolod@dereferenced.org>
-#
-# Maintainer:   William Pitcock <nenolod@dereferenced.org>
-
-# Updated on 2008/07/26 -- William Pitcock <nenolod@dereferenced.org>
-# - Use large-memory by default, hoping that BIOSes now days aren't
-#   so broken.
-#
-# Updated on 2008/06/16 -- William Pitcock <nenolod@sacredspiral.co.uk>
-# - Warn about images larger than 6.5MiB because some chipsets
-#   cannot load them in real mode.
-#
-# Updated on 2006/08/27 -- Artur R. Czechowski <arturcz@hell.pl>
-# - Communication with user is handled via debconf
-#
-# Updated on 2004/07/31 -- Andrés Roldán <aroldan@debian.org>
-# - Added get_bitmap() to allow one choose the bitmap to use.
-#
-# Updated on 2003/12/20 -- Andrés Roldán <aroldan@debian.org>
-# - Modified get_images() to insert initrd= field when necessary.
-#   See Bug#224368.
-#   
-# Updated on 2003/10/24 -- Andrés Roldán <aroldan@debian.org>
-# - Now liloconfig will smartly get the installed kernel images
-#   and put them in the configuration file.
-#
-# Updated on 2003/10/05 -- Andrés Roldán <aroldan@debian.org>
-# - Updated install= comments . See Bug#183471.
-# - Not using depecrated install=/boot/*b options.
-#
-# Updated on 2003/08/07 -- Andrés Roldán <aroldan@fluidsignal.com>
-# - bitmap= field will search bitmaps on /boot 
-#
-# Updated on 2003/04/23 -- Andrés Roldán <aroldan@fluidsignal.com>
-# - added menu entry for sid and sarge from debian-bootscreen.
-#
-# 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
-#
-# Updated on 1999/11/24 -- Peter Maydell <pmaydell@chiark.greenend.org.uk>
-#  - added error checking of various system calls
-#  - added $DEBUG switch and pulled lilo.conf and fstab filenames
-#    out into config variables.
-#  - turned on Perl's -w switch and use strict subs/refs
-#  - now does examination of current situation up front, separated
-#    from the logic of what we do in various situations.
- #  - added check for special marker in /etc/fstab that indicates that we
- #    are configuring the base filesystem and shouldn't actually do anything.
- #
- # Updated on 2000-01-23 -- Peter Maydell <pmaydell@chiark.greenend.org.uk>
- #  - fixed a (harmless) warning produced if /etc/fstab had a blank line in it
- #  - fixed a bug where partition number was not being pulled out of the
- #    /dev/hda4 string correctly.
- #  - added a paranoia check that the disk/device we get from fstab actually
- #    exist in the filesystem.
- #  - fixed flow-of-control problem where we simply weren't ever installing
- #    MBR and making partition active.
- #  - added & to some function calls, for consistency.
- #  - changed all references to /usr/doc/lilo/ to /usr/share/doc/lilo/.
- #  - added warning that the lilo.conf we produce does not suffice for
- #    complicated situations.
- #  - expanded some of the other prompts and explanatory text presented
- #    to the user.
- #  - added a 'ruler' to separate out questions
- #  - questions no longer accept anything except RET as meaning 'go with
- #    default answer'. [Previously, if the default answer was 'yes',
- #    anything not beginning with Y or y would be interpreted as 'no'.
- #    This is IMHO too lenient considering the consequences of getting
- #    it wrong...]
- #  - updated Maintainer, Author and Wishlist...
- #
- # Updated on 2000-01-25 -- Peter Maydell <pmaydell@chiark.greenend.org.uk>
- #  - fixed important bug causing lilo not to install on RAID arrays.
- #    (Bugs #56153,#56183,#56196)
- #  - minor improvement to a regexp (no actual functional change) (Bug#56127)
- #  - expanded cryptic 'iff' comment (Bug#56127)
- #
- # Updates on 2001-05-04 -- Russell Coker <russell@coker.com.au>
- #  - more work on devfs root support
-
- # Wishlist:
- # 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.
- # Support for systems which dual boot (esp. dual Linux/Windows) would
- # also be nice, but could be complicated to get right.
-
- ###use strict 'subs';
- ###use strict 'refs';
- #### use strict 'vars' falls over on all the global variables :->
-use Debconf::Client::ConfModule qw(:all);
-version('2.0');
-$|=1;
-
- fset("liloconfig/banner","seen","false");
- fset("liloconfig/use_current_lilo","seen","false");
- fset("liloconfig/wipe_old_liloconf","seen","false");
- fset("liloconfig/instruction","seen","false");
- fset("liloconfig/install_from_root_device","seen","false");
- fset("liloconfig/use_lba32","seen","false");
- fset("liloconfig/install_mbr","seen","false");
- fset("liloconfig/make_active_partition","seen","false");
- fset("liloconfig/select_bitmap","seen","false");
-
- # Set this to 1 to disable all commands that do things to the
- # hard disk (ie actually running lilo). Note that we still write
- # to $LILOCONF, so you should also tweak that to get a 'safe' test
- # environment.
- #$DEBUG=1;
-
- # Various files we access
- $LILOCONF='/etc/lilo.conf';
- $FSTAB='/etc/fstab';
-
- subst("liloconfig/liloconf_exists","liloconf",$LILOCONF);
- subst("liloconfig/lilo_warning","liloconf",$LILOCONF);
- subst("liloconfig/lilo_error","liloconf",$LILOCONF);
- subst("liloconfig/odd_fstab","liloconf",$LILOCONF);
- subst("liloconfig/instruction","liloconf",$LILOCONF);
-
- subst("liloconfig/fstab_broken","fstab",$FSTAB);
- subst("liloconfig/odd_fstab","fstab",$FSTAB);
-
- # Print a banner now, to give the user something to look at while
- # we ferret around in the fstab...
-
- settitle("liloconfig/maintitle");
- input("low","liloconfig/banner");
-
- # First we analyse the setup and set variables appropriately
- $fstab_broken = 1;        # is there a valid /etc/fstab? Assume not and prove otherwise.
- $liloconf_exists = 0;  # is there a preexisting lilo.conf with a non-commented out line?
- $liloconf_incompatible = 0;   # does lilo.conf use options not valid for this version of lilo?
- $configuring_base = 0;        # are we configuring the 'base' filesystem (special case)
- $odd_fstab = 0;         # set if we don't understand the device in the fstab
- # We also set $device, $disk, $partition (assuming fstab_broken == 0)
-
- if (-f $FSTAB) 
- {
-     # Parse fstab for the root partition...
-     open(FSTAB, "<$FSTAB") or die "liloconfig: couldn't open $FSTAB: $!\n";
-     while (<FSTAB>) 
-     {
-        # Check for a magic string which indicates that we are configuring
-        # the base filesystem and not a real machine...
-        $configuring_base = 1 if /^# UNCONFIGURED FSTAB FOR BASE SYSTEM/;
-        next if /^#/;    # ignore comment lines
-        s/^[ \t]+//;     # remove space or tab at begin of the line
-        ($device,$filesystem) = split(/[ \t]+/);
-        next unless defined $filesystem;   # ignore empty lines too
-        # Stop if we found the root device...
-        if ($filesystem eq '/') 
-        {
-            $fstab_broken = 0;
-            last;
-        }
-     }
-     close(FSTAB) or die "liloconfig: couldn't close $FSTAB: $!\n";
- }
-
- if (! $fstab_broken) 
- {
-     # Valid device/filesystem pair, parse them
-     $disk = `/usr/sbin/lilo_find_mbr $device`;
-     chomp($disk);
-     $partition = $device;
-     my $devfs = 0;
-
-     # Paranoia check: there should be valid /dev/ nodes for these.
-     # We could check for block-special-device-ness, but perhaps
-     # some people have symlink forests in /dev/ ?
-     # This check will fail on things like RAID arrays, where the
-     # devices don't have names like /dev/hda4. In this case we can't
-     # do simple autoconfiguration, but we still want to be able
-     # to allow the user to install their own handrolled lilo.conf.
-     $odd_fstab = 1 unless ($partition =~ /\d+$/ && -e $disk && -e $device);
- }
-
- # Check for an existing lilo.conf with some non-comment lines in it...
- system ("grep -qsv '^#' $LILOCONF");
- # Exit status is 0 iff lilo.conf exists and contains at least one non-comment line.
- if ($? == 0) 
- {
-     $liloconf_exists = 1;
-     $liloconf_incompatible = &compatibility_check ();
- }
-
- ##########################################################
- # Boilerplate arrays used to produce an initial lilo.conf
- ##########################################################
-
- @header = (
-        "# Generated by liloconfig\n",
-        "\n",
-        );
-
- @bootheader = (
-               "# 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"
-               );
-
- @boilerplate1 = (
-                 "\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",
-                 "# LILO supports built in boot sectory, you only need\n",
-                 "# to specify the type, choose one from 'text', 'menu' or 'bitmap'.\n",
-                 "# new: install=bmp      old: install=/boot/boot-bmp.b\n",
-                 "# new: install=text     old: install=/boot/boot-text.b\n",
-                 "# new: install=menu     old: install=/boot/boot-menu.b or boot.b\n",
-                 "# default: 'menu' is default, unless you have a bitmap= line\n",
-                 "# Note: install=bmp must be used to see the bitmap menu.\n",
-                 "# install=menu\n",
-                 "install=bmp\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",
-                 "# Prompt to use certaing image. If prompt is specified without timeout,\n",
-                 "# boot will not take place unless you hit RETURN\n",
-                 "prompt\n",
-                 "timeout=50\n",
-                 "\n",
-                 "# Enable large memory mode.\n",
-                 "large-memory\n",
-                 "\n",
-                 "# Specifies the location of the map file. If MAP is\n",
-                 "# omitted, a file /boot/map is used.\n",
-                 "map=/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",
-                 "# Defines non-standard parameters for the specified disk.\n",
-                 "#disk=/dev/sda\n",
-                 "#\tbios=0x80\n",
-                 "\n",
-                 "# If you are using removable USB drivers (with mass-storage)\n",
-                 "# you will need to tell LILO to not use these devices even\n",
-                 "# if defined in /etc/fstab and referenced in /proc/partitions.\n",
-                 "# Adjust these lines to your devices:\n",
-                 "#\n",
-                 "# disk=/dev/sda inaccessible\n",
-                 "# disk=/dev/sdb inaccessible\n",
-                 "\n"
-                 );
-
- @boilerplate2 = (
-                 "# 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=\"MS Windows\"\n",
-                 "\n"
-                 );
-
- ####################
- # Utility functions
- ####################
-
-sub get_bitmap
-{
-    input("high","liloconfig/select_bitmap");
-    go();
-    ($ret,$val) = get("liloconfig/select_bitmap");
-    
-       # each line with: [ filename,bmp-color,bmp-table,bmp-timer ]
-    @bitmaps = (
-                  [ "/boot/tuxlogo.bmp","6,9,0;15,9,0","59,5;1,23,","66,28;6,8,0" ],
-                  [ "/boot/inside.bmp","14,11,,15,9,0","21,284p,2,7,175p,4","73,29,12,8,0" ],
-                  [ "/boot/debian.bmp","10,0,,7,0,","16,12,1,12,16","34,28,13,0," ],
-                  [ "/boot/debian-de.bmp","10,0,,7,0,","16,12,1,12,16","34,28,13,0," ],
-                  [ "/boot/debianlilo.bmp","1,,0,9,,0","106p,144p,2,9,144p","514p,144p,6,8,0" ]
-                  [ "/boot/coffee.bmp","12,,11,15,,8","385p,100p,1,10","38,2,13,1" ],
-                  [ "/boot/onlyblue.bmp","7,,0,15,,0","3,4,4,26,19,1","37,2,7,4,0" ],
-                  );
-
-    $counter = 0;
-
-    for $ref (@bitmaps)
-    {
-       last if ($val eq @$ref[0]);
-       $counter++;
-    }
-
-    $ans = $counter;
-
-    push (@bitmapconf, "\n# Bitmap configuration for $bitmaps[$ans][0]\n");
-    push (@bitmapconf, "bitmap=$bitmaps[$ans][0]\n");
-    push (@bitmapconf, "bmp-colors=$bitmaps[$ans][1]\n");
-    push (@bitmapconf, "bmp-table=$bitmaps[$ans][2]\n");
-    push (@bitmapconf, "bmp-timer=$bitmaps[$ans][3]\n");
-
-    return @bitmapconf;
-}
-
-sub get_images
-{
-    my @images = ();
-
-    $count = 0;
-   
-    print STDERR "Searching for installed kernels and updating image entries ...\n";
-   
-    push (@images, "# These images were automagically added. You may need to edit something.\n\n");
-    
-    # Ignore that /vmlinuz link since it can surely be poiting to 
-    # some /boot/vmlinuz* file
-    if (-e "/vmlinuz" && ! -l "/vmlinuz")
-    {
-       push (@images, "image=/vmlinuz\n");
-       push (@images, "\tlabel=\"Linux\"\n");
-       if (-e "/initrd.img")
-       {
-           push (@images, "\tinitrd=/initrd.img\n");
+#!/usr/bin/perl -w
+
+#       liloconfig -  creating a new lilo.conf file
+#       
+#       Copyright 2011 Joachim Wiedorn <ad_debian@joonet.de>
+#       
+#       This program is free software; you can redistribute it and/or modify
+#       it under the terms of the GNU 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 General Public License for more details.
+#       
+#       You should have received a copy of the GNU General Public License
+#       along with this program; if not, write to the Free Software
+#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+#       MA 02110-1301, USA.
+
+#---- some modules
+use strict;
+use warnings;
+use Getopt::Std;
+use Pod::Usage;
+use File::Copy;
+
+
+#---- global variables
+my $prog = $0;
+$prog =~ s#.*/##;
+my $version = "0.1";
+
+#---- parameter check
+# h: help, v: verbose, f: force
+our $opt_h = 0;
+our $opt_v = 0;
+our $opt_f = 0;
+getopts('hvf');
+# define perldoc usage
+pod2usage(1) if $opt_h;
+
+#---- other variables
+our $liloconf  = "/etc/lilo.conf";
+our $conftmp_1 = "/tmp/lilotmp1";
+our $conftmp_2 = "/tmp/lilotmp2";
+our $liloconfold = $liloconf . ".old";
+our $liloconfnew = $liloconf . ".new";
+our $fstabconf = "/etc/fstab";
+
+our $idpath = "/dev/disk/by-id";
+our $uuidpath = "/dev/disk/by-uuid";
+our $lblpath = "/dev/disk/by-label";
+our $template = "/usr/share/doc/lilo/examples/lilo.example.conf.gz";
+
+our $rootpart;    # found root part
+our $root_dev;    # /dev/hdX9, /dev/sdX9, /dev/md/*
+our $root_id;     # UUID, LABEL, ID
+our $boot_dev;    # /dev/hdX, /dev/sdX, /dev/md
+our $boot_id;     # DISK-ID
+
+#-------------------- main program --------------------
+
+sub main {
+
+       my $exit = 0;
+
+       if (@ARGV == 1) {
+               $liloconf = "$ARGV[0]";
+               $liloconfold = $liloconf . ".old";
+               $liloconfnew = $liloconf . ".new";
        }
-       push (@images, "\tread-only\n");
-       push (@images, "\n");
-    }
-
-    # Ignore that /boot/vmlinuz link as well since it can surely be 
-    # poiting to some /boot/vmlinuz* file
-    if (-e "/boot/vmlinuz" && ! -l "/boot/vmlinuz")
-    {
-        push (@images, "image=/boot/vmlinuz\n");
-        push (@images, "\tlabel=\"Linux 1\"\n");
-        if (-e "/boot/initrd.img")
-        {
-            push (@images, "\tinitrd=/boot/initrd.img\n");
-        }
-        push (@images, "\tread-only\n");
-        push (@images, "\n");
-    }
-
-    foreach $image (`/bin/ls /boot/vmlinuz*`)
-    {
-        chomp $image;
-
-       my $version = "";
-       my $complement = "";
-       
-        if ($image =~ /vmlinuz-(\d+\.\d+\.\d+)-(.+)/)
-        {
-           $version = $1;
-           $complement = $2;
-           
-            $label = "Lin " . $version . "img" . $count;
-        }
-       elsif ($image =~ /vmlinuz-(\d+\.\d+\.\d+)$/)
-       {
-           $version = $1;
-           
-           $label = "Lin " . $version . "img" . $count;
+       if (-f $liloconf and not $opt_f) {
+               print "$prog: $liloconf already exist! Please use '-f' for overwriting.\n";
+               $exit = 1;
        }
-       else
-        {
-            $label = "Lin " . "img" . $count;
-        }
+       else {
+               $exit = create_lilo_conf()
+       }               
+       return $exit;
+}
+
+#-------------------- subroutines --------------------
+
+sub create_lilo_conf {
        
-        push (@images, "image=$image\n");
-        push (@images, "\tlabel=\"$label\"\n");
+       my $found = 0;
+       my $exit = 1;
+
+       # search for root device in fstab and convert it
+       $found = detect_root_device();
+
+       # convert root device to boot device
+       if ($found) { $found = convert_boot_device(); }
+
+       # finally write new lilo.conf file
+       if ($found) { $exit = write_lilo_conf(); }
+
+       return $exit;
+}
+
+sub detect_root_device {
        
-       if (-e "/boot/initrd.img-$version-$complement")
-       {
-           push (@images, "\tinitrd=/boot/initrd.img-$version-$complement\n");
-       }
-       elsif (-e "/boot/initrd.img-$version")
-       {
-           push (@images, "\tinitrd=/boot/initrd.img-$version\n");
-       }
+       # read fstab and find root device; 
+       my $found = read_fstab();
 
-        push (@images, "\tread-only\n");
-       push (@images, "\n");
+       # identify root device: root_dev and root_id
+       if ($found) { $found = convert_root_device(); }
        
-        $count++;
-    }
-
-    if (-e "/boot/memtest86.bin")
-    {
-        push (@images, "image=/boot/memtest86.bin\n");
-        push (@images, "\tlabel=\"Memory Test\"\n");
-        push (@images, "\tread-only\n");
-        push (@images, "\n");
-    }
-
-    if (-e "/boot/memtest86+.bin")
-    {
-       push (@images, "image=/boot/memtest86+.bin\n");
-       push (@images, "\tlabel=\"Memory Test+\"\n");
-       push (@images, "\tread-only\n");
-       push (@images, "\n");
-    }
-           
-    return @images;
+       return $found;
 }
 
-sub asky 
-{
-    do 
-    {
-       print STDERR @_,"? [Yes] ";
-       $answer=<STDIN>;
-    } 
-    while ($answer ne "\n" && !($answer =~ /^[YyNn].*/));
-    &ruler ();
-    return ( !($answer =~ /^[nN].*/) );
-}
+sub read_fstab {
+       
+       my $root_part;
+       my $mountpoint;
+       my $broken_fstab = 1;
+       my $base_fstab = 0;
+       my $found = 1;
+
+       # check fstab for root device
+       if (-f $fstabconf) {
+               # Parsing fstab for the root partition
+               open(FSTAB, "<$fstabconf") or die "$prog: couldn't open $fstabconf: $!\n";
+
+               while (<FSTAB>) {
+                       # Search magic string which indicates a base filesystem
+                       $base_fstab = 1 if /^# UNCONFIGURED FSTAB FOR BASE SYSTEM/;
+                       next if /^#/;     # ignore comment lines
+
+                       s/^[ \t]+//;      # remove space or tab at begin of the line
+                       ($root_part,$mountpoint) = split(/[ \t]+/);
+                       next unless defined $mountpoint;    # ignore empty lines too
+
+                       # stop if we found the root device...
+                       if ($mountpoint eq '/') {
+                               $broken_fstab = 0;
+                               last;
+                       }
+               }
+               close(FSTAB) or die "$prog: couldn't close $fstabconf: $!\n";
+       }
 
-sub askn 
-{
-    do 
-    {
-       print STDERR @_,"? [No] ";
-       $answer=<STDIN>;
-    } 
-    while ($answer ne "\n" && !($answer =~ /^[YyNn].*/));
-    &ruler ();
-    return ( $answer =~ /^[yY].*/ );
-}
+       if ($base_fstab) {
+               print "E: It seems you want configure the base filesystem \n" .
+                     "and I'm therefore simply going to exit successfully \n" .
+                     "without trying to actually configure LILO properly. \n";
+               $found = 0;
+       }
+       if ($broken_fstab) {
+               print "E: It seems the file /etc/fstab is not properly \n" .
+                     "configured: no root partition '/' found! \n";
+               $found = 0;
+       }
+       # save the found root device
+       $rootpart = $root_part;
 
-sub compatibility_check 
-{
-    # Check a lilo.conf for options which are not compatible
-    # with the current version of lilo, and return 1 if any
-    # incompatible usages are found.
-    # This currently just checks for use of the any_* loaders.
-    system ("egrep '^[^#]*any_' $LILOCONF");
-    return 1 if ($? == 0);
-    return 0;
+       return $found;
 }
 
-sub safe_system($)
-{
-    # Works like system(), but just echoes the command that would
-    # be run if $DEBUG is 1.
-    if ($DEBUG) {
-       print STDERR "[Would have run: ", join(' ', @_), "]\n";
-       $? = 0;
-    } 
-    else 
-    {
-       system($_[0].">&2");
-    }
+sub convert_root_device {
+       
+       my $found = 1;
+       my $root_disk = '';
+       my $root_link;
+       # global variables: $root_dev, $root_id
+
+       if ($rootpart =~ /\/dev\//) {
+               $root_disk = $rootpart;
+
+               if (-b $root_disk) {
+                       $root_dev = $root_disk;
+                       if($opt_v) { print "Convert root option $root_disk into UUID\n"; }
+                       $root_id = find_id_link($root_disk,$uuidpath);
+
+                       if (not -l "$uuidpath/$root_id") {
+                               if($opt_v) { print "W: could not find UUID for $root_disk!\n"; }
+                               ## than we want use root_dev in lilo.conf
+                               #$found = 0;
+                       }
+                       else {
+                               # finally add uuid label
+                               $root_id = "UUID=" . $root_id;
+                       }
+               }
+               else {
+                       if($opt_v) { print "E: cannot check $root_disk: device does not exist!\n"; }
+                       $found = 0;
+               }
+       }
+       elsif ($rootpart =~ /^UUID/ or $rootpart =~ /^LABEL/) {
+               $root_link = $rootpart;
+               $root_link =~ s{\"}{}g;
+               $root_link =~ s{^LABEL=}{/dev/disk/by-label/};
+               $root_link =~ s{^UUID=}{/dev/disk/by-uuid/};
+
+               if (-l $root_link) {
+                       $root_id = $rootpart;
+                       $root_disk = readlink($root_link);
+                       $root_disk =~ s{\.\./\.\./}{/dev/};
+
+                       if (-b $root_disk) { $root_dev = $root_disk; }
+                       else {
+                               if($opt_v) { print "E: cannot check $root_link: link does not exist!\n"; }
+                               $found = 0;
+                       }
+               }
+               else {
+                       print "E: cannot check $root_link: link does not exist!\n";
+                       $found = 0;
+               }
+       }
+       else {
+               print "E: cannot use uncommon $rootpart found as root device!\n";
+               $found = 0;
+       }
+
+       return $found;
 }
 
-#####################################
-# Actual work is done below here...
-#####################################
-
-# Debian's 'base' filesystem is a special case -- it's prebuilt
-# by installing and configuring packages into a subdirectory,
-# which is then made into a tarball, which is then used to
-# make the initial filesystem for a fresh Debian install.
-# Thus we can't actually run LILO now, because we know nothing
-# of the disk layout. That will be done as part of the install
-# process.
-if ($configuring_base) 
-{
-    input("high","liloconfig/configuring_base");
-    go();
-
-exit(0);
+sub find_id_link {
+       
+       my $olddev = $_[0];
+       my $path_id = $_[1];
+       my @sellinks;
+       my $_idlink;
+       my $_actlink;
+       my $newdevid = '';
+
+       opendir(MYDH, "$path_id") or die("cannot open $path_id: $! \n");
+       @sellinks = grep(!/\-part\d\d?$/, grep(!/^\.\.?$/, readdir(MYDH)));
+       @sellinks = sort(@sellinks);
+       closedir(MYDH);
+
+       foreach $_idlink (@sellinks) {
+               chomp $_idlink;
+               if(not $_idlink =~ /^usb/ and length($_idlink) > 10) {
+                       $_actlink = readlink("$path_id/$_idlink");
+                       $_actlink =~ s{\.\./\.\./}{/dev/};
+                       if($opt_v) { print "** try: $_actlink => $_idlink \n"; }
+                       
+                       # stop if we find the right link...
+                       if($_actlink eq $olddev) {
+                               $newdevid = $_idlink;
+                               if($opt_v) { print "** convert: $_actlink => $path_id/$_idlink \n\n"; }
+                               last;
+                       }
+               }
+       }
+
+       if(not $newdevid) {
+               if($opt_v) { print "W: $olddev not converted: link not useful\n\n"; }
+       }
+       
+       return ($newdevid);
 }
 
-if ($liloconf_exists) 
-{
-    # 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.
-
-    input("high","liloconfig/liloconf_exists");
-    go();
-
-    if ($liloconf_incompatible) 
-    {
-       input("high","liloconfig/liloconf_incompatible");
-       go();
-       exit(1);
-    }
-    
-    set("liloconfig/use_current_lilo","true");
-    input("high","liloconfig/use_current_lilo");
-    go();
-    ($ret,$val)=get("liloconfig/use_current_lilo");
-    if ($val eq "true")
-    {
-       input("high","liloconfig/lilo_warning");
-       go();
-       stop();
-       &safe_system("/sbin/lilo -v");
-       if ( $? == 0 ) 
-       {
-           exit(0);
+sub convert_boot_device {
+
+       my $found = 1;
+       my $boot_disk = '';
+       my $boot_link;
+       # global variables: $boot_dev, $boot_id
+
+       if (-b $root_dev) {
+               if ($root_dev =~ /\/dev\/md/) {
+                       # search if the found partition is a raid volume
+                       $boot_disk = check_raid($root_dev);
+               }
+               else {
+                       # find the right block device name
+                       $boot_disk = $root_dev;
+                       $boot_disk =~ s/\d+$//;
+               }
+
+               if (-b $boot_disk) {
+                       # set global variable boot_dev
+                       $boot_dev = $boot_disk;
+               }
+               else { 
+                       print "E: boot device $boot_disk does not exist! \n";
+                       $found = 0;
+               }
        }
-       input("high","liloconfig/lilo_error");
-       go();
-       exit(1);
-    } 
-    else 
-    {
-        set("liloconfig/wipe_old_liloconf","false");
-       input("high","liloconfig/wipe_old_liloconf");
-       go();
-       ($ret,$val)=get("liloconfig/wipe_old_liloconf");
-       if($val eq "true")
-       {
-           rename($LILOCONF, "$LILOCONF.OLD") or die "liloconfig: couldn't save old $LILOCONF as $LILOCONF.OLD: $!\n";
+       else {
+               print "E: could not find root device $root_dev! \n";
+               $found = 0;
        }
-       else 
-       {
-           input("high","liloconfig/no_changes");
-           go();
-           exit(0);
+
+       if ($found) {
+               if($opt_v) { print "Convert boot option $boot_disk into DISK ID\n"; }
+               $boot_id = $idpath . "/" . find_id_link($boot_disk,$idpath);
+
+               if(not -l "$boot_id") {
+                       if($opt_v) { print "W: could not find DISK ID for $boot_disk!\n"; }
+                       ## not so important, than using boot_dev in lilo.conf
+                       #$found = 0;
+               }
        }
-    }
-}
 
-# ASSERT: that we get here only if there is no lilo.conf or the user
-# asked us to wipe out the old one...
-# We make checks for broken fstabs and odd devices only if we are 
-# going to try to write a lilo.conf for the user.
-if ($fstab_broken) 
-{
-    input("high","liloconfig/fstab_broken");
-    go();
-    exit(1);
+       return $found;
 }
 
-if ($odd_fstab) 
-{
-    subst("liloconfig/odd_fstab","device",$device);
-    input("high","liloconfig/odd_fstab");
-    go();
-    exit(1);
-}
+sub check_raid {
+       
+       my $part = $_[0];
+       my $mdname;
+       my $md;
+       my @devices;
 
-input("high","liloconfig/instruction");
-go();
-
-# Flag so we can print STDERR a warning if we fell out the bottom of the config
-# without having run lilo at all.
-$lilorun = 0; $madeactive = 0;
-
-
-subst("liloconfig/install_from_root_device","device",$device);
-set("liloconfig/install_from_root_device","false");
-input("high","liloconfig/install_from_root_device");
-go();
-($ret,$val)=get("liloconfig/install_from_root_device");
-
-if($val eq "true")
-{
-    umask(077);
-    open(CONF, ">$LILOCONF") or die "Couldn't open $LILOCONF for writing: $!\n";
-    if (!chown(0, 0, "$LILOCONF")) 
-    {
-       die "Couldn't make $LILOCONF owned by root.root: $!\n" unless $DEBUG;
-
-       # Following message is only shown if $DEBUG is set. So, I do not care
-       # about templating it. Let it goes into STDERR. YMMV. <arturcz@hell.pl>
-       print STDERR "Oops, couldn't make $LILOCONF owned by root.root. Since you\n";
-       print STDERR "have set the DEBUG flag, I'm going to assume this is because\n";
-       print STDERR "you're running liloconfig as a normal user, and continue anyway.\n";
-    }
-    print CONF @header;
-    input("high","liloconfig/install_from_root_device");
-    go();
-    ($ret,$val)=get("liloconfig/install_from_root_device");
-    if($val eq "true")
-    {
-       print CONF "# This allows booting from any partition on disks with more than 1024\n"; 
-       print CONF "# cylinders.\n";
-       print CONF "lba32\n";
-       print CONF "\n";
-    }
-    @middle_boilerplate = &get_images;
-    @bmp_boilerplate = &get_bitmap;
-
-    print CONF @bootheader, "boot=".$device, "\n", @rootheader, "root=".$device, "\n", @bmp_boilerplate, @boilerplate1, @middle_boilerplate, @boilerplate2;
-    
-    close(CONF) or die "Couldn't close $LILOCONF: $!\n";
-    
-    &safe_system("/sbin/lilo");
-    if ($? != 0) 
-    {
-       input("high","liloconfig/lilo_error");
-       go();
-       exit(1);
-    }
-    $lilorun = 1;
+       # check if the found partition is a raid volume
+       if($part =~ /\/dev\/md/)
+       {
+               $mdname = $part;
+               $mdname =~ s/\/dev\///;
+               $mdname =~ s/\///;
+               $md = `grep $mdname /proc/mdstat`;
+       
+               @devices = split(" ", $md);
+               @devices = sort(@devices[4..$#devices]);
+               $part = "/dev/" . $devices[0];
+               $part =~ s/\[.*$//;
+
+       }
+       return $part;
 }
 
+sub write_lilo_conf {
+       
+       my @status;
+       my $exit = copy_template();
 
-subst("liloconfig/install_mbr","disk",$disk);
-set("liloconfig/install_mbr","false");
-input("high","liloconfig/install_mbr");
-go();
-($ret,$val)=get("liloconfig/install_mbr");
-if($val eq "true")
-{
-    &safe_system("install-mbr $disk");
-    if ($? != 0) 
-    {
-       input("high","liloconfig/mbr_error");
-       go();
-       exit(1);
-    }
-}
+       if (not $exit) {
+               # create lilo.conf.new
+               write_boot_option();
+               write_image_config();
+       }
 
-subst("liloconfig/make_active_partition","device",$device);
-input("high","liloconfig/make_active_partition");
-go();
-($ret,$val)=get("liloconfig/install_mbr");
-if($val eq "true")
-{
-    my $part_num = $partition;
-    $part_num =~ s/^.*[a-z]//;
-    print STDERR "Activating Partition $part_num on disk $disk.\n";
-    &safe_system("/sbin/activate $disk $part_num");
-    if ($? != 0) 
-    {
-       input("high","liloconfig/activate_error");
-       go();
-       exit(1);
-    }
-    $madeactive = 1;
+       if (-f $liloconf and not -f $liloconfold) {
+               # move old lilo.conf to lilo.conf.old
+               @status = stat($liloconf);
+               move ($liloconf, $liloconfold) or die "Cannot rename file: $!\n";
+               utime ($status[9],$status[9],$liloconfold);
+               chmod (0600,$liloconfold);
+               print "Old file moved to: $liloconfold \n";
+       }
+       if (-f $liloconfnew) {
+               move ($liloconfnew, $liloconf) or die "Cannot move file: $!\n";
+               chmod (0600,$liloconf);
+               print "New file created as: $liloconf \n";
+               print "Now you must execute '/sbin/lilo' to " . 
+                     "activate this new configuation!\n\n";
+       }
+       else {
+               print "E: Cannot find temporary file $conftmp_1!\n";
+               $exit = 1;
+       }
+       
+       return $exit;
 }
 
-# Trailer: summarise what we've done
-print STDERR "\n";
-if (! $lilorun) 
-{
-    print STDERR "WARNING: you will have to set up LILO manually to ensure that\n";
-    print STDERR "      your system can be booted successfully!\n";
-    print STDERR "You can rerun liloconfig at any time if you change your mind and\n";
-    print STDERR "wish to use the default configuration.\n";
-} 
-elsif ($madeactive) 
-{
-    # LILO was run and Linux partition made active
-    print STDERR "LILO successfully configured; Linux will be booted by default.\n";
-    print STDERR "If you installed the master boot record, you can boot a different\n";
-    print STDERR "OS by holding down the shift key as the system boots, and then\n";
-    print STDERR "pressing the key corresponding to the partition containing that\n";
-    print STDERR "OS when you see the \"1234F:\" prompt.\n";
+sub copy_template {
+
+       my $endreached = 0;
+       my $exit = 0;
+       
+       # copy template config
+       if (-f $template) {
+               system("gzip -d -c $template >$conftmp_1") if ($template =~ /\.gz$/);
+               system("cat $template >$conftmp_1") if ($template =~ /\.conf$/);
+
+               open(CONFTMP1, "<$conftmp_1") or die "$prog: couldn't open $conftmp_1: $!\n";
+               open(CONFTMP2, ">$conftmp_2") or die "$prog: couldn't open $conftmp_2: $!\n";
+
+               while (<CONFTMP1>) {
+                       if (/first\ example/) {
+                               $endreached = 1;
+                       }
+                       unless ($endreached) {
+                               print CONFTMP2 $_;
+                       }
+               }
+               close(CONFTMP1) or die "$prog: couldn't close $conftmp_1: $!\n";;
+               close(CONFTMP2) or die "$prog: couldn't close $conftmp_2: $!\n";;
+       }
+       else {
+               open(CONFTMP2, ">$conftmp_2") or die "$prog: couldn't open $conftmp_2: $!\n";
+               print CONFTMP2 "# /etc/lilo.conf
+
+### LILO global section ###
+
+#large-memory
+lba32
+boot = /dev/sda
+map = /boot/map
+install = menu
+menu-scheme = Wb:Yr:Wb:Wb
+prompt
+timeout = 100
+vga = normal
+#default = Linux
+
+### LILO per-image section ###
+
+"; 
+               close(CONFTMP2) or die "$prog: couldn't close $conftmp_2: $!\n";;
+       }
+       
+       return $exit;
 }
-else
-{
-    my $part_num = $partition;
-    $part_num =~ s/^.*[a-z]//;
-    # LILO run, but Linux partition not made active
-    print STDERR "OK. If you installed the master boot record, and the partition\n";
-    print STDERR "boot record, you may boot Linux by holding down the shift key\n";
-    print STDERR "as the system boots, and then pressing the $part_num key\n";
-    print STDERR "when you see the \"1234F:\" prompt.\n";
+
+sub write_boot_option {
+       
+       my $oldline = '';
+       my $newline = '';
+       my $ok = 0;
+
+       open(MYFH_NEW, "> $liloconfnew") or die "Cannot open file: $!";
+       open(MYFH_TMP, "< $conftmp_2") or die "Cannot read file: $!";
+
+       while (<MYFH_TMP>) {
+               # line read from MYFH_TMP
+               $oldline = $_;
+
+               if (/^boot/ and $ok == 0) {
+                       if ($boot_id) {
+                               $oldline = "#boot = $boot_dev\n";
+                               $newline = "boot = $boot_id\n";
+                               print MYFH_NEW $oldline;
+                               if($opt_v) { print $oldline; }
+                       }
+                       else {
+                               $oldline = "boot = $boot_dev\n";
+                       }
+                       print MYFH_NEW $newline;
+                       if($opt_v) { print $newline; }
+                       if($opt_v) { print "\n"; }
+
+                       # convert only one time
+                       $ok = 1;
+               }
+               else {
+                       print MYFH_NEW $oldline;
+               }
+       }
+       close(MYFH_TMP);
+       close(MYFH_NEW);
 }
 
-print STDERR "\n";
-print STDERR "For more information about LILO, see the documentation in\n";
-print STDERR "/usr/share/doc/lilo/. For details about the MBR, see also\n";
-print STDERR "/usr/share/doc/mbr/.\n";
+sub write_image_config {
+
+       my $image;
+       my $initrd;
+       my $nr;
+       my $nr2;
+
+       # search for kernel image files
+       my @vmlinuz = readpipe("/bin/ls -t -1 /boot/vmlinuz-2* 2>/dev/null");
+
+       # append to new lilo.conf
+       open(MYFH_NEW, ">> $liloconfnew") or die "Cannot open file: $!";
+
+       # create some line for each kernel image
+       $nr = 0;
+       foreach $image (@vmlinuz) {
+               # search for kernel initrd file
+               chomp $image;
+               $initrd = $image;
+               $initrd =~ s/vmlinuz/initrd\.img/;
+               $nr2 = $nr + 1;
+
+                       print MYFH_NEW     'image = ' . $image . "\n";
+                       if($opt_v) { print 'image = ' . $image . "\n"; }
+               if ($nr == 0) {
+                       print MYFH_NEW     "\t"  . 'label = "Linux"' . "\n";
+                       if($opt_v) { print "\t"  . 'label = "Linux"' . "\n"; }
+               }
+               elsif ($nr == 1) {
+                       print MYFH_NEW     "\t"  . 'label = "Linux Old"' . "\n";
+                       if($opt_v) { print "\t"  . 'label = "Linux Old"' . "\n"; }
+               }
+               if ($root_id) {
+                       print MYFH_NEW     "\t"  . '#root = ' . $root_dev . "\n";
+                       if($opt_v) { print "\t"  . '#root = ' . $root_dev . "\n"; }
+                       print MYFH_NEW     "\t"  . 'root = "' . $root_id . '"' . "\n";
+                       if($opt_v) { print "\t"  . 'root = "' . $root_id . '"' . "\n"; }
+               }
+               else {
+                       print MYFH_NEW     "\t"  . 'root = ' . $root_dev . "\n";
+                       if($opt_v) { print "\t"  . 'root = ' . $root_dev . "\n"; }
+               }
+                       print MYFH_NEW     "\t"  . 'read-only' . "\n";
+                       if($opt_v) { print "\t"  . 'read-only' . "\n"; }
+                       print MYFH_NEW     "#\t" . 'restricted' . "\n";
+                       if($opt_v) { print "#\t" . 'restricted' . "\n"; }
+                       print MYFH_NEW     "#\t" . 'alias = ' . "$nr2" . "\n";
+                       if($opt_v) { print "#\t" . 'alias = ' . "$nr2" . "\n"; }
+                       print MYFH_NEW     "#\t" . 'optional' . "\n";
+                       if($opt_v) { print "#\t" . 'optional' . "\n"; }
+               if (-f $initrd) {
+                       print MYFH_NEW     "\t"  . 'initrd = ' . $initrd . "\n";
+                       if($opt_v) { print "\t"  . 'initrd = ' . $initrd . "\n"; }
+               }
+                       print MYFH_NEW     "\n";
+                       if($opt_v) { print "\n"; }
+
+               $nr++;
+               last if ($nr > 1);
+       }
+
+       close(MYFH_NEW);
+}              
+               
+       
+main();
+
+__END__
+
+
+=head1 NAME
+
+liloconfig - create new lilo.conf file (with diskid and uuid)
+
+=head1 SYNOPSIS
+
+liloconfig [-h] [-v] [-f] [lilo.conf]
+
+=head1 DESCRIPTION
+
+liloconfig is an simple program for creating a new lilo.conf file.
+After creating the new configuration file you must execute '/sbin/lilo'.
+
+liloconfig use the lilo.example.conf file as template. In the final
+lilo.conf file you find many useful comments for custom changes.
+
+=head1 EXAMPLES
+
+Lines in the configuration file /etc/lilo.conf:
+
+  ### LILO global section ###
+
+  #large-memory
+  lba32
+  boot = /dev/sda
+  map = /boot/map
+  install = menu
+  menu-scheme = Wb:Yr:Wb:Wb
+  prompt
+  timeout = 100
+  vga = normal
+  #default = Linux
+
+  ### LILO per-image section ###
+
+  #boot = /dev/sda
+  boot = /dev/disk/by-id/ata-SAMSUNG_SV1604N_S01FJ10X999999
+
+  image = /boot/vmlinuz-2.6.32-5book-686
+      label = "Linux"
+      #root = /dev/sda1
+      root = "UUID=18843936-00f9-4df0-a373-000d05a5dd44"
+      read-only
+  #   restricted
+  #   alias = 1
+  #   optional
+      initrd = /boot/initrd.img-2.6.32-5book-686
+
+  image = /boot/vmlinuz-2.6.32-5-686
+      label = "Linux Old"
+      #root = /dev/sda1
+      root = "UUID=18843936-00f9-4df0-a373-000d05a5dd44"
+      read-only
+  #   restricted
+  #   alias = 2
+  #   optional
+      initrd = /boot/initrd.img-2.6.32-5-686
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-h>
+
+Print a brief help.
+
+=item B<-v>
+
+Print verbose messages.
+
+=item B<-f>
+
+Force overriding existing lilo.conf.
+
+=back
+
+=head1 AUTHOR
+
+B<liloconfig> was written by Joachim Wiedorn.
 
-exit(0);
+=cut