package any; # $Id$ use diagnostics; use strict; #-###################################################################################### #- misc imports #-###################################################################################### use common; use detect_devices; use partition_table qw(:types); use fsedit; use fs; use lang; use run_program; use keyboard; use devices; use modules; use log; use c; sub drakx_version() { $::move ? sprintf "DrakX-move v%s", cat_('/usr/bin/stage2/move.pm') =~ /move\.pm,v (\S+ \S+ \S+)/ : sprintf "DrakX v%s built %s", $::testing ? ('TEST', scalar gmtime()) : (split('/', cat_("$ENV{SHARE_PATH}/VERSION")))[2,3]; } sub facesdir() { "$::prefix/usr/share/mdk/faces/"; } sub face2png { my ($face) = @_; facesdir() . $face . ".png"; } sub facesnames() { my $dir = facesdir(); my @l = grep { /^[A-Z]/ } all($dir); map { if_(/(.*)\.png/, $1) } (@l ? @l : all($dir)); } sub addKdmIcon { my ($user, $icon) = @_; my $dest = "$::prefix/usr/share/faces/$user.png"; eval { cp_af(facesdir() . $icon . ".png", $dest) } if $icon; } sub allocUsers { my ($users) = @_; my @m = my @l = facesnames(); foreach (grep { !$_->{icon} || $_->{icon} eq "automagic" } @$users) { $_->{auto_icon} = splice(@m, rand(@m), 1); #- known biased (see cookbook for better) log::l("auto_icon is $_->{auto_icon}"); @m = @l unless @m; } } sub addUsers { my ($users) = @_; allocUsers($users); foreach my $u (@$users) { run_program::rooted($::prefix, "usermod", "-G", join(",", @{$u->{groups}}), $u->{name}) if !is_empty_array_ref($u->{groups}); addKdmIcon($u->{name}, delete $u->{auto_icon} || $u->{icon}); } } sub crypt { my ($password, $md5) = @_; crypt($password, $md5 ? '$1$' . salt(8) : salt(2)); } sub enableShadow() { run_program::rooted($::prefix, "pwconv") or log::l("pwconv failed"); run_program::rooted($::prefix, "grpconv") or log::l("grpconv failed"); } sub hdInstallPath() { my $tail = first(readlink("/tmp/image") =~ m|^/tmp/hdimage/?(.*)|); my $head = first(readlink("/tmp/hdimage") =~ m|$::prefix(.*)|); defined $tail && ($head ? "$head/$tail" : "/mnt/hd/$tail"); } sub setupBootloader { my ($in, $b, $all_hds, $fstab, $security) = @_; my $hds = $all_hds->{hds}; require bootloader; general: { local $::Wizard_no_previous = 1 if $::isStandalone; setupBootloader__general($in, $b, $all_hds, $fstab, $security) or return 0; } setupBootloader__boot_bios_drive($in, $b, $hds) or goto general; { local $::Wizard_finished = 1 if $::isStandalone; setupBootloader__entries($in, $b, $all_hds, $fstab) or goto general; } #- somewhere should bootloader really installed ? $::isStandalone and my $_w = $in->wait_message(N("Please wait"), N("Bootloader installation in progress")); eval { run_program::rooted($::prefix, 'lilo', '-u') } if $::isInstall && !$::o->{isUpgrade} && -e "$::prefix/etc/lilo.conf" && glob("$::prefix/boot/boot.*"); bootloader::install($b, $hds); } sub setupBootloader_simple { my ($in, $b, $all_hds, $fstab, $security) = @_; my $hds = $all_hds->{hds}; require bootloader; my $mixed_kind_of_disks = bootloader::mixed_kind_of_disks($hds); #- full expert questions when there is 2 kind of disks #- it would need a semi_auto asking on which drive the bios boots... $mixed_kind_of_disks || $b->{bootUnsafe} || arch() =~ /ppc/ or return 1; #- default is good enough if (!$mixed_kind_of_disks && arch() !~ /ia64/) { setupBootloader__mbr_or_not($in, $b, $hds, $fstab) or return 0; } else { general: setupBootloader__general($in, $b, $all_hds, $fstab, $security) or return 0; } setupBootloader__boot_bios_drive($in, $b, $hds) or goto general; 1; } sub setupBootloader__boot_bios_drive { my ($in, $b, $hds) = @_; bootloader::mixed_kind_of_disks($hds) && $b->{boot} =~ /\d$/ && #- on a partition is_empty_hash_ref($b->{bios}) && #- some bios mapping already there arch() !~ /ppc/ or return 1; log::l("mixed_kind_of_disks"); my $hd = $in->ask_from_listf('', N("You decided to install the bootloader on a partition. This implies you already have a bootloader on the hard drive you boot (eg: System Commander). On which drive are you booting?"), \&partition_table::description, $hds) or return 0; log::l("mixed_kind_of_disks chosen $hd->{device}"); $b->{first_hd_device} = "/dev/$hd->{device}"; 1; } sub setupBootloader__mbr_or_not { my ($in, $b, $hds, $fstab) = @_; if (arch() =~ /ppc/) { if (defined $partition_table::mac::bootstrap_part) { $b->{boot} = $partition_table::mac::bootstrap_part; log::l("set bootstrap to $b->{boot}"); } else { die "no bootstrap partition - yaboot.conf creation failed"; } } else { my $floppy = detect_devices::floppy(); my @l = ( [ N("First sector of drive (MBR)") => '/dev/' . $hds->[0]{device} ], [ N("First sector of the root partition") => '/dev/' . fsedit::get_root($fstab, 'boot')->{device} ], if_($floppy, [ N("On Floppy") => "/dev/$floppy" ], ), [ N("Skip") => '' ], ); my $default = find { $_->[1] eq $b->{boot} } @l; $in->ask_from_({ title => N("LILO/grub Installation"), messages => N("Where do you want to install the bootloader?"), interactive_help_id => 'setupBootloaderBeginner', }, [ { val => \$default, list => \@l, format => sub { $_[0][0] }, type => 'list' } ]); my $new_boot = $default->[1] or return; #- remove bios mapping if the user changed the boot device delete $b->{bios} if $new_boot ne $b->{boot}; $b->{boot} = $new_boot; } 1; } sub setupBootloader__general { my ($in, $b, $all_hds, $fstab, $security) = @_; my @method_choices = bootloader::method_choices($fstab); my $profiles = bootloader::has_profiles($b); my $prev_force_acpi = my $force_acpi = bootloader::get_append($b, 'acpi') !~ /off|ht/; my $prev_force_noapic = my $force_noapic = bootloader::get_append($b, 'noapic'); my $prev_force_nolapic = my $force_nolapic = bootloader::get_append($b, 'nolapic'); my $memsize = bootloader::get_append($b, 'mem'); my $prev_clean_tmp = my $clean_tmp = any { $_->{mntpoint} eq '/tmp' } @{$all_hds->{special} ||= []}; my $prev_boot = $b->{boot}; $b->{password2} ||= $b->{password} ||= ''; $::Wizard_title = N("Boot Style Configuration"); if (arch() !~ /ppc/) { $in->ask_from_({ messages => N("Bootloader main options"), interactive_help_id => 'setupBootloader', callbacks => { complete => sub { !$memsize || $memsize =~ /^\d+K$/ || $memsize =~ s/^(\d+)M?$/$1M/i or $in->ask_warn('', N("Give the ram size in MB")), return 1; #- $security > 4 && length($b->{password}) < 6 and $in->ask_warn('', N("At this level of security, a password (and a good one) in lilo is requested")), return 1; $b->{restricted} && !$b->{password} and $in->ask_warn('', N("Option ``Restrict command line options'' is of no use without a password")), return 1; $b->{password} eq $b->{password2} or !$b->{restricted} or $in->ask_warn('', [ N("The passwords do not match"), N("Please try again") ]), return 1; 0; }, }, }, [ { label => N("Bootloader to use"), val => \$b->{method}, list => \@method_choices, format => \&bootloader::method2text }, if_(arch() !~ /ia64/, { label => N("Boot device"), val => \$b->{boot}, list => [ map { "/dev/$_" } (map { $_->{device} } (@{$all_hds->{hds}}, grep { !isFat_or_NTFS($_) } @$fstab)), detect_devices::floppies_dev() ], not_edit => !$::expert }, ), { label => N("Delay before booting default image"), val => \$b->{timeout} }, { text => N("Enable ACPI"), val => \$force_acpi, type => 'bool' }, if_(!$force_nolapic, { text => N("Force no APIC"), val => \$force_noapic, type => 'bool' }, ), { text => N("Force No Local APIC"), val => \$force_nolapic, type => 'bool' }, if_($security >= 4 || $b->{password} || $b->{restricted}, { label => N("Password"), val => \$b->{password}, hidden => 1 }, { label => N("Password (again)"), val => \$b->{password2}, hidden => 1 }, { text => N("Restrict command line options"), val => \$b->{restricted}, type => "bool", text => N("restrict") }, ), { text => N("Clean /tmp at each boot"), val => \$clean_tmp, type => 'bool', advanced => 1 }, { label => N("Precise RAM size if needed (found %d MB)", availableRamMB()), val => \$memsize, advanced => 1 }, if_(detect_devices::isLaptop(), { text => N("Enable multiple profiles"), val => \$profiles, type => 'bool', advanced => 1 }, ), ]) or return 0; } else { $b->{boot} = $partition_table::mac::bootstrap_part; $in->ask_from_({ messages => N("Bootloader main options"), interactive_help_id => 'setupYabootGeneral', }, [ { label => N("Bootloader to use"), val => \$b->{method}, list => \@method_choices, format => \&bootloader::method2text }, { label => N("Init Message"), val => \$b->{'init-message'} }, { label => N("Boot device"), val => \$b->{boot}, list => [ map { "/dev/$_" } (map { $_->{device} } (grep { isAppleBootstrap($_) } @$fstab)) ], not_edit => !$::expert }, { label => N("Open Firmware Delay"), val => \$b->{delay} }, { label => N("Kernel Boot Timeout"), val => \$b->{timeout} }, { label => N("Enable CD Boot?"), val => \$b->{enablecdboot}, type => "bool" }, { label => N("Enable OF Boot?"), val => \$b->{enableofboot}, type => "bool" }, { label => N("Default OS?"), val => \$b->{defaultos}, list => [ 'linux', 'macos', 'macosx', 'darwin' ] }, ]) or return 0; } #- remove bios mapping if the user changed the boot device delete $b->{bios} if $b->{boot} ne $prev_boot; if ($b->{method} eq 'grub') { $in->do_pkgs->ensure_is_installed('grub', "/usr/sbin/grub", 1) or return 0; } bootloader::set_profiles($b, $profiles); bootloader::set_append($b, "mem", $memsize || 0); if ($prev_force_acpi != $force_acpi) { bootloader::set_append($b, acpi => ($force_acpi ? '' : 'ht')); } if ($prev_force_noapic != $force_noapic) { ($force_noapic ? \&bootloader::set_append : \&bootloader::remove_append_simple)->($b, 'noapic'); } if ($prev_force_nolapic != $force_nolapic) { ($force_nolapic ? \&bootloader::set_append : \&bootloader::remove_append_simple)->($b, 'nolapic'); } if ($prev_clean_tmp != $clean_tmp) { if ($clean_tmp && !fsedit::has_mntpoint('/tmp', $all_hds)) { push @{$all_hds->{special}}, { device => 'none', mntpoint => '/tmp', pt_type => 'tmpfs' }; } else { @{$all_hds->{special}} = grep { $_->{mntpoint} ne '/tmp' } @{$all_hds->{special}}; } } 1; } sub setupBootloader__entries { my ($in, $b, $_all_hds, $fstab) = @_; require Xconfig::resolution_and_depth; my $Modify = sub { my ($e) = @_; my $default = my $old_default = $e->{label} eq $b->{default}; my $vga = Xconfig::resolution_and_depth::from_bios($e->{vga}); my @l; if ($e->{type} eq "image") { @l = ( { label => N("Image"), val => \$e->{kernel_or_dev}, list => [ map { "/boot/$_" } bootloader::installed_vmlinuz() ], not_edit => 0 }, { label => N("Root"), val => \$e->{root}, list => [ map { "/dev/$_->{device}" } @$fstab ], not_edit => !$::expert }, { label => N("Append"), val => \$e->{append} }, if_(arch() !~ /ppc|ia64/, { label => N("Video mode"), val => \$vga, list => [ '', Xconfig::resolution_and_depth::bios_vga_modes() ], format => \&Xconfig::resolution_and_depth::to_string, advanced => 1 }, ), { label => N("Initrd"), val => \$e->{initrd}, list => [ map { if_(/^initrd/, "/boot/$_") } all("$::prefix/boot") ], not_edit => 0, advanced => 1 }, ); } else { @l = ( { label => N("Root"), val => \$e->{kernel_or_dev}, list => [ map { "/dev/$_->{device}" } @$fstab, detect_devices::floppies() ], not_edit => !$::expert }, ); } if (arch() !~ /ppc/) { @l = ( { label => N("Label"), val => \$e->{label} }, @l, { text => N("Default"), val => \$default, type => 'bool' }, ); } else { unshift @l, { label => N("Label"), val => \$e->{label}, list => ['macos', 'macosx', 'darwin'] }; if ($e->{type} eq "image") { @l = ({ label => N("Label"), val => \$e->{label} }, $::expert ? @l[1..4] : (@l[1..2], { label => N("Append"), val => \$e->{append} }), if_($::expert, { label => N("Initrd-size"), val => \$e->{initrdsize}, list => [ '', '4096', '8192', '16384', '24576' ] }), if_($::expert, $l[5]), { label => N("NoVideo"), val => \$e->{novideo}, type => 'bool' }, { text => N("Default"), val => \$default, type => 'bool' } ); } } $in->ask_from_( { interactive_help_id => arch() =~ /ppc/ ? 'setupYabootAddEntry' : 'setupBootloaderAddEntry', callbacks => { complete => sub { $e->{label} or $in->ask_warn('', N("Empty label not allowed")), return 1; $e->{kernel_or_dev} or $in->ask_warn('', $e->{type} eq 'image' ? N("You must specify a kernel image") : N("You must specify a root partition")), return 1; member(lc $e->{label}, map { lc $_->{label} } grep { $_ != $e } @{$b->{entries}}) and $in->ask_warn('', N("This label is already used")), return 1; 0; } } }, \@l) or return; $b->{default} = $old_default || $default ? $default && $e->{label} : $b->{default}; $e->{vga} = ref($vga) ? $vga->{bios} : $vga; bootloader::configure_entry($e); #- hack to make sure initrd file are built. 1; }; my $Add = sub { my @labels = map { $_->{label} } @{$b->{entries}}; my ($e, $prefix); if ($in->ask_from_list_('', N("Which type of entry do you want to add?"), [ N_("Linux"), arch() =~ /sparc/ ? N_("Other OS (SunOS...)") : arch() =~ /ppc/ ? N_("Other OS (MacOS...)") : N_("Other OS (Windows...)") ] ) eq "Linux") { $e = { type => 'image', root => '/dev/' . fsedit::get_root($fstab)->{device}, #- assume a good default. }; $prefix = "linux"; } else { $e = { type => 'other' }; $prefix = arch() =~ /sparc/ ? "sunos" : arch() =~ /ppc/ ? "macos" : "windows"; } $e->{label} = $prefix; for (my $nb = 0; member($e->{label}, @labels); $nb++) { $e->{label} = "$prefix-$nb"; } $Modify->($e) or return; bootloader::add_entry($b, $e); $e; }; my $Remove = sub { my ($e) = @_; delete $b->{default} if $b->{default} eq $e->{label}; @{$b->{entries}} = grep { $_ != $e } @{$b->{entries}}; 1; }; my @prev_entries = @{$b->{entries}}; if ($in->ask_from__add_modify_remove('', N("Here are the entries on your boot menu so far. You can create additional entries or change the existing ones."), [ { format => sub { my ($e) = @_; ref($e) ? "$e->{label} ($e->{kernel_or_dev})" . ($b->{default} eq $e->{label} && " *") : translate($e); }, list => $b->{entries}, } ], Add => $Add, Modify => $Modify, Remove => $Remove)) { 1; } else { @{$b->{entries}} = @prev_entries; ''; } } my @etc_pass_fields = qw(name pw uid gid realname home shell); sub unpack_passwd { my ($l) = @_; my %l; @l{@etc_pass_fields} = split ':', chomp_($l); \%l; } sub pack_passwd { my ($l) = @_; join(':', @$l{@etc_pass_fields}) . "\n"; } sub get_autologin() { my %desktop = getVarsFromSh("$::prefix/etc/sysconfig/desktop"); my $desktop = $desktop{DESKTOP} || 'KDE'; my $autologin = do { if (($desktop{DISPLAYMANAGER} || $desktop) eq 'GNOME') { my %conf = read_gnomekderc("$::prefix/etc/X11/gdm/gdm.conf", 'daemon'); text2bool($conf{AutomaticLoginEnable}) && $conf{AutomaticLogin}; } else { # KDM / MdkKDM my %conf = read_gnomekderc("$::prefix/usr/share/config/kdm/kdmrc", 'X-:0-Core'); text2bool($conf{AutoLoginEnable}) && $conf{AutoLoginUser}; } }; { autologin => $autologin, desktop => $desktop }; } sub set_autologin { my ($user, $desktop) = @_; my $autologin = bool2text($user); #- Configure KDM / MDKKDM eval { update_gn-$title = N("What is Mandrake Linux?");