[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

lilo.conf -> menu.lst



  As a result of the recent thread on Grub, I've been working on trying to get
an automated process set up for converting as much information as possible from
lilo.conf files to Grub's menu.lst format. I have a rather basic filter working,
which will parse lilo.conf if you haven't done anything particularly odd
(backslash-escaping newlines, etc) and write as much of a Grub configuration
file as it can, given that there's no one-to-one mapping between Lilo config
options and Grub config options.  It ignores many possible config settings and
syntaxes of Lilo (lilo.conf's syntax is just way too hairy to parse this
late at night), but it seems to work for fairly 'basic' configurations.

  Hopefully this is an appropriate place to post it :-/  I've attached it to
this message; if you want to use this to create a menu.lst file, PLEASE go over
the file it generates to check for correctness.  It's unlikely you can zap the
hard drive, since I don't use the install= command, but you could cause a
major headache for yourself on your next reboot..
  Execute the script as "lilo2grub [infile [outfile]]" -- it defaults to reading
'./lilo.conf' and writing './menu.lst'.  '-' can be used as outfile (but not
infile yet.  I'm lazy. :) )

  There are two files in the script.  One, liloconf, exports routines to parse
lilo.conf files.  This is where I need to add support for the full syntactic
spectrum that lilo allows.  The other is the script itself, which performs
various checks on the data in lilo.conf and writes a menu.lst file with the
information.

  Daniel

-- 
  "People would panic?"
  "Very briefly, I'm afraid."

     -- The dangers of colliding with a star examined;
           Terry Pratchett, _The Light Fantasic_
# lilocfg.py
#
#  A module which parses and creates lilo configuration files.
# (well, creation is not working yet. -- DNB

import string

class lilogroup:
    def __init__(self,type,where,conffile):
	'type=="image" or "other", where is the parameter to the command.'
	self.type=type
	self.where=where
	self.options={}
	self.conffile=conffile

    def getoption(self,option):
	if self.options.has_key(option):
	    return self.options[option]
	else:
	    return self.conffile.getoption(option)

class liloconf:
    """Sort of parses a lilo config file.  The syntax is way too hairy
    to really handle correctly, but I think 99% of people only use the sane
    bits of it anyway.  Anyone wishing to write a complete config file parser
    for lilo is free to do so.. :-)"""
    def __init__(self,filename='/etc/lilo.conf'):
	self.__dict__['options']={}
	self.groups=[]

	self.filename=filename
	cfgfile=open(self.filename,'r')

	group=None
	line=cfgfile.readline()
	while line <> "":
	    split=map(string.strip,string.split(string.split(line,'#',1)[0],'=',1))
	    if len(split) > 1:
		# A name=val style declaration
		name=string.lower(split[0])
		val=split[1]
	    else:
		# A flag variable
		name=string.lower(split[0])
		val=1

	    if name=='image' or name=='other':
		group=lilogroup(name,val,self)
		self.groups.append(group)
	    elif group == None:
		self.options[name]=val
	    else:
		group.options[name]=val

	    line=cfgfile.readline()

    def getoption(self,option):
	if self.options.has_key(option):
	    return self.options[option]
	else:
	    return None
#!/usr/bin/python
#
#  A simple program to convert LILO configuration files to GRUB menu.lst files.

import sys
import os

import re
import string

mountedre=re.compile('^(\S+) on (\S+)')

import liloconf

infilename='lilo.conf'
outfilename='menu.lst'

if len(sys.argv)>1:
    infilename=sys.argv[1]
    if len(sys.argv)>2:
	outfilename=sys.argv[2]

if outfilename == '-':
    outfile=sys.stdout
else:
    outfile=open('%s.new'%outfilename,'w')
# Do things nicely to avoid corrupted config files..

lilocfg=liloconf.liloconf(infilename)

mounted={}
for i in map(lambda x:tuple(mountedre.match(x).groups()),os.popen('mount','r').readlines()):
    mounted[i[1]]=i[0]
def findfs(filename,mounted=mounted):
    """Returns a tuple containing the device in the first item and the file's
    location on that filesystem in the second.  It assumes that the file
    is not itself a mount point (ie, it's a regular file) for convenience.
    Doesn't use ismount(), instead calls mount to check the list of mounted
    filesystems."""
    loc='/'+os.path.basename(filename)
    filename=os.path.dirname(filename)
    while not mounted.has_key(filename) and filename <> '/':
	loc='/%s%s'%(os.path.basename(filename),loc)
	filename=os.path.dirname(filename)
    return (filename,loc)

def dev2grub(device):
    dev=string.lower(device)
    if dev[:7]=='/dev/hd':
	devnum=ord(dev[7])-ord('a')
	devsub=ord(dev[8])-ord('1')
	return '(hd%i,%i)'%(devnum,devsub)
    elif dev[:7]=='/dev/fd':
	devnum=ord(dev[7])-ord('a')
	devsub=ord(dev[8])-ord('1')
	return '(hd%i,%i)'%(devnum,devsub)
    else:
	raise 'UnknownDeviceType',device

outfile.write('# GRUB menu.lst file autogenerated from %s by lilo2grub\n'%infilename)
if lilocfg.getoption('delay') <> None:
    delay=int(lilocfg.getoption('delay'))/10
    if delay==0 and lilocfg.getoption('delay')>0:
	delay=1 # Hack around the resolution difference..
    outfile.write('timeout=%i\n'%delay)
else:
    if lilocfg.getoption('timeout') <> None:
	delay=int(lilocfg.getoption('timeout'))/10
	if delay==0 and lilocfg.getoption('timeout')>0:
	    delay=1
	outfile.write('timeout=%i\n'%delay)
    elif lilocfg.getoption('prompt') == None:
	outfile.write('timeout= 0\n')
if lilocfg.getoption('default') <> None:
    outfile.write('default=%i\n'%map(lambda x:x.getoption('label'),lilocfg.groups).index(lilocfg.getoption('default')))

for group in lilocfg.groups:
    if group.getoption('label') <> None:
	outfile.write('title=%s\n'%group.getoption('label'))
    else:
	outfile.write('title=%s at %s\n'%(group.type,group.where))

    if group.type=='other':
	if group.getoption('loader') <> None:
	    # Note: this may introduce dependencies on LILO files.  Hmm..
	    loader=group.getoption(loader)
	else:
	    loader='/boot/chain.b'

	filesys,loc=findfs(loader)

	outfile.write('  root=%s\n'%dev2grub(mounted[filesys]))
	outfile.write('  chainloader=%s\n'%loc)
    elif group.type=='image':
	# Write a Linux kernel image definition..
	options=''
	if group.getoption('append') <> None:
	    options=group.getoption('append')+options

	if group.getoption('initrd') <> None:
	    # ?????
	    pass

	if group.getoption('ramdisk') <> None:
	    # ?????
	    pass

	if group.getoption('root') <> None:
	    options='root=%s %s'%(group.getoption('root'),options)

	if group.getoption('literal') <> None:
	    options=group.getoption('literal')

	filesys,loc=findfs(group.where)

	outfile.write('  root=%s\n'%dev2grub(mounted[filesys]))
	outfile.write('  kernel=%s %s\n'%(loc,options))
    outfile.write('  boot\n')

if outfilename <> '-':
    os.rename('%s.new'%outfile,outfilename)

Reply to: