summaryrefslogtreecommitdiffstats
path: root/perl-install/commands.pm
Commit message (Expand)AuthorAgeFilesLines
* make perl_checker happyPascal Rigaux2002-08-051-1/+1
* s/__END__/1;Thierry Vignaud2002-08-051-1/+1
* kill "wonderful perl"Thierry Vignaud2002-08-051-5/+1
* - the old $o->{keyboard} is now $o->{keyboard}{KEYBOARD}Pascal Rigaux2002-08-011-1/+1
* make new perl_checker happyPascal Rigaux2002-07-311-1/+2
* make new perl_checker happy (and that's not easy!)Pascal Rigaux2002-07-311-10/+10
* remove "$_ =~ " (as detected by new perl_checker)Pascal Rigaux2002-07-171-1/+1
* adapt to new modprobe.pmPascal Rigaux2002-07-061-1/+1
* adapt to new modules.pmPascal Rigaux2002-07-041-2/+2
* make lspci a full pci probe instead of safe pci probe.Francois Pons2001-09-181-1/+1
* use new mkdir_p, rm_rf and cp_af from MDK::CommonPascal Rigaux2001-09-161-14/+2
* (sync): (re-?)addPascal Rigaux2001-08-031-0/+2
* do not export sync, keep it in common (esp. so that it doesn't conflict with ...Pascal Rigaux2001-07-251-1/+1
* move to MDK::Common, bool->to_boolPascal Rigaux2001-07-241-6/+7
* fix syntaxPascal Rigaux2001-07-241-1/+1
* removed/renamed unused/seldom-used functionsPascal Rigaux2001-07-241-2/+2
* generalize the use of chomp_ as the functional alternative to chomp (and work...Pascal Rigaux2001-07-241-2/+2
* (grep_): add a missing semi-colonPascal Rigaux2001-06-111-1/+1
* fixed log of packdrake.Francois Pons2001-04-121-2/+1
* - move report_bug in install_anyPascal Rigaux2001-04-051-29/+2
* fix typoPascal Rigaux2001-03-281-2/+1
* add fstab in the logPascal Rigaux2001-03-281-2/+6
* fixed live update between GLIBC 2.1 and GLIBC 2.2. should work for otherFrancois Pons2001-03-121-4/+4
* (loadkeys): createdPascal Rigaux2001-03-121-0/+7
* *** empty log message ***Stew Benedict2001-03-031-1/+1
* (more): handle 'q' to quitPascal Rigaux2001-02-241-1/+5
* call /usr/bin/insmod_ with full pathPascal Rigaux2001-02-221-1/+1
* (head_tail): fix usagePascal Rigaux2001-02-051-1/+1
* removed need of packdrake binaryFrancois Pons2001-01-051-1/+6
* report_bug: created, returns a stringPascal Rigaux2000-12-081-9/+12
* removed foreach (<... which are eating memoryFrancois Pons2000-11-141-3/+5
* no_commentPascal Rigaux2000-10-041-1/+1
* no_commentPascal Rigaux2000-10-021-1/+2
* no_commentPascal Rigaux2000-09-261-0/+1
* no_commentPascal Rigaux2000-09-241-1/+1
* no_commentPascal Rigaux2000-09-141-1/+1
* no_commentPascal Rigaux2000-09-121-1/+1
* no_commentPascal Rigaux2000-09-111-0/+1
* no_commentPascal Rigaux2000-09-061-1/+2
* no_commentPascal Rigaux2000-09-011-0/+1
* *** empty log message ***Francois Pons2000-08-241-1/+1
* no_commentPascal Rigaux2000-08-041-7/+2
* no_commentPascal Rigaux2000-07-231-8/+6
* no_commentPascal Rigaux2000-06-281-9/+38
* *** empty log message ***Francois Pons2000-05-291-1/+5
* *** empty log message ***Francois Pons2000-05-251-1/+1
* no_commentPascal Rigaux2000-04-191-1/+1
* no_commentPascal Rigaux2000-04-181-2/+3
* no_commentPascal Rigaux2000-04-171-5/+3
* *** empty log message ***Francois Pons2000-03-171-0/+1
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617

package install2; # $Id$

use diagnostics;
use strict;
use vars qw($o $version);

#-######################################################################################
#- misc imports
#-######################################################################################
use steps;
use common;
use install_any qw(:all);
use install_steps;
use commands;
use lang;
use keyboard;
use mouse;
use fsedit;
use devices;
use partition_table qw(:types);
use modules;
use detect_devices;
use run_program;
use any;
use log;
use fs;
#-$::corporate=1;


#-#######################################################################################
#-$O
#-the big struct which contain, well everything (globals + the interactive methods ...)
#-if you want to do a kickstart file, you just have to add all the required fields (see for example
#-the variable $default)
#-#######################################################################################
$o = $::o = {
#    bootloader => { linear => 0, lba32 => 1, message => 1, timeout => 5, restricted => 0 },
    mkbootdisk => 1, #- no mkbootdisk if 0 or undef, find a floppy with 1, or fd1
#-    packages   => [ qw() ],
    partitioning => { clearall => 0, eraseBadPartitions => 0, auto_allocate => 0 }, #-, readonly => 0 },
    security => 2,
    authentication => { md5 => 1, shadow => 1 },
    lang         => 'en_US',
    isUpgrade    => 0,
    toRemove     => [],
    toSave       => [],
#-    simple_themes => 1,

    timezone => {
#-                   timezone => "Europe/Paris",
#-                   UTC      => 1,
                },
#-    superuser => { password => 'a', shell => '/bin/bash', realname => 'God' },
#-    user => { name => 'foo', password => 'bar', home => '/home/foo', shell => '/bin/bash', realname => 'really, it is foo' },

#-    keyboard => 'de',
#-    display => "192.168.1.19:1",
    steps        => \%steps::installSteps,
    orderedSteps => \@steps::orderedInstallSteps,

#- for the list of fields available for user and superuser, see @etc_pass_fields in install_steps.pm
#-    intf => { eth0 => { DEVICE => "eth0", IPADDR => '1.2.3.4', NETMASK => '255.255.255.128' } },

#-step : the current one
#-prefix
#-mouse
#-keyboard
#-netc
#-methods
#-packages compss
#-printer haveone entry(cf printer.pm)

};


sub installStepsCall {
    my ($o, $auto, $fun, @args) = @_;
    $fun = "install_steps::$fun" if $auto;
    $o->$fun(@args);
}

#-######################################################################################
#- Steps Functions
#- each step function are called with two arguments : clicked(because if you are a
#- beginner you can force the the step) and the entered number
#-######################################################################################

#------------------------------------------------------------------------------
sub selectLanguage {
    my ($clicked, $ent_number, $auto) = @_;

    installStepsCall($o, $auto, 'selectLanguage', $ent_number == 1);

    addToBeDone {
	lang::write_langs($o->{prefix}, $o->{langs});
    } 'formatPartitions' unless $::g_auto_install;
    addToBeDone {
	lang::write($o->{prefix}, $o->{lang});
	keyboard::write($o->{prefix}, $o->{keyboard}, lang::lang2charset($o->{lang}));
    } 'installPackages' unless $::g_auto_install;
}

#------------------------------------------------------------------------------
sub selectMouse {
    my ($clicked, $ent_number, $auto) = @_;

    require pkgs;
    my ($first_time) = $ent_number == 1;

    add2hash($o->{mouse} ||= {}, mouse::read($o->{prefix})) if $o->{isUpgrade} && $first_time;

    installStepsCall($o, $auto, 'selectMouse', !$first_time || $clicked);

    addToBeDone { mouse::write($o->{prefix}, $o->{mouse}) } 'installPackages';
}

#------------------------------------------------------------------------------
sub setupSCSI {
    my ($clicked, $ent_number, $auto) = @_;
    installStepsCall($o, $auto, 'setupSCSI', $clicked);
}

#------------------------------------------------------------------------------
sub selectKeyboard {
    my ($clicked, $first_time, $auto) = ($_[0], $_[1] == 1, $_[2]);

    if ($o->{isUpgrade} && $first_time && $o->{keyboard_unsafe}) {
	my $keyboard = keyboard::read($o->{prefix});
	$keyboard and $o->{keyboard} = $keyboard;
    }
    return if !$::expert && !$clicked;

    installStepsCall($o, $auto, 'selectKeyboard', $clicked);
}

#------------------------------------------------------------------------------
sub selectInstallClass {
    my ($clicked, $ent_number, $auto) = @_;

    installStepsCall($o, $auto, 'selectInstallClass', $clicked);

    if ($o->{steps}{choosePackages}{entered} >= 1 && !$o->{steps}{installPackages}{done}) {
	installStepsCall($o, $auto, 'setPackages');
	installStepsCall($o, $auto, 'selectPackagesToUpgrade') if $o->{isUpgrade};
    }
    if ($o->{isUpgrade}) {
	@{$o->{orderedSteps}} = map { /setupSCSI/ ? ($_, "doPartitionDisks") : $_ }
	                        grep { !/doPartitionDisks/ } @{$o->{orderedSteps}};
	my $s; foreach (@{$o->{orderedSteps}}) {
	    $s->{next} = $_ if $s;
	    $s = $o->{steps}{$_};
	}
    }
}

#------------------------------------------------------------------------------
sub doPartitionDisks {
    my ($clicked, $ent_number, $auto) = @_;
    $o->{steps}{formatPartitions}{done} = 0;
    installStepsCall($o, $auto, 'doPartitionDisksBefore');
    installStepsCall($o, $auto, 'doPartitionDisks');
    installStepsCall($o, $auto, 'doPartitionDisksAfter');
}

sub formatPartitions {
    my ($clicked, $ent_number, $auto) = @_;

    $o->{steps}{choosePackages}{done} = 0;
    installStepsCall($o, $auto, 'choosePartitionsToFormat', $o->{fstab}) if !$o->{isUpgrade};
    installStepsCall($o, $auto, 'formatMountPartitions', $o->{fstab}) if !$::testing;

    mkdir "$o->{prefix}/$_", 0755 foreach 
      qw(dev etc etc/profile.d etc/rpm etc/sysconfig etc/sysconfig/console 
	etc/sysconfig/network-scripts etc/sysconfig/console/consolefonts 
	etc/sysconfig/console/consoletrans
	home mnt tmp var var/tmp var/lib var/lib/rpm var/lib/urpmi);
    mkdir "$o->{prefix}/$_", 0700 foreach qw(root root/tmp);

    any::rotate_logs($o->{prefix});

    require raid;
    raid::prepare_prefixed($o->{raid}, $o->{prefix});

    my $d = "/initrd/loopfs/lnx4win";
    if (-d $d) {
#-	install_any::useMedium(0);
	install_any::getAndSaveFile("lnx4win/$_", "$d/$_") foreach qw(ctl3d32.dll loadlin.exe linux.pif lnx4win.exe lnx4win.ico rm.exe uninstall.bat uninstall.pif);
    }

#-    chdir "$o->{prefix}"; was for core dumps

    #-noatime option for ext2 fs on laptops (do not wake up the hd)
    #-	 Do  not  update  inode  access times on this
    #-	 file system (e.g, for faster access  on  the
    #-	 news spool to speed up news servers).
    $o->{pcmcia} and $_->{options} = "noatime" foreach grep { isTrueFS($_) } @{$o->{fstab}};
}

#------------------------------------------------------------------------------
sub choosePackages {
    my ($clicked, $ent_number, $auto) = @_;
    require pkgs;

    #- always setPackages as it may have to copy hdlist files and depslist file.
    installStepsCall($o, $auto, 'setPackages');
    installStepsCall($o, $auto, 'selectPackagesToUpgrade') if $o->{isUpgrade} && $ent_number == 1;

    installStepsCall($o, $auto, 'choosePackages', $o->{packages}, $o->{compssUsers}, $ent_number == 1);
    log::l("compssUsersChoice's: ", join(" ", grep { $o->{compssUsersChoice}{$_} } keys %{$o->{compssUsersChoice}}));

    #- check pre-condition where base backage has to be selected.
    pkgs::packageFlagSelected(pkgs::packageByName($o->{packages}, 'basesystem')) or die "basesystem package not selected";

    #- check if there are package that need installation.
    $o->{steps}{installPackages}{done} = 0 if $o->{steps}{installPackages}{done} && pkgs::packagesToInstall($o->{packages}) > 0;
}

#------------------------------------------------------------------------------
sub installPackages {
    my ($clicked, $ent_number, $auto) = @_;

    installStepsCall($o, $auto, 'readBootloaderConfigBeforeInstall') if $ent_number == 1;

    installStepsCall($o, $auto, 'beforeInstallPackages');
    installStepsCall($o, $auto, 'installPackages');
    installStepsCall($o, $auto, 'afterInstallPackages');
}
#------------------------------------------------------------------------------
sub miscellaneous {
    my ($clicked, $ent_number, $auto) = @_;

    installStepsCall($o, $auto, 'miscellaneousBefore', $clicked);
    installStepsCall($o, $auto, 'miscellaneous', $clicked);

    addToBeDone {
	setVarsInSh("$o->{prefix}/etc/sysconfig/system", { 
            CLEAN_TMP => $o->{miscellaneous}{CLEAN_TMP},
            CLASS => $::expert && 'expert' || 'beginner',
            SECURITY => $o->{security},
	    META_CLASS => $o->{meta_class} || 'PowerPack',
        });
	substInFile { s/KEYBOARD_AT_BOOT=.*/KEYBOARD_AT_BOOT=yes/ } "$o->{prefix}/etc/sysconfig/usb" if detect_devices::usbKeyboards();

    } 'installPackages';
}

#------------------------------------------------------------------------------
sub summary {
    my ($clicked, $ent_number, $auto) = @_;
    installStepsCall($o, $auto, 'summary', $ent_number == 1);
}
#------------------------------------------------------------------------------
sub configureNetwork {
    my ($clicked, $ent_number, $auto) = @_;
    #- get current configuration of network device.
    require network;
    eval { network::read_all_conf($o->{prefix}, $o->{netc} ||= {}, $o->{intf} ||= {}) };
    installStepsCall($o, $auto, 'configureNetwork', $ent_number == 1, $clicked);
}
#------------------------------------------------------------------------------
sub installCrypto {
    my ($clicked, $ent_number, $auto) = @_;
    installStepsCall($o, $auto, 'installCrypto');
}
#------------------------------------------------------------------------------
sub configureServices {
    my ($clicked, $ent_number, $auto) = @_;
    installStepsCall($o, $auto, 'configureServices', $clicked);
}
#------------------------------------------------------------------------------
sub setRootPassword {
    my ($clicked, $ent_number, $auto) = @_;
    return if $o->{isUpgrade};

    installStepsCall($o, $auto, 'setRootPassword', $clicked);
    addToBeDone { install_any::setAuthentication($o) } 'installPackages';
}
#------------------------------------------------------------------------------
sub addUser {
    my ($clicked, $ent_number, $auto) = @_;
    return if $o->{isUpgrade} && !$clicked;

    installStepsCall($o, $auto, 'addUser', $clicked);
}

#------------------------------------------------------------------------------
sub createBootdisk {
    my ($clicked, $ent_number, $auto) = @_;
    modules::write_conf($o->{prefix});
    installStepsCall($o, $auto, 'createBootdisk', $ent_number == 1, $clicked);
}

#------------------------------------------------------------------------------
sub setupBootloader {
    my ($clicked, $ent_number, $auto) = @_;
    return if $::g_auto_install;

    modules::write_conf($o->{prefix});

    installStepsCall($o, $auto, 'setupBootloaderBefore') if $ent_number == 1;
    installStepsCall($o, $auto, 'setupBootloader', $ent_number-1 + $clicked*2); #- gore :-(

    local $ENV{DRAKX_PASSWORD} = $o->{bootloader}{password};
    local $ENV{DURING_INSTALL} = 1;
    run_program::rooted($o->{prefix}, "/usr/sbin/msec", $o->{security});
}
#------------------------------------------------------------------------------
sub configureX {
    my ($clicked, $ent_number, $auto) = @_;

    #- done here and also at the end of install2.pm, just in case...
    install_any::write_fstab($o);
    modules::write_conf($o->{prefix});

    require pkgs;
    installStepsCall($o, $auto, 'configureX', $clicked) if pkgs::packageFlagInstalled(pkgs::packageByName($o->{packages}, 'XFree86')) && !$o->{X}{disabled} || $clicked || $::testing;
}
#------------------------------------------------------------------------------
sub exitInstall {
    my ($clicked, $ent_number, $auto) = @_;
    installStepsCall($o, $auto, 'exitInstall', getNextStep() eq 'exitInstall');
}


#-######################################################################################
#- MAIN
#-######################################################################################
sub main {
    $SIG{__DIE__} = sub { chomp(my $err = $_[0]); log::l("warning: $err") };
    $SIG{SEGV} = sub { 
	my $msg = "segmentation fault: seems like memory is missing as the install crashes"; print "$msg\n"; log::l($msg);
	$o->ask_warn('', $msg);
	setVirtual(1);
	require install_steps_auto_install;
	install_steps_auto_install_non_interactive::errorInStep ();
    };
    $ENV{PERL_BADLANG} = 1;
    umask 022;

    $::isInstall = 1;
    $::expert = $::g_auto_install = 0;

#-    c::unlimit_core() unless $::testing;

    my ($cfg, $patch, @auto);
    my %cmdline; map { 
	my ($n, $v) = split '=';
	$cmdline{$n} = $v || 1;
    } split ' ', cat_("/proc/cmdline");

    my $opt; foreach (@_) {
	if (/^--?(.*)/) {
	    $cmdline{$opt} = 1 if $opt;
	    $opt = $1;
	} else {
	    $cmdline{$opt} = $_ if $opt;
	    $opt = '';
	}
    } $cmdline{$opt} = 1 if $opt;
    
    map_each {
	my ($n, $v) = @_;
	my $f = ${{
	    oem       => sub { $::oem = $v },
	    lang      => sub { $o->{lang} = $v },
	    flang     => sub { $o->{lang} = $v ; push @auto, 'selectLanguage' },
	    method    => sub { $o->{method} = $v },
	    pcmcia    => sub { $o->{pcmcia} = $v },
	    vga16     => sub { $o->{vga16} = $v },
	    vga       => sub { $o->{vga} = $v },
	    step      => sub { $o->{steps}{first} = $v },
	    expert    => sub { $::expert = $v },
	    fbeginner => sub { $::expert = 0; push @auto, 'selectInstallClass' },
	    fexpert   => sub { $::expert = 1; push @auto, 'selectInstallClass' },
	    desktop   => sub { $o->{meta_class} = 'desktop' },
	    firewall  => sub { $o->{meta_class} = 'firewall'; push @auto, 'selectInstallClass'},
	    lnx4win   => sub { $o->{lnx4win} = 1 },
	    readonly  => sub { $o->{partitioning}{readonly} = $v ne "0" },
	    display   => sub { $o->{display} = $v },
	    security  => sub { $o->{security} = $v },
	    live      => sub { $::live = 1 },
	    noauto    => sub { $::noauto = 1 },
	    test      => sub { $::testing = 1 },
            nopci     => sub { $::nopci = 1 },
	    patch     => sub { $patch = 1 },
	    defcfg    => sub { $cfg = $v },
	    newt      => sub { $o->{interactive} = "newt" },
	    text      => sub { $o->{interactive} = "newt" },
	    stdio     => sub { $o->{interactive} = "stdio"},
	    corporate => sub { $::corporate = 1 },
	    kickstart => sub { $::auto_install = $v },
	    auto_install => sub { $::auto_install = $v },
	    simple_themes => sub { $o->{simple_themes} = 1 },
	    useless_thing_accepted => sub { $o->{useless_thing_accepted} = 1 },
	    alawindows => sub { $o->{security} = 0; $o->{partitioning}{clearall} = 1; $o->{bootloader}{crushMbr} = 1 },
	    fdisk => sub { $o->{partitioning}{fdisk} = 1 },
	    g_auto_install => sub { $::testing = $::g_auto_install = 1; $o->{partitioning}{auto_allocate} = 1 },
	    nomouseprobe => sub { $o->{nomouseprobe} = $v },
	    blank         => sub { $o->{blank} = 1},
	    updatemodules => sub { $o->{updatemodules} = 1},
	}}{lc $n}; &$f if $f;
    } %cmdline;

    if ($::testing) {
	$ENV{SHARE_PATH} ||= "/export/Mandrake/mdkinst/usr/share";
	$ENV{SHARE_PATH} = "/usr/share" if !-e $ENV{SHARE_PATH};
    } else {
	$ENV{SHARE_PATH} ||= "/usr/share";
    }

    undef $::auto_install if $cfg;
    if ($::g_auto_install) {
	(my $root = `/bin/pwd`) =~ s|(/[^/]*){5}$||;
	symlinkf $root, "/tmp/image" or die "unable to create link /tmp/image";
	$o->{method} ||= "cdrom";
	$o->{mkbootdisk} = 0;
    }
    unless ($::testing || $::live) {
	symlink "rhimage", "/tmp/image"; #- for compatibility with old stage1
	unlink $_ foreach "/modules/modules.mar", "/sbin/stage1";
    }

    print STDERR "in second stage install\n";
    log::openLog(($::testing || $o->{localInstall}) && 'debug.log');
    log::l("second stage install running (", any::drakx_version(), ")");

    $o->{prefix} = $::testing ? "/tmp/test-perl-install" : $::live ? "" : "/mnt";
    $o->{root}   = $::testing ? "/tmp/root-perl-install" : "/";
    $o->{isUpgrade} = 1 if $::live;
    mkdir $o->{prefix}, 0755;
    mkdir $o->{root}, 0755;
    devices::make("/dev/zero"); #- needed by ddcxinfos

    #-  make sure we don't pick up any gunk from the outside world
    my $remote_path = "$o->{prefix}/sbin:$o->{prefix}/bin:$o->{prefix}/usr/sbin:$o->{prefix}/usr/bin:$o->{prefix}/usr/X11R6/bin";
    $ENV{PATH} = "/usr/bin:/bin:/sbin:/usr/sbin:/usr/X11R6/bin:$remote_path" unless $::g_auto_install;

    eval { spawnShell() };

    $o->{prefix} = $::testing ? "/tmp/test-perl-install" : $::live ? "" : "/mnt";
    mkdir $o->{prefix}, 0755;

    modules::load_deps(($::testing ? ".." : "") . "/modules/modules.dep");
    modules::read_stage1_conf($_) foreach "/tmp/conf.modules", "/etc/modules.conf";
    modules::read_already_loaded();

    #- done after module dependencies are loaded for "vfat depends on fat"
    if ($::auto_install) {
	require install_steps_auto_install;
	eval { $o = $::o = install_any::loadO($o, $::auto_install) };
	if ($@) {
	    if ($o->{useless_thing_accepted}) { #- Pixel's hack to be able to fail through
		log::l("error using auto_install, continuing");
		undef $::auto_install;
	    } else {
		print "Error using auto_install\n$@\n";
		install_steps_auto_install_non_interactive::errorInStep ();
	    }
	} else {
	    log::l("auto install config file loaded successfully");
	}
    }
    $o->{interactive} ||= 'gtk' if !$::auto_install;
 
    if ($o->{interactive} eq "gtk" && availableMemory < 22 * 1024) {
 	log::l("switching to newt install cuz not enough memory");
 	$o->{interactive} = "newt";
    }
    require"install_steps_$o->{interactive}.pm" if $o->{interactive}; #- no space to skip perl2fcalls

 
    eval { $o = $::o = install_any::loadO($o, "patch") } if $patch;
    eval { $o = $::o = install_any::loadO($o, $cfg) } if $cfg;

    eval { modules::load("af_packet") };

    map_index {
	modules::add_alias("sound-slot-$::i", $_->{driver});
    } modules::get_that_type('sound');

    #- needed very early for install_steps_gtk
    modules::load_thiskind("usb"); 
    eval { ($o->{mouse}, @{$o->{wacom} = []}) = mouse::detect() } unless $o->{nomouseprobe} || $o->{mouse};

    lang::set($o->{lang}); #- mainly for defcfg

    $o->{allowFB} = listlength(cat_("/proc/fb"));

    my $VERSION = cat__(install_any::getFile("VERSION")) or do { print "VERSION file missing\n"; sleep 5 };
    $o->{lnx4win} = 1 if $VERSION =~ /lnx4win/i;
    $o->{meta_class} = 'desktop' if $VERSION =~ /desktop/i;
    $o->{meta_class} = 'firewall' if $VERSION =~ /firewall/i;
    if ($::oem) {
	$o->{partitioning}{use_existing_root} = 1;
	$o->{partitioning}{auto_allocate} = 1;
	$o->{compssListLevel} = 4;
	push @auto, 'selectInstallClass', 'doPartitionDisks', 'choosePackages', 'configureTimezone', 'exitInstall';
    }

    foreach (@auto) {
	my $s = $o->{steps}{/::(.*)/ ? $1 : $_} or next;
	$s->{auto} = $s->{hidden} = 1;
    }

    my $o_;
    while (1) {
    	$o_ = $::auto_install ?
    	  install_steps_auto_install->new($o) :
    	    $o->{interactive} eq "stdio" ?
    	  install_steps_stdio->new($o) :
    	    $o->{interactive} eq "newt" ?
    	  install_steps_newt->new($o) :
    	    $o->{interactive} eq "gtk" ?
    	  install_steps_gtk->new($o) :
    	    die "unknown install type";
	$o_ and last;

	$o->{interactive} = "newt";
	require install_steps_newt;
    }
    $::o = $o = $o_;

    if (-e '/tmp/network') {
	require network;
	#- get stage1 network configuration if any.
	log::l('found /tmp/network');
	$o->{netc} ||= network::read_conf('/tmp/network');
	if (my ($file) = glob_('/tmp/ifcfg-*')) {
	    log::l("found network config file $file");
	    my $l = network::read_interface_conf($file);
	    $o->{intf} ||= { $l->{DEVICE} => $l };
	}
	if (-e '/etc/resolv.conf') {
	    my $file ='/etc/resolv.conf';
	    log::l("found network config file $file");
	    add2hash($o->{netc}, network::read_resolv_conf($file));
	}
    }

    #-the main cycle
    my $clicked = 0;
    MAIN: for ($o->{step} = $o->{steps}{first};; $o->{step} = getNextStep()) {
	$o->{steps}{$o->{step}}{entered}++;
	$o->enteringStep($o->{step});
	$o->{steps}{$o->{step}}{icon} and $o->{icon} = $o->{steps}{$o->{step}}{icon};
	eval {
	    &{$install2::{$o->{step}}}($clicked || $o->{steps}{$o->{step}}{noauto},
				       $o->{steps}{$o->{step}}{entered},
				       $clicked ? 0 : $o->{steps}{$o->{step}}{auto});
	};
	my $err = $@;
	$o->kill_action;
	$clicked = 0;
	if ($err) {
	    local $_ = $err;
	    $o->kill_action;
	    if (/^setstep (.*)/) {
		$o->{step} = $1;
		$o->{steps}{$1}{done} = 0;
		$clicked = 1;
		redo MAIN;
	    }
	    /^theme_changed$/ and redo MAIN;
	    unless (/^already displayed/) {
		eval { $o->errorInStep($_) };
		$o->{steps}{$o->{step}}{auto} = 0;
		$err = $@;
		$err and next;
	    }
	    $o->{step} = $o->{steps}{$o->{step}}{onError};
	    next MAIN unless $o->{steps}{$o->{step}}{reachable}; #- sanity check: avoid a step not reachable on error.
	    redo MAIN;
	}
	$o->{steps}{$o->{step}}{done} = 1;
	$o->leavingStep($o->{step});

	last if $o->{step} eq 'exitInstall';
    }
    install_any::clean_postinstall_rpms();
    install_any::log_sizes($o);
    install_any::ejectCdrom();
    install_any::remove_advertising($o);

    install_any::write_fstab($o);
    modules::write_conf($o->{prefix});

    #- to ensure linuxconf doesn't cry against those files being in the future
    foreach ('/etc/modules.conf', '/etc/crontab', '/etc/sysconfig/mouse', '/etc/sysconfig/network', '/etc/X11/fs/config') {
	my $now = time - 24 * 60 * 60;
	utime $now, $now, "$o->{prefix}/$_";
    }
    $::live or install_any::killCardServices();

    #- make sure failed upgrade will not hurt too much.
    install_steps::cleanIfFailedUpgrade($o);

    -e "$o->{prefix}/usr/sbin/urpmi.update" or eval { commands::rm("-rf", "$o->{prefix}/var/lib/urpmi") };

    #- mainly for auto_install's
    run_program::run("bash", "-c", $o->{postInstallNonRooted}) if $o->{postInstallNonRooted};
    run_program::rooted($o->{prefix}, "sh", "-c", $o->{postInstall}) if $o->{postInstall};

    #- have the really bleeding edge ddebug.log
    eval { commands::cp('-f', "/tmp/ddebug.log", "$o->{prefix}/root") };

    #- ala pixel? :-) [fpons]
    common::sync(); common::sync();

    log::l("installation complete, leaving");
    print "\n" x 80;
}

#-######################################################################################
#- Wonderful perl :(
#-######################################################################################
1;