package install_steps; # $Id$ use diagnostics; use strict; use vars qw(@filesToSaveForUpgrade); #-###################################################################################### #- misc imports #-###################################################################################### use common qw(:file :system :common :functional); use install_any qw(:all); use install_interactive; use partition_table qw(:types); use detect_devices; use modules; use run_program; use lang; use keyboard; use fsedit; use loopback; #use commands; use any; use log; use fs; @filesToSaveForUpgrade = qw( /etc/ld.so.conf /etc/fstab /etc/hosts /etc/conf.modules /etc/modules.conf ); #-###################################################################################### #- OO Stuff #-###################################################################################### sub new($$) { my ($type, $o) = @_; bless $o, ref $type || $type; return $o; } #-###################################################################################### #- In/Out Steps Functions #-###################################################################################### sub enteringStep { my ($o, $step) = @_; log::l("starting step `$step'"); } sub leavingStep { my ($o, $step) = @_; log::l("step `$step' finished"); if (-d "$o->{prefix}/root") { eval { commands::cp('-f', "/tmp/ddebug.log", "$o->{prefix}/root") }; install_any::g_auto_install(); } for (my $s = $o->{steps}{first}; $s; $s = $o->{steps}{$s}{next}) { #- the reachability property must be recomputed each time to take #- into account failed step. next if $o->{steps}{$s}{done} && !$o->{steps}{$s}{redoable}; my $reachable = 1; if (my $needs = $o->{steps}{$s}{needs}) { my @l = ref $needs ? @$needs : $needs; $reachable = min(map { $o->{steps}{$_}{done} || 0 } @l); } $o->{steps}{$s}{reachable} = 1 if $reachable; } $o->{steps}{$step}{reachable} = $o->{steps}{$step}{redoable}; while (my $f = shift @{$o->{steps}{$step}{toBeDone} || []}) { eval { &$f() }; $o->ask_warn(_("Error"), [ _("An error occurred, but I don't know how to handle it nicely. Continue at your own risk."), $@ ]) if $@; } } sub errorInStep($$) { print "error :(\n"; c::_exit(1) } sub kill_action {} sub set_help { 1 } #-###################################################################################### #- Steps Functions #-###################################################################################### #------------------------------------------------------------------------------ sub selectLanguage { my ($o) = @_; lang::set($o->{lang}); $o->{langs} ||= { $o->{lang} => 1 }; log::l("selectLanguage: pack_langs ", lang::pack_langs($o->{langs})); if ($o->{keyboard_unsafe} || !$o->{keyboard}) { $o->{keyboard_unsafe} = 1; $o->{keyboard} = keyboard::lang2keyboard($o->{lang}); selectKeyboard($o) if !$::live; } } #------------------------------------------------------------------------------ sub selectKeyboard { my ($o) = @_; keyboard::setup($o->{keyboard}); } #------------------------------------------------------------------------------ sub selectPath {} #------------------------------------------------------------------------------ sub selectInstallClass {} #------------------------------------------------------------------------------ sub setupSCSI { my ($o) = @_; modules::configure_pcmcia($o->{pcmcia}) if $o->{pcmcia}; modules::load_ide(); modules::load_thiskind('scsi|disk'); } #------------------------------------------------------------------------------ sub doPartitionDisksBefore { my ($o) = @_; if (cat_("/proc/mounts") =~ m|/\w+/(\S+)\s+/tmp/hdimage\s+(\S+)| && !$o->{partitioning}{readonly}) { $o->{stage1_hd} = { device => $1, type => $2 }; install_any::getFile("XXX"); #- close still opened filehandle eval { fs::umount("/tmp/hdimage") }; } eval { close *pkgs::LOG; eval { fs::umount("$o->{prefix}/proc") }; eval { fs::umount_all($o->{fstab}, $o->{prefix}) }; eval { sleep 1; fs::umount_all($o->{fstab}, $o->{prefix}) } if $@; #- HACK } if $o->{fstab} && !$::testing && !$::live; $o->{raid} ||= {}; } #------------------------------------------------------------------------------ sub doPartitionDisksAfter { my ($o) = @_; unless ($::testing) { partition_table::write($_) foreach @{$o->{hds}}; $_->{rebootNeeded} and $o->rebootNeeded foreach @{$o->{hds}}; } $o->{fstab} = [ fsedit::get_fstab(@{$o->{hds}}, $o->{raid}) ]; fsedit::get_root_($o->{fstab}) or die "Oops, no root partition"; if ($o->{partitioning}{use_existing_root}) { #- ensure those partitions are mounted so that they are not proposed in choosePartitionsToFormat fs::mount_part($_, $o->{prefix}) foreach grep { $_->{mntpoint} && !$_->{notFormatted} } @{$o->{fstab}}; } if (my $s = delete $o->{stage1_hd}) { my ($part) = grep { $_->{device} eq $s->{device} } @{$o->{fstab}}; $part->{isMounted} ? do { rmdir "/tmp/hdimage" ; symlinkf("$o->{prefix}$part->{mntpoint}", "/tmp/hdimage") } : eval { fs::mount($s->{device}, "/tmp/hdimage", $s->{type}); $part->{isMounted} = 1; }; } cat_("/proc/mounts") =~ m|(\S+)\s+/tmp/image nfs| && !grep { $_->{mntpoint} eq "/mnt/nfs" } @{$o->{manualFstab} || []} and push @{$o->{manualFstab}}, { type => "nfs", mntpoint => "/mnt/nfs", device => $1, options => "noauto,ro,nosuid,rsize=8192,wsize=8192" }; } #------------------------------------------------------------------------------ sub doPartitionDisks { my ($o) = @_; install_any::getHds($o); if ($o->{partitioning}{use_existing_root} || $o->{isUpgrade}) { # either one root is defined (and all is ok), or we take the first one we find my $p = fsedit::get_root_($o->{fstab}) || first(install_any::find_root_parts($o->{hds}, $o->{prefix})) or die; install_any::use_root_part($o->{fstab}, $p, $o->{prefix}); } if ($o->{partitioning}{auto_allocate}) { fsedit::auto_allocate($o->{hds}, $o->{partitions}); } } #------------------------------------------------------------------------------ sub ask_mntpoint_s { my ($o, $fstab) = @_; #- TODO: set the mntpoints my %m; foreach (@$fstab) { my $m = $_->{mntpoint}; next unless $m && $m ne 'swap'; #- there may be a lot of swap. $m{$m} and die _("Duplicate mount point %s", $m); $m{$m} = 1; #- in case the type does not correspond, force it to ext2 $_->{type} = 0x83 if $m =~ m|^/| && !isFat($_) && !isTrueFS($_); } 1; } sub rebootNeeded($) { my ($o) = @_; log::l("Rebooting..."); c::_exit(0); } sub choosePartitionsToFormat($$) { my ($o, $fstab) = @_; foreach (@$fstab) { $_->{mntpoint} = "swap" if isSwap($_); $_->{mntpoint} or next; add2hash_($_, { toFormat => $_->{notFormatted} }); if (!$_->{toFormat}) { my $t = isLoopback($_) ? eval { fsedit::typeOfPart($o->{prefix} . loopback::file($_)) } : fsedit::typeOfPart($_->{device}); $_->{toFormatUnsure} = $_->{mntpoint} eq "/" || #- if detected dos/win, it's not precise enough to just compare the types (too many of them) (!$t || isOtherAvailableFS({ type => $t }) ? !isOtherAvailableFS($_) : $t != $_->{type}); } } } sub formatMountPartitions { my ($o) = @_; fs::formatMount_all($o->{raid}, $o->{fstab}, $o->{prefix}); } #------------------------------------------------------------------------------ sub setPackages { my ($o) = @_; install_any::setPackages($o); pkgs::selectPackagesAlreadyInstalled($o->{packages}, $o->{prefix}) if !$o->{isUpgrade} && (-r "$o->{prefix}/var/lib/rpm/packages.rpm" || -r "$o->{prefix}/var/lib/rpm/Packages"); } sub selectPackagesToUpgrade { my ($o) = @_; pkgs::selectPackagesToUpgrade($o->{packages}, $o->{prefix}, $o->{base}, $o->{toRemove}, $o->{toSave}); } sub choosePackages { my ($o, $packages, $compss, $compssUsers, $first_time) = @_; #- now for upgrade, package that must be upgraded are #- selected first, after is used the same scheme as install. #- make sure we kept some space left for available else the system may #- not be able to start (xfs at least). my $available = install_any::getAvailableSpace($o); my $availableCorrected = pkgs::invCorrectSize($available / sqr(1024)) * sqr(1024); log::l(sprintf "available size %s (corrected %s)", formatXiB($available), formatXiB($availableCorrected)); #- avoid destroying user selection of packages but only #- for expert, as they may have done individual selection before. if ($first_time || !$::expert) { pkgs::unselectAllPackages($packages); pkgs::selectPackage($o->{packages}, pkgs::packageByName($o->{packages}, $_) || next) foreach @{$o->{default_packages}}; unless ($::expert) { add2hash_($o, { compssListLevel => 5 }) unless $::auto_install; exists $o->{compssListLevel} and pkgs::setSelectedFromCompssList($packages, $o->{compssUsersChoice}, $o->{compssListLevel}, $availableCorrected); } } $availableCorrected; } sub beforeInstallPackages { my ($o) = @_; #- save these files in case of upgrade failure. if ($o->{isUpgrade}) { foreach (@filesToSaveForUpgrade) { unlink "$o->{prefix}/$_.mdkgisave"; if (-e "$o->{prefix}/$_") { eval { commands::cp("$o->{prefix}/$_", "$o->{prefix}/$_.mdkgisave") }; } } } #- some packages need such files for proper installation. $::live or fs::write($o->{prefix}, $o->{fstab}, $o->{manualFstab}, $o->{useSupermount}); require network; network::add2hosts("$o->{prefix}/etc/hosts", "localhost.localdomain", "127.0.0.1"); require pkgs; pkgs::init_db($o->{prefix}); } sub pkg_install { my ($o, @l) = @_; log::l("selecting packages"); require pkgs; if ($::testing) { log::l("selecting package \"$_\"") foreach @l; } else { pkgs::selectPackage($o->{packages}, pkgs::packageByName($o->{packages}, $_) || die "$_ rpm not found") foreach @l; } my @toInstall = pkgs::packagesToInstall($o->{packages}); if (@toInstall) { log::l("installing packages"); $o->installPackages; } else { log::l("all packages selected are already installed, nothing to do") } } sub pkg_install_if_requires_satisfied { my ($o, @l) = @_; require pkgs; foreach (@l) { my %newSelection; my $pkg = pkgs::packageByName($o->{packages}, $_) || die "$_ rpm not found"; pkgs::selectPackage($o->{packages}, $pkg, 0, \%newSelection); scalar(keys %newSelection) == 1 and pkgs::selectPackage($o->{packages}, $pkg); } $o->installPackages; } sub installPackages($$) { #- complete REWORK, TODO and TOCHECK! my ($o) = @_; my $packages = $o->{packages}; if (@{$o->{toRemove} || []}) { #- hack to ensure proper upgrade of packages from other distribution, #- as release number are not mandrake based. this causes save of #- important files and restore them after. foreach (@{$o->{toSave} || []}) { if (-e "$o->{prefix}/$_") { unlink "$o->{prefix}/$_.mdkgisave"; eval { commands::cp("$o->{prefix}/$_", "$o->{prefix}/$_.mdkgisave") }; } } pkgs::remove($o->{prefix}, $o->{toRemove}); foreach (@{$o->{toSave} || []}) { if (-e "$o->{prefix}/$_.mdkgisave") { unlink "$o->{prefix}/$_"; rename "$o->{prefix}/$_.mdkgisave", "$o->{prefix}/$_"; } } $o->{toSave} = []; #- hack for compat-glibc to upgrade properly :-( if (pkgs::packageFlagSelected(pkgs::packageByName($packages, 'compat-glibc')) && !pkgs::packageFlagInstalled(pkgs::packageByName($packages, 'compat-glibc'))) { rename "$o->{prefix}/usr/i386-glibc20-linux", "$o->{prefix}/usr/i386-glibc20-linux.mdkgisave"; } } #- small transaction will be built based on this selection and depslist. my @toInstall = pkgs::packagesToInstall($packages); my $time = time; $ENV{DURING_INSTALL} = 1; pkgs::install($o->{prefix}, $o->{isUpgrade}, \@toInstall, $packages->{depslist}, $packages->{mediums}); delete $ENV{DURING_INSTALL}; run_program::rooted($o->{prefix}, 'ldconfig') or die "ldconfig failed!" unless $::g_auto_install; log::l("Install took: ", formatTimeRaw(time - $time)); install_any::log_sizes($o); } sub afterInstallPackages($) { my ($o) = @_; return if $::g_auto_install; die _("Some important packages didn't get installed properly. Either your cdrom drive or your cdrom is defective. Check the cdrom on an installed computer using \"rpm -qpl Mandrake/RPMS/*.rpm\" ") if grep { m|read failed: Input/output error| } cat_("$o->{prefix}/root/install.log"); if (arch() !~ /^sparc/) { #- TODO restore it as may be needed for sparc -x "$o->{prefix}/usr/bin/dumpkeys" or $::testing or die "Some important packages didn't get installed properly. Please switch to console 2 (using ctrl-alt-f2) and look at the log file /tmp/ddebug.log Consoles 1,3,4,7 may also contain interesting information"; } pkgs::done_db(); #- why not? cuz weather is nice today :-) [pixel] sync(); sync(); #- configure PCMCIA services if needed. modules::write_pcmcia($o->{prefix}, $o->{pcmcia}); #- for mandrake_firstime touch "$o->{prefix}/var/lock/TMP_1ST"; any::writeandclean_ldsoconf($o->{prefix}); log::l("before install packages, after writing ld.so.conf"); #- make sure some services have been enabled (or a catastrophic restart will occur). #- these are normally base package post install scripts or important services to start. run_program::rooted($o->{prefix}, "chkconfig", "--add", $_) foreach qw(random netfs network rawdevices sound kheader usb keytable syslog crond portmap); #- call update-menus at the end of package installation run_program::rooted($o->{prefix}, "update-menus"); if ($o->{pcmcia}) { substInFile { s/.*(TaskBarShowAPMStatus).*/$1=1/ } "$o->{prefix}/usr/lib/X11/icewm/preferences"; eval { commands::cp("$o->{prefix}/usr/share/applnk/System/kapm.kdelnk", "$o->{prefix}/etc/skel/Desktop/Autostart/kapm.kdelnk") }; } my $msec = "$o->{prefix}/etc/security/msec"; substInFile { s/^xgrp\n//; $_ .= "xgrp\n" if eof } "$msec/group.conf" if -d $msec; substInFile { s/^audio\n//; $_ .= "audio\n" if eof } "$msec/group.conf" if -d $msec; substInFile { s/^cdrom\n//; $_ .= "cdrom\n" if eof } "$msec/group.conf" if -d $msec; substInFile { s/^cdwriter\n//; $_ .= "cdwriter\n" if eof } "$msec/group.conf" if -d $msec; my $pkg = pkgs::packageByName($o->{packages}, 'urpmi'); if ($pkg && pkgs::packageSelectedOrInstalled($pkg)) { install_any::install_urpmi($o->{prefix}, $::oem ? 'cdrom' : $o->{method}, #- HACK $o->{packages}{mediums}); } if (my $charset = lang::charset($o->{lang}, $o->{prefix})) { eval { update_userkderc("$o->{prefix}/usr/share/config/kdeglobals", 'Locale', Charset => $charset) }; } # #- update language and icons for KDE. # update_userkderc($_, 'Locale', Language => "") foreach list_skels($o->{prefix}, '.kderc'); # log::l("updating kde icons according to available devices"); # install_any::kdeicons_postinstall($o->{prefix}); my $welcome = _("Welcome to %s", "HOSTNAME"); substInFile { s/^(GreetString)=.*/$1=$welcome/ } "$o->{prefix}/usr/share/config/kdmrc"; substInFile { s/^(UserView)=true/$1=false/ } "$o->{prefix}/usr/share/config/kdmrc" if $o->{security} >= 3; run_program::rooted($o->{prefix}, "kdeDesktopCleanup"); #- konsole and gnome-terminal are lamers in exotic languages, link them to something better if ($o->{lang} =~ /ja|ko|zh/) { foreach ("konsole", "gnome-terminal") { my $f = "$o->{prefix}/usr/bin/$_"; symlinkf("X11/rxvt.sh", $f) if -e $f; } } foreach (list_skels($o->{prefix}, '.kde/share/config/kfmrc')) { my $found; substInFile { $found ||= /KFM Misc Defaults/; $_ .= "[KFM Misc Defaults] GridWidth=85 GridHeight=70 " if eof && !$found; } $_ } #- move some file after an upgrade that may be seriously annoying. #- and rename saved files to .mdkgiorig. if ($o->{isUpgrade}) { log::l("moving previous desktop files that have been updated to Trash of each user"); install_any::kdemove_desktop_file($o->{prefix}); foreach (@filesToSaveForUpgrade) { if (-e "$o->{prefix}$_.mdkgisave") { unlink "$o->{prefix}$_.mdkgiorig"; rename "$o->{prefix}/$_.mdkgisave", "$o->{prefix}/$_.mdkgiorig"; } } } } #------------------------------------------------------------------------------ sub selectMouse($) { my ($o) = @_; } #------------------------------------------------------------------------------ sub configureNetwork { my ($o) = @_; require network; network::configureNetwork2($o->{prefix}, $o->{netc}, $o->{intf}, sub { $o->pkg_install(@_) }); } #------------------------------------------------------------------------------ sub installCrypto { my ($o) = @_; my $u = $o->{crypto} or return; $u->{mirror} && $u->{packages} or return; upNetwork($o); require crypto; my @crypto_packages = crypto::getPackages($o->{prefix}, $o->{packages}, $u->{mirror}); $o->pkg_install(@{$u->{packages}}); } sub summary { my ($o) = @_; configureTimezone($o); configurePrinter($o); } #------------------------------------------------------------------------------ sub configureTimezone { my ($o) = @_; install_any::preConfigureTimezone($o); require timezone; timezone::write($o->{prefix}, $o->{timezone}); } #------------------------------------------------------------------------------ sub configureServices { my ($o) = @_; if ($o->{services}) { require services; services::doit($o, $o->{services}, $o->{prefix}); } } #------------------------------------------------------------------------------ sub configurePrinter { my($o) = @_; my ($use_cups, $use_lpr) = (0, 0); foreach (values %{$o->{printer}{configured} || {}}) { for ($_->{mode}) { /CUPS/ and $use_cups++; /lpr/ and $use_lpr++; } } #- if at least one queue is configured, configure it. if ($use_cups || $use_lpr) { $o->pkg_install(($use_cups ? ('cups-drivers') : ()), ($use_lpr ? ('rhs-printfilters') : ())); require printer; eval { add2hash($o->{printer}, printer::getinfo($o->{prefix})) }; #- get existing configuration. $use_cups and printer::poll_ppd_base(); $use_lpr and printer::read_printer_db(); foreach (keys %{$o->{printer}{configured} || {}}) { log::l("configuring printer queue $_->{queue} for $_->{mode}"); printer::copy_printer_params($_, $o->{printer}); #- setup all configured queues, which is not the case interactively where #- only the working queue is setup on configuration. printer::configure_queue($o->{printer}); } } } #------------------------------------------------------------------------------ sub setRootPassword { my ($o) = @_; my $p = $o->{prefix}; my $u = $o->{superuser} ||= {}; local $o->{superuser}{name} = 'root'; any::write_passwd_user($o->{prefix}, $o->{superuser}, $o->{authentication}{md5}); } #------------------------------------------------------------------------------ sub addUser { my ($o) = @_; my $p = $o->{prefix}; my $users = $o->{users} ||= []; my (%uids, %gids); foreach (glob_("$p/home")) { my ($u, $g) = (stat($_))[4,5]; $uids{$u} = 1; $gids{$g} = 1; } foreach (@$users) { $_->{home} ||= "/home/$_->{name}"; my $u = $_->{uid} || ($_->{oldu} = (stat("$p$_->{home}"))[4]); my $g = $_->{gid} || ($_->{oldg} = (stat("$p$_->{home}"))[5]); #- search for available uid above 501 else initscripts may fail to change language for KDE. if (!$u || getpwuid($u)) { for ($u = 501; getpwuid($u) || $uids{$u}; $u++) {} } if (!$g || getgrgid($g)) { for ($g = 501; getgrgid($g) || $gids{$g}; $g++) {} } $_->{uid} = $u; $uids{$u} = 1; $_->{gid} = $g; $gids{$g} = 1; } any::write_passwd_user($p, $_, $o->{authentication}{md5}) foreach @$users; open F, ">> $p/etc/group" or die "can't append to group file: $!"; print F "$_->{name}:x:$_->{gid}:\n" foreach @$users; foreach my $u (@$users) { if (! -d "$p$u->{home}") { my $mode = $o->{security} < 2 ? 0755 : 0750; eval { commands::cp("-f", "$p/etc/skel", "$p$u->{home}") }; if ($@) { log::l("copying of skel failed: $@"); mkdir("$p$u->{home}", $mode); } else { chmod $mode, "$p$u->{home}"; } } require commands; eval { commands::chown_("-r", "$u->{uid}.$u->{gid}", "$p$u->{home}") } if $u->{uid} != $u->{oldu} || $u->{gid} != $u->{oldg}; } any::addUsers($p, $users); $o->pkg_install("autologin") if $o->{autologin}; any::set_autologin($p, $o->{autologin}, $o->{desktop}); install_any::setAuthentication($o); } #------------------------------------------------------------------------------ sub createBootdisk($) { my ($o) = @_; my $dev = $o->{mkbootdisk} or return; my @l = detect_devices::floppies(); $dev = shift @l || die _("No floppy drive available") if $dev eq "1"; #- special case meaning autochoose return if $::testing; require bootloader; bootloader::mkbootdisk($o->{prefix}, install_any::kernelVersion($o), $dev, $o->{bootloader}{perImageAppend}); $o->{mkbootdisk} = $dev; } #------------------------------------------------------------------------------ sub readBootloaderConfigBeforeInstall { my ($o) = @_; my ($image, $v); require bootloader; add2hash($o->{bootloader} ||= {}, bootloader::read($o->{prefix}, arch() =~ /sparc/ ? "/etc/silo.conf" : "/etc/lilo.conf")); #- since kernel or kernel-smp may not be upgraded, it should be checked #- if there is a need to update existing lilo.conf entries by following #- symlinks before kernel or other packages get installed. #- update everything that could be a filename (for following symlink). foreach my $e (@{$o->{bootloader}{entries}}) { while (my $v = readlink "$o->{prefix}/$e->{kernel_or_dev}") { $v = "/boot/$v" if $v !~ m|^/|; -e "$o->{prefix}$v" or last; log::l("renaming /boot/$e->{kernel_or_dev} entry by $v"); $e->{kernel_or_dev} = $v; } while (my $v = readlink "$o->{prefix}/$e->{initrd}") { $v = "/boot/$v" if $v !~ m|^/|; -e "$o->{prefix}$v" or last; log::l("renaming /boot/$e->{initrd} entry by $v"); $e->{initrd} = $v; } } } sub setupBootloaderBefore { my ($o) = @_; if (arch() =~ /alpha/) { if (my $dev = fsedit::get_root($o->{fstab})) { $o->{bootloader}{boot} ||= "/dev/$dev->{rootDevice}"; $o->{bootloader}{root} ||= "/dev/$dev->{device}"; $o->{bootloader}{part_nb} ||= first($dev->{device} =~ /(\d+)/); } } else { #- check for valid fb mode to enable a default boot with frame buffer. my $vga = $o->{allowFB} && (!detect_devices::matching_desc('Rage LT') && !detect_devices::matching_desc('SiS') && !detect_devices::matching_desc('Rage Mobility')) && $o->{vga}; require bootloader; #- propose the default fb mode for kernel fb, if aurora is installed too. bootloader::suggest($o->{prefix}, $o->{bootloader}, $o->{hds}, $o->{fstab}, install_any::kernelVersion($o), pkgs::packageFlagInstalled(pkgs::packageByName($o->{packages}, 'Aurora') || {}) && $vga); bootloader::suggest_floppy($o->{bootloader}) if $o->{security} <= 3; $o->{bootloader}{keytable} ||= keyboard::keyboard2kmap($o->{keyboard}); } } sub setupBootloader($) { my ($o) = @_; return if $::g_auto_install; if (arch() =~ /alpha/) { return if $::testing; my $b = $o->{bootloader}; $b->{boot} or $o->ask_warn('', "Can't install aboot, not a bsd disklabel"), return; run_program::rooted($o->{prefix}, "swriteboot", $b->{boot}, "/boot/bootlx") or do { cdie "swriteboot failed"; run_program::rooted($o->{prefix}, "swriteboot", "-f1", $b->{boot}, "/boot/bootlx"); }; run_program::rooted($o->{prefix}, "abootconf", $b->{boot}, $b->{part_nb}); modules::load('loop'); output "$o->{prefix}/etc/aboot.conf", map_index { -e "$o->{prefix}/boot/initrd-$_->[1]" ? "$::i:$b->{part_nb}$_->[0] root=$b->{root} initrd=/boot/initrd-$_->[1] $b->{perImageAppend}\n" : "$::i:$b->{part_nb}$_->[0] root=$b->{root} $b->{perImageAppend}\n" } map { run_program::rooted($o->{prefix}, "mkinitrd", "-f", "/boot/initrd-$_->[1]", "--ifneeded", $_->[1]) ;#or #unlink "$o->{prefix}/boot/initrd-$_->[1]";$_ } grep { $_->[0] && $_->[1] } $_ } grep { $_->[0] && $_->[1] } map { [ m|$o->{prefix}(/boot/vmlinux-(.*))| ] } glob_("$o->{prefix}/boot/vmlinux-*"); # output "$o->{prefix}/etc/aboot.conf", # map_index { "$::i:$b->{part_nb}$_ root=$b->{root} $b->{perImageAppend}\n" } # map { /$o->{prefix}(.*)/ } eval { glob_("$o->{prefix}/boot/vmlinux*") }; } else { require bootloader; bootloader::install($o->{prefix}, $o->{bootloader}, $o->{fstab}, $o->{hds}); } } #------------------------------------------------------------------------------ sub configureXBefore { my ($o) = @_; my $xkb = $o->{X}{keyboard}{xkb_keymap} || keyboard::keyboard2xkb($o->{keyboard}); $xkb = '' if !($xkb && -e "$o->{prefix}/usr/X11R6/lib/X11/xkb/symbols/$xkb"); if (!$xkb && (my $f = keyboard::xmodmap_file($o->{keyboard}))) { require commands; commands::cp("-f", $f, "$o->{prefix}/etc/X11/xinit/Xmodmap"); $xkb = ''; } { my $f = "$o->{prefix}/etc/sysconfig/i18n"; setVarsInSh($f, add2hash_({ XKB_IN_USE => $xkb ? '': 'no' }, { getVarsFromSh($f) })); } $o->{X}{keyboard}{xkb_keymap} = $xkb; $o->{X}{mouse} = $o->{mouse}; $o->{X}{wacom} = $o->{wacom}; require Xconfig; Xconfig::getinfoFromDDC($o->{X}); Xconfig::getinfoFromXF86Config($o->{X}, $o->{prefix}); #- take default from here at least. #- keep this here if the package has to be updated. $o->pkg_install("XFree86"); } sub configureX { my ($o) = @_; $o->configureXBefore; require Xconfigurator; require class_discard; { local $::testing = 0; #- unset testing local $::auto = 1; $o->{X}{skiptest} = 1; Xconfigurator::main($o->{prefix}, $o->{X}, class_discard->new, $o->{allowFB}, sub { $o->pkg_install(@_) }); } $o->configureXAfter; } sub configureXAfter { my ($o) = @_; if ($o->{X}{card}{server} eq 'FBDev') { unless (install_any::setupFB($o, Xconfigurator::getVGAMode($o->{X}))) { log::l("disabling automatic start-up of X11 if any as setup framebuffer failed"); Xconfigurator::rewriteInittab(3) unless $::testing; #- disable automatic start-up of X11 on error. } } if ($o->{X}{default_depth} >= 16 && $o->{X}{card}{default_wres} >= 1024) { log::l("setting large icon style for kde"); install_any::kderc_largedisplay($o->{prefix}); } } #------------------------------------------------------------------------------ sub miscellaneousBefore { my ($o) = @_; my %s = getVarsFromSh("$o->{prefix}/etc/sysconfig/system"); $o->{miscellaneous}{HDPARM} ||= $s{HDPARM} if exists $s{HDPARM}; $o->{security} ||= $s{SECURITY} if exists $s{SECURITY}; $ENV{SECURE_LEVEL} = $o->{security}; add2hash_ $o, { useSupermount => $o->{security} < 4 && arch() !~ /sparc/ && !$::corporate }; add2hash_($o->{miscellaneous} ||= {}, { numlock => !$o->{pcmcia} }); } sub miscellaneous { my ($o) = @_; local $_ = $o->{bootloader}{perImageAppend}; if ($o->{lnx4win} and !/mem=/) { $_ .= ' mem=' . availableRamMB() . 'M'; } if (my @l = detect_devices::IDEburners() and !/ide-scsi/) { $_ .= " " . join(" ", (map { "$_->{device}=ide-scsi" } @l), #- in that case, also add ide-floppy otherwise ide-scsi will be used! map { "$_->{device}=ide-floppy" } detect_devices::ide_zips()); } if ($o->{miscellaneous}{HDPARM}) { $_ .= join('', map { " $_=autotune" } grep { /ide.*/ } all("/proc/ide")) if !/ide.=autotune/; } #- keep some given parameters #-TODO log::l("perImageAppend: $_"); $o->{bootloader}{perImageAppend} = $_; } #------------------------------------------------------------------------------ sub generateAutoInstFloppy($) { my ($o) = @_; } #------------------------------------------------------------------------------ sub exitInstall { my ($o) = @_; output "$o->{prefix}/root/report.bug", commands::report_bug(); install_any::unlockCdrom; install_any::log_sizes($o); } #------------------------------------------------------------------------------ sub hasNetwork { my ($o) = @_; $o->{intf} && $o->{netc}{NETWORKING} ne 'no' || $o->{netcnx}{modem}; } #------------------------------------------------------------------------------ sub upNetwork { my ($o, $pppAvoided) = @_; foreach (qw(resolv.conf protocols services)) { symlinkf("$o->{prefix}/etc/$_", "/etc/$_"); } modules::write_conf($o->{prefix}); if ($o->{intf} && $o->{netc}{NETWORKING} ne 'no') { network::up_it($o->{prefix}, $o->{intf}); } elsif (!$pppAvoided && $o->{netcnx}{modem} && !$o->{netcnx}{modem}{isUp}) { eval { modules::load_multi(qw(serial ppp bsd_comp ppp_deflate)) }; run_program::rooted($o->{prefix}, "/etc/rc.d/init.d/syslog", "start"); run_program::rooted($o->{prefix}, "ifup", "ppp0"); $o->{netcnx}{modem}{isUp} = 1; } else { $::testing or return; } 1; } #------------------------------------------------------------------------------ sub downNetwork { my ($o, $pppOnly) = @_; modules::write_conf($o->{prefix}); if (!$pppOnly && $o->{intf} && $o->{netc}{NETWORKING} ne 'no') { network::down_it($o->{prefix}, $o->{intf}); } elsif ($o->{netcnx}{modem} && $o->{netcnx}{modem}{isUp}) { run_program::rooted($o->{prefix}, "ifdown", "ppp0"); run_program::rooted($o->{prefix}, "/etc/rc.d/init.d/syslog", "stop"); eval { modules::unload($_) foreach qw(ppp_deflate bsd_comp ppp serial) }; $o->{netcnx}{modem}{isUp} = 0; } else { $::testing or return; } 1; } #------------------------------------------------------------------------------ sub cleanIfFailedUpgrade($) { my ($o) = @_; #- if an upgrade has failed, there should be .mdkgisave files around. if ($o->{isUpgrade}) { foreach (@filesToSaveForUpgrade) { if (-e "$o->{prefix}/$_" && -e "$o->{prefix}/$_.mdkgisave") { rename "$o->{prefix}/$_", "$o->{prefix}/$_.mdkginew"; #- keep new files around in case ! rename "$o->{prefix}/$_.mdkgisave", "$o->{prefix}/$_"; } } } } #-###################################################################################### #- Wonderful perl :( #-###################################################################################### 1; s="hl ipl">$prefix/etc/rc.d/init.d/$name"); $s ||= -e "$prefix/etc/init.d/$name" && cat_("$prefix/etc/init.d/$name"); $s ||= -e "$prefix/etc/xinetd.d/$name" && cat_("$prefix/etc/xinetd.d/$name"); $s =~ s/\\\s*\n#\s*//mg; if ($s =~ /^# description:\s+\S/sm) { ($s) = $s =~ /^# description:\s+(.*?)^(?:[^#]|# {0,2}\S)/sm; } else { ($s) = $s =~ /^#\s*(.*?)^[^#]/sm; } $s =~ s/#\s*//mg; } $s =~ s/\n/ /gm; $s =~ s/\s+$//; $s; } sub ask_install_simple { my ($in, $prefix) = @_; my ($l, $on_services) = services($prefix); $in->ask_many_from_list("drakxservices", N("Choose which services should be automatically started at boot time"), { list => $l, help => sub { description($_[0], $prefix) }, values => $on_services, sort => 1, }); } sub ask_install { my ($in, $prefix) = @_; my %root_services = ( N("Printing") => [ qw(cups cupslpd lpr lpd oki4daemon hpoj cups-lpd) ], N("Internet") => [ qw(httpd boa tux roxen ftp pftp tftp proftpd wu-ftpd pure-ftpdipsec proftpd-xinetd ipchains iptables ipvsadm isdn4linux ibod jabber jabber-icq adsl squid portsentry prelude nessusd junkbuster radvd cddbp ippl iptoip jail.init) ], N("File sharing") => [ qw(nfs nfslock smb nettalk netfs mcserv autofs amd venus.init auth2.init codasrv.init update.init swat) ], N("System") => [ qw(usb usbd pcmcia irda xinetd inetd kudzu harddrake apmd sound network xfs alsa functions halt kheader killall mandrake_everytime mandrake_firstime random rawdevices single keytable syslog crond medusa-init portmap acon anacron atd gpm psacct wine acpid numlock jserver sensors mosix bpowerd bpowerfail fcron powertweak.init ups syslog-ng cvs apcupsd) ], N("Remote Administration") => [ qw(sshd telnetd telnet rsh rlogin rexec webmin cfd heartbeat ldirectord iplog mon vncserver netsaint olympusd drakxtools_http) ], # N("Network Client") => [ qw(ypbind nscd arpwatch fetchmail dnrd_rc diald rsync) ], # N("Network Server") => [ qw(named bootparamd ntpd xntpd chronyd postfix sendmail # imap imaps ipop2 ipop3 pop3s routed yppasswdd ypserv ldap dhcpd dhcrelay # hylafax innd identd rstatd rusersd rwalld rwhod gated # kadmin kprop krb524 krb5kdc krb5server hldsld bayonne sockd dhsd gnu-pop3d # gdips pptpd.conf vrrpd crossfire bnetd pvmd ircd sympa finger ntalk talk) ], N("Database Server") => [ qw(mysql postgresql) ], ); my %services_root; foreach my $root (keys %root_services) { $services_root{$_} = $root foreach @{$root_services{$root}}; } my ($l, $on_services) = services($prefix); my %services; $services{$_} = 0 foreach @{$l || []}; $services{$_} = 1 foreach @{$on_services || []}; $in->ask_browse_tree_info('drakxservices', N("Choose which services should be automatically started at boot time"), { node_state => sub { $services{$_[0]} ? 'selected' : 'unselected' }, build_tree => sub { my ($add_node, $flat) = @_; $add_node->($_, !$flat && ($services_root{$_} || N("Other"))) foreach sort keys %services; }, grep_unselected => sub { grep { !$services{$_} } @_ }, toggle_nodes => sub { my ($set_state, @nodes) = @_; my $new_state = !$services{$nodes[0]}; foreach (@nodes) { $set_state->($_, $new_state ? 'selected' : 'unselected'); $services{$_} = $new_state; } }, get_status => sub { N("Services: %d activated for %d registered", scalar(grep { $_ } values %services), scalar(values %services)); }, get_info => sub { formatLines(description($_[0], $prefix)) }, }) or return ($l, $on_services); #- no change on cancel. [ grep { $services{$_} } @$l ]; } sub ask_standalone_gtk { my ($_in, $prefix) = @_; my ($l, $on_services) = services($prefix); require ugtk2; ugtk2->import(qw(:wrappers :create)); my $W = ugtk2->new(N("Services")); my ($x, $y, $w_popup); my $nopop = sub { $w_popup and $w_popup->destroy }; my $display = sub { $nopop->(); $_[0] and gtkshow(gtkadd($w_popup = Gtk2::Window->new('popup'), gtksignal_connect(gtkadd(Gtk2::EventBox->new, gtkadd(gtkset_shadow_type(Gtk2::Frame->new, 'etched_out'), gtkset_justify(Gtk2::Label->new($_[0]), 'left'))), button_press_event => sub { $nopop->() } )))->move($x, $y) }; my $update_service = sub { my $started = -e "/var/lock/subsys/$_[0]"; my $action = $started ? "stop" : "start"; $_[1]->set($started ? N("running") : N("stopped")); $started, $action; }; my $b = Gtk2::EventBox->new; $b->set_events('pointer_motion_mask'); gtkadd($W->{window}, gtkadd($b, gtkpack_($W->create_box_with_title(N("Services and deamons")), 1, gtkset_size_request(create_scrolled_window(create_packtable({ col_spacings => 10, row_spacings => 3 }, map { my $service = $_; my $infos = warp_text(description($_, $prefix), 40); $infos ||= N("No additional information\nabout this service, sorry."); my $l = Gtk2::Label->new; my ($started, $action) = $update_service->($service, gtkset_justify($l, 'left')); [ gtkpack__(Gtk2::HBox->new(0,0), $_), gtkpack__(Gtk2::HBox->new(0,0), $l), gtkpack__(Gtk2::HBox->new(0,0), gtksignal_connect(Gtk2::Button->new(N("Info")), clicked => sub { $display->($infos) })), gtkpack__(Gtk2::HBox->new(0,0), gtkset_active(gtksignal_connect( Gtk2::CheckButton->new(N("On boot")), clicked => sub { if ($_[0]->active) { push @$on_services, $service if !member($service, @$on_services); } else { @$on_services = grep { $_ ne $service } @$on_services; } }), member($service, @$on_services))), map { my $a = $_; gtkpack__(Gtk2::HBox->new(0,0), gtksignal_connect(Gtk2::Button->new(translate($a)), clicked => sub { my $c = "service $service " . (lc($a) eq "start" ? "restart" : lc($a)) . " 2>&1"; local $_ = `$c`; s/\033\[[^mG]*[mG]//g; ($started, $action) = $update_service->($service, $l); $display->($_); } )) } (N_("Start"), N_("Stop")) ] } @$l)), 500, 400), 0, gtkpack(gtkset_border_width(Gtk2::HBox->new(0,0),5), $W->create_okcancel) )) ); $b->signal_connect(motion_notify_event => sub { my ($w, $e) = @_; my ($ox, $oy) = $w->window->get_origin; $x = $e->x+$ox; $y = $e->y+$oy }); $b->signal_connect(button_press_event => sub { $nopop->() }); $::isEmbedded and flush(); $W->main or return; $on_services; } sub ask { my ($in, $_prefix) = @_; !$::isInstall && $in->isa('interactive::gtk') ? &ask_standalone_gtk : &ask_install; } sub doit { my ($_in, $on_services, $prefix) = @_; my ($l, $was_on_services) = services($prefix); foreach (@$l) { my $before = member($_, @$was_on_services); my $after = member($_, @$on_services); if ($before != $after) { my $script = "/etc/rc.d/init.d/$_"; run_program::rooted($prefix, "chkconfig", $after ? "--add" : "--del", $_);