summaryrefslogtreecommitdiffstats
path: root/perl-install/any.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/any.pm')
-rw-r--r--perl-install/any.pm2540
1 files changed, 1856 insertions, 684 deletions
diff --git a/perl-install/any.pm b/perl-install/any.pm
index 2333cbd44..ab93036dc 100644
--- a/perl-install/any.pm
+++ b/perl-install/any.pm
@@ -8,42 +8,39 @@ use strict;
#-######################################################################################
use common;
use detect_devices;
-use partition_table qw(:types);
-use fsedit;
-use fs;
+use partition_table;
+use fs::proc_partitions;
+use fs::type;
use lang;
use run_program;
+use devices;
use modules;
use log;
+use fs;
+use c;
-sub drakx_version {
- sprintf "DrakX v%s built %s", $::testing ? ('TEST', scalar gmtime()) : (split('/', cat_("$ENV{SHARE_PATH}/VERSION")))[2,3];
-}
-
-sub facesdir {
- my ($prefix) = @_;
- "$prefix/usr/share/mdk/faces/";
+sub facesdir() {
+ "$::prefix/usr/share/mga/faces/";
}
sub face2png {
- my ($face, $prefix) = @_;
- facesdir($prefix) . $face . ".png";
+ my ($face) = @_;
+ facesdir() . $face . ".png";
}
-sub facesnames {
- my ($prefix) = @_;
- my $dir = facesdir($prefix);
+sub facesnames() {
+ my $dir = facesdir();
my @l = grep { /^[A-Z]/ } all($dir);
map { if_(/(.*)\.png/, $1) } (@l ? @l : all($dir));
}
sub addKdmIcon {
- my ($prefix, $user, $icon) = @_;
- my $dest = "$prefix/usr/share/faces/$user.png";
- eval { cp_af(facesdir($prefix) . $icon . ".png", $dest) } if $icon;
+ my ($user, $icon) = @_;
+ my $dest = "$::prefix/usr/share/faces/$user.png";
+ eval { cp_af(facesdir() . $icon . ".png", $dest) } if $icon;
}
-sub allocUsers {
- my ($prefix, $users) = @_;
- my @m = my @l = facesnames($prefix);
+sub alloc_user_faces {
+ 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}");
@@ -51,291 +48,931 @@ sub allocUsers {
}
}
-sub addUsers {
- my ($prefix, $users) = @_;
- my $msec = "$prefix/etc/security/msec";
+sub create_user {
+ my ($u, $authentication) = @_;
+
+ my @existing = stat("$::prefix/home/$u->{name}");
- allocUsers($prefix, $users);
- foreach my $u (@$users) {
- substInFile { s/^$u->{name}\n//; $_ .= "$u->{name}\n" if eof } "$msec/user.conf" if -d $msec;
- addKdmIcon($prefix, $u->{name}, delete $u->{auto_icon} || $u->{icon});
+ if (!getpwnam($u->{name})) {
+ my $uid = $u->{uid} || $existing[4];
+ if ($uid && getpwuid($uid)) {
+ undef $uid; #- suggested uid already in use
+ }
+ my $gid = $u->{gid} || $existing[5] || int getgrnam($u->{name});
+ if ($gid) {
+ if (getgrgid($gid)) {
+ undef $gid if getgrgid($gid) ne $u->{name};
+ } else {
+ run_program::rooted($::prefix, 'groupadd', '-g', $gid, $u->{name});
+ }
+ } elsif ($u->{rename_from}) {
+ run_program::rooted($::prefix, 'groupmod', '-n', $u->{name}, $u->{rename_from});
+ }
+
+ require authentication;
+ my $symlink_home_from = $u->{rename_from} && (getpwnam($u->{rename_from}))[7];
+ run_program::raw({ root => $::prefix, sensitive_arguments => 1 },
+ ($u->{rename_from} ? 'usermod' : 'adduser'),
+ '-p', authentication::user_crypted_passwd($u, $authentication),
+ if_($uid, '-u', $uid), if_($gid, '-g', $gid),
+ if_($u->{realname}, '-c', $u->{realname}),
+ if_($u->{home}, '-d', $u->{home}, if_($u->{rename_from}, '-m')),
+ if_($u->{shell}, '-s', $u->{shell}),
+ ($u->{rename_from}
+ ? ('-l', $u->{name}, $u->{rename_from})
+ : $u->{name}));
+ symlink($u->{home}, $symlink_home_from) if $symlink_home_from;
+ eval { run_program::rooted($::prefix, 'systemctl', 'try-restart', 'accounts-daemon.service') };
+ }
+
+ my (undef, undef, $uid, $gid, undef, undef, undef, $home) = getpwnam($u->{name});
+
+ if (@existing && $::isInstall && ($uid != $existing[4] || $gid != $existing[5])) {
+ log::l("chown'ing $home from $existing[4].$existing[5] to $uid.$gid");
+ eval { common::chown_('recursive', $uid, $gid, "$::prefix$home") };
}
- run_program::rooted($prefix, "/usr/share/msec/grpuser.sh --refresh >/dev/null");
}
-sub crypt {
- my ($password, $md5) = @_;
- crypt($password, $md5 ? '$1$' . salt(8) : salt(2));
+sub add_users {
+ my ($users, $authentication) = @_;
+
+ alloc_user_faces($users);
+
+ foreach (@$users) {
+ create_user($_, $authentication);
+ run_program::rooted($::prefix, "usermod", "-G", join(",", @{$_->{groups}}), $_->{name}) if !is_empty_array_ref($_->{groups});
+ addKdmIcon($_->{name}, delete $_->{auto_icon} || $_->{icon});
+ }
}
-sub enableShadow {
- my ($prefix) = @_;
- run_program::rooted($prefix, "pwconv") or log::l("pwconv failed");
- run_program::rooted($prefix, "grpconv") or log::l("grpconv failed");
+
+sub install_bootloader_pkgs {
+ my ($do_pkgs, $b) = @_;
+
+ bootloader::ensure_pkg_is_installed($do_pkgs, $b);
+ install_acpi_pkgs($do_pkgs, $b);
}
-sub enableMD5Shadow { #- NO MORE USED
- my ($prefix, $shadow, $md5) = @_;
- substInFile {
- if (/^password.*pam_pwdb.so/) {
- s/\s*shadow//; s/\s*md5//;
- s/$/ shadow/ if $shadow;
- s/$/ md5/ if $md5;
+
+sub install_acpi_pkgs {
+ my ($do_pkgs, $b) = @_;
+
+ my $acpi = bootloader::get_append_with_key($b, 'acpi');
+ my $use_acpi = !member($acpi, 'off', 'ht');
+ if ($use_acpi) {
+ $do_pkgs->ensure_files_are_installed([ [ qw(acpi acpi) ], [ qw(acpid acpid) ] ], $::isInstall);
+ }
+ require services;
+ services::set_status($_, $use_acpi, $::isInstall) foreach qw(acpid);
+}
+
+sub setupBootloaderBeforeStandalone {
+ my ($do_pkgs, $b, $all_hds, $fstab) = @_;
+ require keyboard;
+ my $keyboard = keyboard::read_or_default();
+ my $allow_fb = listlength(cat_("/proc/fb"));
+ my $cmdline = cat_('/proc/cmdline');
+ my $vga_fb = first($cmdline =~ /\bvga=(\S+)/);
+ my $splash = $cmdline =~ /\bsplash\b/;
+ my $quiet = $cmdline =~ /\bquiet\b/;
+ setupBootloaderBefore($do_pkgs, $b, $all_hds, $fstab, $keyboard, $allow_fb, $vga_fb, $splash, $quiet);
+}
+
+sub setupBootloaderBefore {
+ my ($do_pkgs, $bootloader, $all_hds, $fstab, $keyboard, $allow_fb, $vga_fb, $splash, $quiet) = @_;
+ require bootloader;
+
+ #- auto_install backward compatibility
+ #- one should now use {message_text}
+ if ($bootloader->{message} =~ m!^[^/]!) {
+ $bootloader->{message_text} = delete $bootloader->{message};
+ }
+
+ if (cat_("/proc/cmdline") =~ /mem=nopentium/) {
+ bootloader::set_append_with_key($bootloader, mem => 'nopentium');
+ }
+ if (cat_("/proc/cmdline") =~ /\b(pci)=(\S+)/) {
+ bootloader::set_append_with_key($bootloader, $1, $2);
+ }
+ if (my ($acpi) = cat_("/proc/cmdline") =~ /\bacpi=(\w+)/) {
+ if ($acpi eq 'ht') {
+ #- the user is using the default, which may not be the best
+ my $year = detect_devices::computer_info()->{BIOS_Year};
+ if ($year >= 2002) {
+ log::l("forcing ACPI on recent bios ($year)");
+ $acpi = '';
+ }
}
- } grep { -r $_ } map { "$prefix/etc/pam.d/$_" } qw(login rlogin passwd);
+ bootloader::set_append_with_key($bootloader, acpi => $acpi);
+ }
+ if (cat_("/proc/cmdline") =~ /\bnoapic/) {
+ bootloader::set_append_simple($bootloader, 'noapic');
+ }
+ if (cat_("/proc/cmdline") =~ /\bnoresume/) {
+ bootloader::set_append_simple($bootloader, 'noresume');
+ } elsif (bootloader::get_append_simple($bootloader, 'noresume')) {
+ } else {
+ if (my ($biggest_swap) = sort { $b->{size} <=> $a->{size} } grep { isSwap($_) } @$fstab) {
+ my $biggest_swap_dev = fs::wild_device::from_part('', $biggest_swap);
+ bootloader::set_append_with_key($bootloader, resume => $biggest_swap_dev);
+ mkdir_p("$::prefix/etc/dracut.conf.d");
+ output("$::prefix/etc/dracut.conf.d/51-mageia-resume.conf", qq(add_device+=" $biggest_swap_dev "\n));
+ }
+ }
+
+ #- set nokmsboot if a conflicting driver is configured.
+ if (-x "$::prefix/sbin/display_driver_helper" && !run_program::rooted($::prefix, "/sbin/display_driver_helper", "--is-kms-allowed")) {
+ bootloader::set_append_simple($bootloader, 'nokmsboot');
+ }
+
+ #- check for valid fb mode to enable a default boot with frame buffer.
+ my $vga = $allow_fb && (!detect_devices::matching_desc__regexp('3D Rage LT') &&
+ !detect_devices::matching_desc__regexp('Rage Mobility [PL]') &&
+ !detect_devices::matching_desc__regexp('i740') &&
+ !detect_devices::matching_desc__regexp('Matrox') &&
+ !detect_devices::matching_desc__regexp('Tseng.*ET6\d00') &&
+ !detect_devices::matching_desc__regexp('SiS.*SG86C2.5') &&
+ !detect_devices::matching_desc__regexp('SiS.*559[78]') &&
+ !detect_devices::matching_desc__regexp('SiS.*300') &&
+ !detect_devices::matching_desc__regexp('SiS.*540') &&
+ !detect_devices::matching_desc__regexp('SiS.*6C?326') &&
+ !detect_devices::matching_desc__regexp('SiS.*6C?236') &&
+ !detect_devices::matching_desc__regexp('Voodoo [35]|Voodoo Banshee') && #- 3d acceleration seems to bug in fb mode
+ !detect_devices::matching_desc__regexp('828[14][05].* CGC') #- i810 & i845 now have FB support during install but we disable it afterwards
+ );
+ my $force_vga = $allow_fb && (detect_devices::matching_desc__regexp('SiS.*630') || #- SiS 630 need frame buffer.
+ detect_devices::matching_desc__regexp('GeForce.*Integrated') #- needed for fbdev driver (hack).
+ );
+
+ #- propose the default fb mode for kernel fb, if bootsplash is installed.
+ my $need_fb = -e "$::prefix/usr/share/bootsplash/scripts/make-boot-splash";
+ bootloader::suggest($bootloader, $all_hds,
+ vga_fb => ($force_vga || $vga && $need_fb) && $vga_fb,
+ splash => $splash,
+ quiet => $quiet);
+
+ if (is_uefi()) {
+ if (my @esp = grep { $_->{mntpoint} eq '/boot/EFI' } @$fstab) {
+ $bootloader->{removable} = $esp[0]{is_removable};
+ }
+ } else {
+ if (my $root_part = fs::get::root($fstab)) {
+ $bootloader->{removable} = $root_part->{is_removable};
+ }
+ }
+ $bootloader->{default_to_no_probe} = 1 if $bootloader->{removable};
+
+ $bootloader->{keytable} ||= keyboard::keyboard2kmap($keyboard);
+ log::l("setupBootloaderBefore end");
}
sub setupBootloader {
- my ($in, $b, $all_hds, $fstab, $security, $prefix, $more) = @_;
- my $hds = $all_hds->{hds};
+ my ($in, $b, $all_hds, $fstab, $security) = @_;
- $more++ if $b->{bootUnsafe};
- $more = 2 if arch() =~ /ppc/; #- no auto for PPC yet
-
- if (!$::expert && $more < 1) {
- #- automatic
- } elsif (!$::expert && arch() !~ /ia64/) {
- my @l = (__("First sector of drive (MBR)"), __("First sector of boot partition"));
-
- $in->set_help('setupBootloaderBeginner') unless $::isStandalone;
- if (arch() =~ /sparc/) {
- $b->{use_partition} = $in->ask_from_list_(_("SILO Installation"),
- _("Where do you want to install the bootloader?"),
- \@l, $l[$b->{use_partition}]) or return;
- } elsif (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";
- }
+ 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, $all_hds->{hds}) or goto general;
+ {
+ local $::Wizard_finished = 1 if $::isStandalone;
+ if (bootloader::main_method($b->{method}) eq 'grub2') {
+ setupBootloader__grub2($in, $b, $all_hds, $fstab) or goto general;
} else {
- my $boot = $hds->[0]{device};
- my $onmbr = "/dev/$boot" eq $b->{boot};
- $b->{boot} = "/dev/" . ($in->ask_from_list_(_("LILO/grub Installation"),
- _("Where do you want to install the bootloader?"),
- \@l, $l[!$onmbr]) eq $l[0]
- ? $boot : fsedit::get_root($fstab, 'boot')->{device});
+ setupBootloader__entries($in, $b, $all_hds, $fstab) or goto general;
}
- } else {
- $in->set_help(arch() =~ /sparc/ ? "setupSILOGeneral" : arch() =~ /ppc/ ? 'setupYabootGeneral' :"setupBootloaderGeneral") unless $::isStandalone; #- TO MERGE ?
-
- my @silo_install_lang = (_("First sector of drive (MBR)"), _("First sector of boot partition"));
- my $silo_install_lang = $silo_install_lang[$b->{use_partition}];
-
- my %bootloaders = (if_(exists $b->{methods}{silo},
- __("SILO") => sub { $b->{methods}{silo} = 1 }),
- if_(exists $b->{methods}{lilo},
- __("LILO with text menu") => sub { $b->{methods}{lilo} = "lilo-menu" },
- __("LILO with graphical menu") => sub { $b->{methods}{lilo} = "lilo-graphic" }),
- if_(exists $b->{methods}{grub},
- #- put lilo if grub is chosen, so that /etc/lilo.conf is generated
- __("Grub") => sub { $b->{methods}{grub} = 1;
- exists $b->{methods}{lilo}
- and $b->{methods}{lilo} = "lilo-menu" }),
- if_(exists $b->{methods}{loadlin},
- __("Boot from DOS/Windows (loadlin)") => sub { $b->{methods}{loadlin} = 1 }),
- if_(exists $b->{methods}{yaboot},
- __("Yaboot") => sub { $b->{methods}{yaboot} = 1 }),
- );
- my $bootloader = arch() =~ /sparc/ ? __("SILO") : arch() =~ /ppc/ ? __("Yaboot") : __("LILO with graphical menu");
- my $profiles = bootloader::has_profiles($b);
- my $memsize = bootloader::get_append($b, 'mem');
-
- $b->{vga} ||= 'Normal';
- if (arch !~ /ppc/) {
- $in->ask_from('', _("Bootloader main options"), [
-{ label => _("Bootloader to use"), val => \$bootloader, list => [ keys(%bootloaders) ], format => \&translate },
- arch() =~ /sparc/ ? (
-{ label => _("Bootloader installation"), val => \$silo_install_lang, list => \@silo_install_lang },
-) : if_(arch() !~ /ia64/,
-{ label => _("Boot device"), val => \$b->{boot}, list => [ map { "/dev/$_" } (map { $_->{device} } (@$hds, grep { !isFat($_) } @$fstab)), detect_devices::floppies_dev() ], not_edit => !$::expert },
-{ label => _("LBA (doesn't work on old BIOSes)"), val => \$b->{lba32}, type => "bool", text => "lba", advanced => 1 },
-{ label => _("Compact"), val => \$b->{compact}, type => "bool", text => _("compact"), advanced => 1 },
-{ label => _("Video mode"), val => \$b->{vga}, list => [ keys %bootloader::vga_modes ], not_edit => !$::expert, advanced => 1 },
-),
-{ label => _("Delay before booting default image"), val => \$b->{timeout} },
- if_($security >= 4,
-{ label => _("Password"), val => \$b->{password}, hidden => 1 },
-{ label => _("Password (again)"), val => \$b->{password2}, hidden => 1 },
-{ label => _("Restrict command line options"), val => \$b->{restricted}, type => "bool", text => _("restrict") },
- ),
-{ label => _("Clean /tmp at each boot"), val => \$b->{CLEAN_TMP}, type => 'bool', advanced => 1 },
-{ label => _("Precise RAM size if needed (found %d MB)", availableRamMB()), val => \$memsize, advanced => 1 },
- if_(detect_devices::isLaptop,
-{ label => _("Enable multi profiles"), val => \$profiles, type => 'bool', advanced => 1 },
- ),
-],
- complete => sub {
- !$memsize || $memsize =~ /K$/ || $memsize =~ s/^(\d+)M?$/$1M/i or $in->ask_warn('', _("Give the ram size in MB")), return 1;
-#- $security > 4 && length($b->{password}) < 6 and $in->ask_warn('', _("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('', _("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('', [ _("The passwords do not match"), _("Please try again") ]), return 1;
- 0;
- }
- ) or return 0;
+ }
+ 1;
+}
+
+sub setupBootloaderUntilInstalled {
+ my ($in, $b, $all_hds, $fstab, $security) = @_;
+ do {
+ my $before = fs::fstab_to_string($all_hds);
+ setupBootloader($in, $b, $all_hds, $fstab, $security) or $in->exit;
+ if ($before ne fs::fstab_to_string($all_hds)) {
+ #- ovitters: This fstab comparison was needed for optionally
+ #- setting up /tmp using tmpfs. That code was removed. Not removing
+ #- this code as I'm not sure if something still relies on this
+ fs::write_fstab($all_hds);
+ }
+ } while !installBootloader($in, $b, $all_hds);
+}
+
+sub installBootloader {
+ my ($in, $b, $all_hds) = @_;
+ return if detect_devices::is_xbox();
+
+ return 1 if arch() =~ /arm/;
+
+ install_bootloader_pkgs($in->do_pkgs, $b);
+
+ retry:
+ eval {
+ my $_w = $in->wait_message(N("Please wait"), N("Bootloader installation in progress"));
+ bootloader::install($b, $all_hds);
+ };
+
+ if (my $err = $@) {
+ $err =~ /wizcancel/ and return;
+ $err =~ s/^\w+ failed// or die;
+ $err = formatError($err);
+ while ($err =~ s/^Warning:.*//m) {}
+ if (my ($dev) = $err =~ /^Reference:\s+disk\s+"(.*?)".*^Is the above disk an NT boot disk?/ms) {
+ if ($in->ask_yesorno('',
+formatAlaTeX(N("LILO wants to assign a new Volume ID to drive %s. However, changing
+the Volume ID of a Windows NT, 2000, or XP boot disk is a fatal Windows error.
+This caution does not apply to Windows 95 or 98, or to NT data disks.
+
+Assign a new Volume ID?", $dev)))) {
+ $b->{force_lilo_answer} = 'n';
+ } else {
+ $b->{'static-bios-codes'} = 1;
+ }
+ goto retry;
} else {
- $b->{boot} = $partition_table_mac::bootstrap_part;
- $in->ask_from('', _("Bootloader main options"), [
- { label => _("Bootloader to use"), val => \$bootloader, list => [ keys(%bootloaders) ], format => \&translate },
- { label => _("Init Message"), val => \$b->{initmsg} },
- { label => _("Boot device"), val => \$b->{boot}, list => [ map { "/dev/$_" } (map { $_->{device} } (grep { isAppleBootstrap($_) } @$fstab))], not_edit => !$::expert },
- { label => _("Open Firmware Delay"), val => \$b->{delay} },
- { label => _("Kernel Boot Timeout"), val => \$b->{timeout} },
- { label => _("Enable CD Boot?"), val => \$b->{enablecdboot}, type => "bool" },
- { label => _("Enable OF Boot?"), val => \$b->{enableofboot}, type => "bool" },
- { label => _("Default OS?"), val=> \$b->{defaultos}, list => [ 'linux', 'macos', 'macosx', 'darwin' ] },
- ]) or return 0;
+ $in->ask_warn('', [ N("Installation of bootloader failed. The following error occurred:"), $err ]);
+ return;
}
-
- $b->{methods}{$_} = 0 foreach keys %{$b->{methods}};
- $bootloaders{$bootloader} and $bootloaders{$bootloader}->();
- #- at least one method
- grep_each { $::b } %{$b->{methods}} or return;
-
- $b->{use_partition} = $silo_install_lang eq _("First sector of drive (MBR)") ? 0 : 1;
- $b->{vga} = $bootloader::vga_modes{$b->{vga}} || $b->{vga};
-
- bootloader::set_profiles($b, $profiles);
- bootloader::add_append($b, "mem", $memsize);
- }
-
- while ($::expert || $more > 1) {
- $in->set_help(arch() =~ /sparc/ ? 'setupSILOAddEntry' : arch() =~ /ppc/ ? 'setupYabootAddEntry' : 'setupBootloaderAddEntry') unless $::isStandalone;
- my ($c, $e);
- $in->ask_from_(
- {
- messages =>
-_("Here are the different entries.
-You can add some more or change the existing ones."),
- ok => '',
-},
- [ { val => \$e, format => sub {
- my ($e) = @_;
- ref $e ?
- "$e->{label} ($e->{kernel_or_dev})" . ($b->{default} eq $e->{label} && " *") :
- translate($e);
- }, list => [ @{$b->{entries}} ] },
- (map { my $s = $_; { val => translate($_), clicked_may_quit => sub { $c = $s; 1 } } } (__("Modify"), __("Add"), __("Done"))),
- ]
- );
- !$c || $c eq "Done" and last;
-
- if ($c eq "Add") {
- my @labels = map { $_->{label} } @{$b->{entries}};
- my $prefix;
- if ($in->ask_from_list_('', _("Which type of entry do you want to add?"),
- [ __("Linux"), arch() =~ /sparc/ ? __("Other OS (SunOS...)") : arch() =~ /ppc/ ?
- __("Other OS (MacOS...)") : __("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";;
+ }
+ 1;
+}
+
+
+sub setupBootloader_simple {
+ my ($in, $b, $all_hds, $fstab, $security) = @_;
+ my $hds = $all_hds->{hds};
+
+ require bootloader;
+ bootloader::ensafe_first_bios_drive($hds)
+ || $b->{bootUnsafe} or return 1; #- default is good enough
+
+ if (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) = @_;
+
+ if (!is_empty_hash_ref($b->{bios})) {
+ #- some bios mapping already there
+ return 1;
+ } elsif (bootloader::mixed_kind_of_disks($hds) && $b->{boot} =~ /\d$/) { #- on a partition
+ # see below
+ } else {
+ return 1;
+ }
+
+ log::l("_ask_boot_bios_drive");
+ 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 disk 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 _ask_mbr_or_not {
+ my ($in, $default, @l) = @_;
+ $in->ask_from_({ title => N("Bootloader Installation"),
+ interactive_help_id => 'setupBootloaderBeginner',
+ },
+ [
+ { label => N("Where do you want to install the bootloader?"), title => 1 },
+ { val => \$default, list => \@l, format => sub { $_[0][0] }, type => 'list' },
+ ]
+ );
+ $default;
+}
+
+sub setupBootloader__mbr_or_not {
+ my ($in, $b, $hds, $fstab) = @_;
+
+ log::l("setupBootloader__mbr_or_not");
+
+ my $floppy = detect_devices::floppy();
+
+ my @l = (
+ bootloader::ensafe_first_bios_drive($hds) ?
+ (map { [ N("First sector (MBR) of drive %s", partition_table::description($_)) => '/dev/' . $_->{device} ] } @$hds)
+ :
+ [ N("First sector of drive (MBR)") => '/dev/' . $hds->[0]{device} ],
+
+ [ N("First sector of the root partition") => '/dev/' . fs::get::root($fstab, 'boot')->{device} ],
+ if_($floppy,
+ [ N("On Floppy") => "/dev/$floppy" ],
+ ),
+ [ N("Skip") => '' ],
+ );
+
+ my $default = find { $_->[1] eq $b->{boot} } @l;
+ if (!$::isInstall) {
+ $default = _ask_mbr_or_not($in, $default, @l);
+ }
+ my $new_boot = $default->[1];
+
+ #- remove bios mapping if the user changed the boot device
+ delete $b->{bios} if $new_boot && $new_boot ne $b->{boot};
+ $b->{boot} = $new_boot or return;
+ 1;
+}
+
+sub setupBootloader__general {
+ my ($in, $b, $all_hds, $fstab, $_security) = @_;
+
+ return if detect_devices::is_xbox();
+ my @method_choices = bootloader::method_choices($all_hds);
+ my $prev_force_acpi = my $force_acpi = bootloader::get_append_with_key($b, 'acpi') !~ /off|ht/;
+ my $prev_enable_apic = my $enable_apic = !bootloader::get_append_simple($b, 'noapic');
+ my $prev_enable_lapic = my $enable_lapic = !bootloader::get_append_simple($b, 'nolapic');
+ my $prev_enable_smp = my $enable_smp = !bootloader::get_append_simple($b, 'nosmp');
+ my $prev_boot = $b->{boot};
+ my $prev_method = $b->{method};
+
+ $b->{password2} ||= $b->{password} ||= '';
+ $::Wizard_title = N("Boot Style Configuration");
+ my (@boot_devices, %boot_devices);
+ if (is_uefi()) {
+ @boot_devices = 'ESP';
+ %boot_devices = (ESP => N("EFI System Partition"));
+ } else {
+ foreach (bootloader::allowed_boot_parts($b, $all_hds)) {
+ my $dev = "/dev/$_->{device}";
+ push @boot_devices, $dev;
+ my $name = $_->{mntpoint} || $_->{info} || $_->{device_LABEL};
+ unless ($name) {
+ $name = formatXiB($_->{size}*512) . " " if $_->{size};
+ $name .= $_->{fs_type};
}
- $e->{label} = $prefix;
- for (my $nb = 0; member($e->{label}, @labels); $nb++) { $e->{label} = "$prefix-$nb" }
+ $boot_devices{$dev} = $name ? "$dev ($name)" : $dev;
}
- my %old_e = %$e;
+ }
+
+ $in->ask_from_({ #messages => N("Bootloader main options"),
+ title => N("Bootloader main options"),
+ interactive_help_id => 'setupBootloader',
+ }, [
+ #title => N("Bootloader main options"),
+ { label => N("Bootloader"), title => 1 },
+ { label => N("Bootloader to use"), val => \$b->{method},
+ list => \@method_choices, format => \&bootloader::method2text },
+ { label => N("Boot device"), val => \$b->{boot}, list => \@boot_devices, allow_empty_list => 1,
+ format => sub { $boot_devices{$_[0]} } },
+ { label => N("Main options"), title => 1 },
+ { label => N("Delay before booting default image"), val => \$b->{timeout} },
+ { text => N("Enable ACPI"), val => \$force_acpi, type => 'bool', advanced => 1 },
+ { text => N("Enable SMP"), val => \$enable_smp, type => 'bool', advanced => 1 },
+ { text => N("Enable APIC"), val => \$enable_apic, type => 'bool', advanced => 1,
+ disabled => sub { !$enable_lapic } },
+ { text => N("Enable Local APIC"), val => \$enable_lapic, type => 'bool', advanced => 1 },
+ { label => N("Security"), title => 1 },
+ { label => N("Password"), val => \$b->{password}, hidden => 1,
+ validate => sub {
+ my $ok = $b->{password} eq $b->{password2}
+ or $in->ask_warn('', [ N("The passwords do not match"), N("Please try again") ]);
+ my $ok2 = !($b->{password} && $b->{method} eq 'grub-graphic')
+ or $in->ask_warn('', N("You cannot use a password with %s",
+ bootloader::method2text($b->{method})));
+ $ok && $ok2;
+ } },
+ { label => N("Password (again)"), val => \$b->{password2}, hidden => 1 },
+ ]) or return 0;
+
+ #- remove bios mapping if the user changed the boot device
+ delete $b->{bios} if $b->{boot} ne $prev_boot;
+
+ if ($b->{boot} =~ m!/dev/md\d+$!) {
+ $b->{'raid-extra-boot'} = 'mbr';
+ } else {
+ delete $b->{'raid-extra-boot'} if $b->{'raid-extra-boot'} eq 'mbr';
+ }
+
+ bootloader::ensure_pkg_is_installed($in->do_pkgs, $b) or goto &setupBootloader__general;
+
+ bootloader::suggest_message_text($b) if ! -e "$::prefix/boot/message-text"; #- in case we switch from grub to lilo
+
+ if ($prev_force_acpi != $force_acpi) {
+ bootloader::set_append_with_key($b, acpi => ($force_acpi ? '' : 'ht'));
+ }
+
+ if ($prev_enable_smp != $enable_smp) {
+ ($enable_smp ? \&bootloader::remove_append_simple : \&bootloader::set_append_simple)->($b, 'nosmp');
+ }
+
+ if ($prev_enable_apic != $enable_apic) {
+ ($enable_apic ? \&bootloader::remove_append_simple : \&bootloader::set_append_simple)->($b, 'noapic');
+ ($enable_apic ? \&bootloader::set_append_simple : \&bootloader::remove_append_simple)->($b, 'apic');
+ }
+ if ($prev_enable_lapic != $enable_lapic) {
+ ($enable_lapic ? \&bootloader::remove_append_simple : \&bootloader::set_append_simple)->($b, 'nolapic');
+ ($enable_lapic ? \&bootloader::set_append_simple : \&bootloader::remove_append_simple)->($b, 'lapic');
+ }
+
+ if (bootloader::main_method($prev_method) eq 'lilo' &&
+ bootloader::main_method($b->{method}) eq 'grub') {
+ log::l("switching for lilo to grub, ensure we don't read lilo.conf anymore");
+ renamef("$::prefix/etc/lilo.conf", "$::prefix/etc/lilo.conf.unused");
+ }
+ if ($prev_method eq 'refind' && $b->{method} ne 'refind') {
+ log::l("switching from rEFInd, ensure we don't detect refind as the active boot method");
+ renamef("$::prefix/boot/refind_linux.conf", "$::prefix/boot/refind_linux.conf.unused");
+ }
+ if ($b->{method} eq 'refind') {
+ if (bootloader::main_method($prev_method) eq 'grub2') {
+ #- grub2 doesn't provide any entries we can use, so revert to the defaults
+ %$b = ();
+ setupBootloaderBeforeStandalone($in->do_pkgs, $b, $all_hds, $fstab);
+ $b->{method} = 'refind';
+ $b->{boot} = 'ESP';
+ undef $b->{default};
+ }
+ setupBootloader__refind($in, $b, $fstab);
+ } else {
+ 1;
+ }
+}
+
+sub setupBootloader__refind {
+ my ($in, $b, $fstab) = @_;
+
+ my $already_in_refind = -e "$::prefix/boot/EFI/EFI/refind/refind.conf";
+ my $already_in_default = -e "$::prefix/boot/EFI/EFI/BOOT/refind.conf";
+ my $already_installed = $already_in_refind || $already_in_default;
+
+ my $update_esp = !$already_installed;
+ my $as_default = $already_in_default || $b->{removable};
+
+ if (!defined $b->{banner_path}) {
+ #- We haven't yet read any existing configuration, either because we are doing a clean
+ #- install or because we are switching from a different bootloader. Try to read it now.
+ #- Even if we are doing a clean install, rEFInd may already be installed in the ESP.
+ bootloader::read_refind_config($b);
+ }
+
+ my $use_nvram = $b->{use_nvram};
+ my $banner_path = $b->{banner_path};
+ my $banner_scale = $b->{banner_scale};
+ my $banner_type = $banner_path eq 'refind_banner.png' ? 'banner'
+ : $banner_path eq 'mageia_theme.png' ? 'theme'
+ : 'custom';
+ $in->ask_from_(
+ {
+ title => N("Bootloader Configuration"),
+ interactive_help_id => 'setupBootloader',
+ },
+ [
+ { label => N("Install Options"), title => 1, },
+ { text => N("Install or update rEFInd in the EFI system partition"),
+ val => \$update_esp, type => 'bool', disabled => sub { !$already_installed } },
+ { text => N("Install in /EFI/BOOT (removable device or workaround for some BIOSs)"),
+ val => \$as_default, type => 'bool', disabled => sub { !$update_esp } },
+ { text => N("Configure rEFInd to store its variables in the EFI NVRAM"),
+ val => \$use_nvram, type => 'bool' },
+ { label => N("Background"), title => 1, },
+ { val => \$banner_type, type => 'combo', list => [ 'banner', 'theme', 'custom' ],
+ format => sub {
+ my ($choice) = @_;
+ +{
+ 'banner' => N("rEFInd banner"),
+ 'theme' => N("Mageia theme"),
+ 'custom' => N("Custom"),
+ }->{$choice};
+ },
+ changed => sub {
+ if ($banner_type eq 'banner') {
+ $banner_path = 'refind_banner.png';
+ $banner_scale = 'noscale';
+ } elsif ($banner_type eq 'theme') {
+ $banner_path = 'mageia_theme.png';
+ $banner_scale = 'fillscreen';
+ }
+ }
+ },
+ { val => \$banner_path, type => 'entry', disabled => sub { $banner_type ne 'custom' } },
+ { val => \$banner_scale, type => 'combo', list => [ 'noscale', 'fillscreen' ],
+ format => sub {
+ my ($choice) = @_;
+ +{
+ 'noscale' => N("No scaling"),
+ 'fillscreen' => N("Scale to fit"),
+ }->{$choice};
+ }
+ },
+ ]
+ ) or return 0;
+
+ if ($update_esp) {
+ $b->{install_mode} = $as_default ? 'as_default' : 'as_refind';
+ } else {
+ $b->{install_mode} = $as_default ? 'no_install' : 'nvram_only';
+ }
+ $b->{use_nvram} = $use_nvram;
+ $b->{banner_path} = $banner_path;
+ $b->{banner_scale} = $banner_scale;
+ if (my @esp = grep { $_->{mntpoint} eq '/boot/EFI' } @$fstab) {
+ $b->{esp_device} = $esp[0]{real_device} || fs::wild_device::from_part('', $esp[0]);
+ }
+ 1;
+}
+
+sub setupBootloader__entries {
+ my ($in, $b, $all_hds, $fstab) = @_;
+
+ require Xconfig::resolution_and_depth;
+
+ my $Modify = sub {
+ require network::network; #- to list network profiles
+ my ($e) = @_;
my $default = my $old_default = $e->{label} eq $b->{default};
+ my $vga = Xconfig::resolution_and_depth::from_bios($e->{vga});
+ my ($append, $netprofile) = bootloader::get_append_netprofile($e);
+
+ my %hd_infos = map { $_->{device} => $_->{info} } fs::get::hds($all_hds);
+ my %root_descr = map {
+ my $info = delete $hd_infos{$_->{rootDevice}};
+ my $dev = "/dev/$_->{device}";
+ my $hint = $info || $_->{info} || $_->{device_LABEL};
+ my $info_ = $hint ? "$dev ($hint)" : $dev;
+ ($dev => $info_, fs::wild_device::from_part('', $_) => $info_);
+ } @$fstab;
my @l;
- if ($e->{type} eq "image") {
+ if ($b->{method} eq 'refind') {
+ @l = (
+ { label => N("Label"), val => \$e->{label} },
+ { label => N("Append"), val => \$append },
+ { label => N("Video mode"), val => \$vga, list => [ '', Xconfig::resolution_and_depth::bios_vga_modes() ],
+ format => \&Xconfig::resolution_and_depth::to_string, advanced => 1 },
+ );
+ } elsif ($e->{type} eq "image") {
@l = (
-{ label => _("Image"), val => \$e->{kernel_or_dev}, list => [ map { s/$prefix//; $_ } glob_("$prefix/boot/vmlinuz*") ], not_edit => 0 },
-{ label => _("Root"), val => \$e->{root}, list => [ map { "/dev/$_->{device}" } @$fstab ], not_edit => !$::expert },
-{ label => _("Append"), val => \$e->{append} },
- if_(arch !~ /ppc|ia64/,
-{ label => _("Video mode"), val => \$e->{vga}, list => [ keys %bootloader::vga_modes ], not_edit => !$::expert },
-),
-{ label => _("Initrd"), val => \$e->{initrd}, list => [ map { s/$prefix//; $_ } glob_("$prefix/boot/initrd*") ] },
-{ label => _("Read-write"), val => \$e->{'read-write'}, type => 'bool' }
+{ 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 { fs::wild_device::from_part('', $_) } grep { !isSwap($_) } @$fstab ], format => sub { $root_descr{$_[0]} } },
+{ label => N("Append"), val => \$append },
+ if_($e->{xen},
+{ label => N("Xen append"), val => \$e->{xen_append} }
+ ),
+ if_($b->{password}, { label => N("Requires password to boot"), val => \$e->{lock}, type => "bool" }),
+{ 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 },
+{ label => N("Network profile"), val => \$netprofile, list => [ sort(uniq('', $netprofile, network::network::netprofile_list())) ], advanced => 1 },
);
- @l = @l[0..2] unless $::expert;
} else {
@l = (
-{ label => _("Root"), val => \$e->{kernel_or_dev}, list => [ map { "/dev/$_->{device}" } @$fstab ], not_edit => !$::expert },
-if_(arch() !~ /sparc|ppc|ia64/,
-{ label => _("Table"), val => \$e->{table}, list => [ '', map { "/dev/$_->{device}" } @$hds ], not_edit => !$::expert },
-{ label => _("Unsafe"), val => \$e->{unsafe}, type => 'bool' }
-),
+{ label => N("Root"), val => \$e->{kernel_or_dev}, list => [ map { "/dev/$_->{device}" } @$fstab, detect_devices::floppies() ] },
);
- @l = $l[0] unless $::expert;
}
-if (arch() !~ /ppc/) {
- @l = (
-{ label => _("Label"), val => \$e->{label} },
-@l,
-{ label => _("Default"), val => \$default, type => 'bool' },
- );
-} else {
- @l = ({ label => _("Label"), val => \$e->{label}, list=> ['macos', 'macosx', 'darwin'] },
- @l );
- if ($e->{type} eq "image") {
- @l = ({ label => _("Label"), val => \$e->{label} },
- $::expert ? @l[1..4] : (@l[1..2], { label => _("Append"), val => \$e->{append} }) ,
- if_($::expert, { label => _("Initrd-size"), val => \$e->{initrdsize}, list => [ '', '4096', '8192', '16384', '24576' ] }),
- if_($::expert, $l[5]),
- { label => _("NoVideo"), val => \$e->{novideo}, type => 'bool' },
- { label => _("Default"), val => \$default, type => 'bool' }
- );
+ if ($b->{method} ne 'refind') {
+ @l = (
+ { label => N("Label"), val => \$e->{label} },
+ @l,
+ { text => N("Default"), val => \$default, type => 'bool' },
+ );
}
-}
-
- if ($in->ask_from_(
- {
- if_($c ne "Add", cancel => _("Remove entry")),
+ $in->ask_from_(
+ {
+ interactive_help_id => 'setupBootloaderAddEntry',
callbacks => {
complete => sub {
- $e->{label} or $in->ask_warn('', _("Empty label not allowed")), return 1;
- member($e->{label}, map { $_->{label} } grep { $_ != $e } @{$b->{entries}}) and $in->ask_warn('', _("This label is already used")), return 1;
+ $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)) {
- $b->{default} = $old_default || $default ? $default && $e->{label} : $b->{default};
- $e->{vga} = $bootloader::vga_modes{$e->{vga}} || $e->{vga};
- require bootloader;
- bootloader::configure_entry($prefix, $e); #- hack to make sure initrd file are built.
+ } } }, \@l) or return;
+
+ $b->{default} = $old_default || $default ? $default && $e->{label} : $b->{default};
+ my $new_vga = ref($vga) ? $vga->{bios} : $vga;
+ if ($new_vga ne $e->{vga}) {
+ $e->{vga} = $new_vga;
+ $e->{initrd} and bootloader::add_boot_splash($e->{initrd}, $e->{vga});
+ }
+ bootloader::set_append_netprofile($e, $append, $netprofile);
+ bootloader::configure_entry($b, $e); #- hack to make sure initrd file are built.
+ 1;
+ };
+
+ my $Add = sub {
+ my @labels = map { $_->{label} } @{$b->{entries}};
+ my ($e, $prefix);
+ if ($b->{method} eq 'refind') {
+ $e = { type => 'image',
+ kernel_or_dev => '/boot/vmlinuz',
+ root => '/dev/' . fs::get::root($fstab)->{device}, #- assume a good default.
+ };
+ $prefix = "linux";
+ } elsif ($in->ask_from_list_('', N("Which type of entry do you want to add?"),
+ [ N_("Linux"), N_("Other OS (Windows...)") ]
+ ) eq "Linux") {
+ $e = { type => 'image',
+ root => '/dev/' . fs::get::root($fstab)->{device}, #- assume a good default.
+ };
+ $prefix = "linux";
+ } else {
+ $e = { type => 'other' };
+ $prefix = "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;
+ };
- push @{$b->{entries}}, $e if $c eq "Add";
+ my $Up = sub {
+ my ($e) = @_;
+ my @entries = @{$b->{entries}};
+ my ($index) = grep { $entries[$_]{label} eq $e->{label} } 0..$#entries;
+ if ($index > 0) {
+ ($b->{entries}[$index - 1], $b->{entries}[$index]) = ($b->{entries}[$index], $b->{entries}[$index - 1]);
+ }
+ 1;
+ };
+
+ my $Down = sub {
+ my ($e) = @_;
+ my @entries = @{$b->{entries}};
+ my ($index) = grep { $entries[$_]{label} eq $e->{label} } 0..$#entries;
+ if ($index < $#entries) {
+ ($b->{entries}[$index + 1], $b->{entries}[$index]) = ($b->{entries}[$index], $b->{entries}[$index + 1]);
+ }
+ 1;
+ };
+
+ my @prev_entries = @{$b->{entries}};
+
+ #- the rEFInd configuration file just provides alternative kernel command lines
+ #- so we only want to display entries that relate to the default kernel.
+ if ($b->{method} eq 'refind') {
+ @{$b->{entries}} =
+ grep {
+ my $pb = $_->{type} ne 'image' || $_->{kernel_or_dev} ne '/boot/vmlinuz';
+ log::l("dropping bootloader entry $_->{label} because it is not needed by rEFInd") if $pb;
+ !$pb;
+ } @{$b->{entries}};
+ }
+
+ if ($in->ask_from__add_modify_remove(N("Bootloader Configuration"),
+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) ?
+ ($b->{default} eq $e->{label} ? " * " : " ") . "$e->{label} ($e->{kernel_or_dev})" :
+ translate($e);
+ }, list => $b->{entries},
+ } ], Add => $Add, Modify => $Modify, Remove => $Remove, Up => $Up, Down => $Down)) {
+ 1;
+ } else {
+ @{$b->{entries}} = @prev_entries;
+ '';
+ }
+}
+
+sub setupBootloader__grub2 {
+ my ($in, $b, $_all_hds, $_fstab) = @_;
+
+ # update entries (so that we can display their list below):
+ my $error;
+ # grub2-update can take many minutes on some systems (mga#18538)
+ # FIXME: change the message to be more informative
+ my $_w = $in->wait_message(N("Please wait"), N("Please wait"));
+ run_program::rooted($::prefix, 'update-grub2', '2>', \$error) or die "update-grub2 failed: $error";
+ undef $_w;
+
+ # read grub2 auto-generated entries (instead of keeping eg: grub/lilo ones):
+ my $b2 = bootloader::read_grub2();
+
+ # get default parameters:
+ my $append = $b->{perImageAppend} || bootloader::get_grub2_append($b2);
+ my $default = $b2->{default};
+
+ require Xconfig::resolution_and_depth;
+
+ require network::network; #- to list network profiles
+ my $vga = Xconfig::resolution_and_depth::from_bios($b->{default_vga});
+ my $os_prober = $in->do_pkgs->is_installed('os-prober', '/usr/bin/os-prober') && !$b->{default_to_no_probe};
+
+ my $res = $in->ask_from_(
+ {
+ title => N("Bootloader Configuration"),
+ interactive_help_id => 'setupBootloaderAddEntry',
+ },
+ [
+ { label => N("Default"), val => \$default,
+ list => [ map { $_->{label} } @{$b2->{entries}} ] },
+ { label => N("Append"), val => \$append },
+ { label => N("Video mode"), val => \$vga, list => [ '', Xconfig::resolution_and_depth::bios_vga_modes() ],
+ format => \&Xconfig::resolution_and_depth::to_string, advanced => 1 },
+ { text => N("Do not touch ESP or MBR"), val => \$b->{no_esp_or_mbr}, type => 'bool', advanced => 1,
+ validate => sub {
+ $b->{no_esp_or_mbr} and $in->ask_warn(N("Warning"),
+ N("Not installing on ESP or MBR means that the installation is not bootable unless chain loaded from another OS!"));
+ 1;
+ },
+ },
+ { text => N("Probe Foreign OS"), val => \$os_prober, type => 'bool',
+ help => N("Unselect this option to stop grub2 scanning for other operating systems, which will prevent them from being included in the grub2 boot menu. The option may also be unselected after installation, removing the other operating systems from the grub2 boot menu, but reducing the time needed for installing kernel updates"),
+ },
+ if_(is_uefi(),
+ { text => N("Install in /EFI/BOOT (removable device or workaround for some BIOSs)"),
+ val => \$b->{removable}, type => 'bool' },
+ ),
+ ]);
+ if ($res) {
+ $b->{entries} = $b2->{entries};
+ $b->{default} = $default;
+ $b->{default_vga} = ref($vga) ? $vga->{bios} : $vga;
+ $b->{perImageAppend} = $append;
+ if ($os_prober) {
+ $in->do_pkgs->ensure_is_installed('os-prober', '/usr/bin/os-prober');
} else {
- @{$b->{entries}} = grep { $_ != $e } @{$b->{entries}};
+ $in->do_pkgs->remove('os-prober');
}
+ 1;
+ } else {
+ '';
}
- 1;
}
-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 get_session_file {
+ my ($desktop) = @_;
+ my @dir_wm = qw(xsessions wayland-sessions);
+ my $xsession_file;
+ foreach my $dwm (@dir_wm) {
+ my $xs_file = find {
+ my %xsession = read_gnomekderc($_, 'Desktop Entry');
+ $xsession{Name} =~ s/\s+//g;
+ $xsession{Name} eq ${desktop};
+ } glob("$::prefix/usr/share/$dwm/*.desktop");
+ $xsession_file = $xs_file unless $xsession_file;
+ }
+ $xsession_file =~ s!\.[^.]+$!!;
+ $xsession_file =~ s!.*/!!;
+ $xsession_file ||= $desktop;
+ return $xsession_file;
+}
+
+sub get_session_file_with_extension {
+ return get_session_file(@_) . '.desktop';
+}
+
+sub available_dms() {
+ my @l;
+ foreach (glob("$::prefix/usr/share/X11/dm.d/*.conf")) {
+ my %dm = getVarsFromSh($_);
+ push @l, $dm{EXEC} if $dm{EXEC} && -x "$::prefix/$dm{EXEC}";
+ }
+ @l;
}
-sub pack_passwd {
- my ($l) = @_;
- join(':', @$l{@etc_pass_fields}) . "\n";
+
+sub get_autologin() {
+ my %desktop = getVarsFromSh("$::prefix/etc/sysconfig/desktop");
+ my $gdm_file = "$::prefix/etc/X11/gdm/custom.conf";
+ my $sddm_file = "$::prefix/etc/sddm.conf";
+ my $lightdm_conffile = "$::prefix/etc/lightdm/lightdm.conf.d/50-mageia-autologin.conf";
+ my $lxdm_conffile = "$::prefix/etc/lxdm/lxdm.conf";
+ my $autologin_file = "$::prefix/etc/sysconfig/autologin";
+ my $desktop = $desktop{DESKTOP} || first(sessions());
+ my %desktop_to_dm = (
+ GNOME => 'gdm',
+ Plasma => 'sddm',
+ Xfce => 'lightdm',
+ LXDE => 'lxdm',
+ );
+ my $dm =
+ basename(readlink("$::prefix/etc/systemd/system/display-manager.service")) =~ s/(.*)\.service/$1/r ||
+ $desktop_to_dm{$desktop} ||
+ basename(first(available_dms()));
+
+ my $autologin_user;
+ if ($dm eq "gdm") {
+ my %conf = read_gnomekderc($gdm_file, 'daemon');
+ $autologin_user = text2bool($conf{AutomaticLoginEnable}) && $conf{AutomaticLogin};
+ } elsif ($dm eq "sddm") {
+ my %conf = read_gnomekderc($sddm_file, 'Autologin');
+ $autologin_user = $conf{User};
+ } elsif ($dm eq "lightdm") {
+ my %conf = read_gnomekderc($lightdm_conffile, 'Seat:*');
+ $autologin_user = text2bool($conf{'#dummy-autologin'}) && $conf{"autologin-user"};
+ } elsif ($dm eq "lxdm") {
+ my %conf = read_gnomekderc($lxdm_conffile, 'base');
+ $autologin_user = $conf{autologin};
+ $autologin_user =~ s/^.//;
+ } else {
+ my %conf = getVarsFromSh($autologin_file);
+ $autologin_user = text2bool($conf{AUTOLOGIN}) && $conf{USER};
+ }
+
+ { user => $autologin_user, desktop => $desktop, dm => $dm };
}
-sub get_autologin {
- my ($prefix, $o) = @_;
- my %l = getVarsFromSh("$prefix/etc/sysconfig/autologin");
- $o->{autologin} ||= $l{USER};
- %l = getVarsFromSh("$prefix/etc/sysconfig/desktop");
- $o->{desktop} ||= $l{DESKTOP};
+sub is_standalone_autologin_needed {
+ my ($dm) = @_;
+ return member($dm, qw(slim xdm));
}
sub set_autologin {
- my ($prefix, $user, $desktop) = @_;
+ my ($do_pkgs, $autologin, $o_auto) = @_;
+ log::l("set_autologin $autologin->{user} $autologin->{desktop}");
+ my $do_autologin = bool2text($autologin->{user});
+
+ $autologin->{dm} ||= 'xdm';
+ $do_pkgs->ensure_is_installed($autologin->{dm}, undef, $o_auto)
+ or return;
+ if ($autologin->{user} && is_standalone_autologin_needed($autologin->{dm})) {
+ $do_pkgs->ensure_is_installed('autologin', '/usr/bin/startx.autologin', $o_auto)
+ or return;
+ }
- if ($user) {
- my %l = getVarsFromSh("$prefix/etc/sysconfig/desktop");
- $l{DESKTOP} = $desktop;
- setVarsInSh("$prefix/etc/sysconfig/desktop", \%l);
- log::l("cat $prefix/etc/sysconfig/desktop ($desktop):\n", cat_("$prefix/etc/sysconfig/desktop"));
- }
- setVarsInSh("$prefix/etc/sysconfig/autologin",
- { USER => $user, AUTOLOGIN => bool2yesno($user), EXEC => "/usr/X11R6/bin/startx" });
- log::l("cat $prefix/etc/sysconfig/autologin ($user):\n", cat_("$prefix/etc/sysconfig/autologin"));
+ #- Configure SDDM
+ my $sddm_conffile = "$::prefix/etc/sddm.conf";
+ eval { common::update_gnomekderc_no_create($sddm_conffile, 'Autologin' => (
+ Session => get_session_file_with_extension($autologin->{desktop}),
+ User => $autologin->{user},
+ )) } if -e $sddm_conffile;
+
+ #- Configure GDM
+ my $gdm_conffile = "$::prefix/etc/X11/gdm/custom.conf";
+ eval { update_gnomekderc($gdm_conffile, daemon => (
+ AutomaticLoginEnable => $do_autologin,
+ AutomaticLogin => $autologin->{user},
+ )) } if -e $gdm_conffile;
+
+ #- Configure LIGHTDM
+ my $lightdm_conffile = "$::prefix/etc/lightdm/lightdm.conf.d/50-mageia-autologin.conf";
+ eval { update_gnomekderc($lightdm_conffile, 'Seat:*' => (
+ '#dummy-autologin' => $do_autologin,
+ 'autologin-user' => $autologin->{user},
+ 'autologin-session' => get_session_file($autologin->{desktop}),
+ )) } if -e $lightdm_conffile;
+
+ #- Configure LXDM
+ my $lxdm_conffile = "$::prefix/etc/lxdm/lxdm.conf";
+ eval { update_gnomekderc($lxdm_conffile, 'base' => (
+ 'autologin' => $autologin->{user} ? '@' . $autologin->{user} : ''
+ ));
+ if ($autologin->{user} && $autologin->{desktop} && !member($autologin->{desktop}, qw(default failsafe))) {
+ update_gnomekderc($lxdm_conffile, $autologin->{user} => (
+ 'user' => $autologin->{user},
+ 'session' => get_session_file($autologin->{desktop}),
+ )) } } if -e $lxdm_conffile;
+
+ #- Configure XDM
+ my $xdm_autologin_cfg = "$::prefix/etc/sysconfig/autologin";
+ if (is_standalone_autologin_needed($autologin->{dm})) {
+ setVarsInShMode($xdm_autologin_cfg, 0644,
+ { USER => $autologin->{user}, AUTOLOGIN => bool2yesno($autologin->{user}), EXEC => '/usr/bin/startx.autologin' });
+ } else {
+ unlink $xdm_autologin_cfg;
+ }
+
+ my $sys_conffile = "$::prefix/etc/sysconfig/desktop";
+ my %desktop = getVarsFromSh($sys_conffile);
+ $desktop{DESKTOP} = $autologin->{desktop};
+ $desktop{DISPLAYMANAGER} = $autologin->{dm};
+ setVarsInSh($sys_conffile, \%desktop);
+ symlinkf("/usr/lib/systemd/system/$autologin->{dm}.service", "$::prefix/etc/systemd/system/display-manager.service");
+
+ if ($autologin->{user}) {
+ my $home = (getpwnam($autologin->{user}))[7];
+ set_window_manager($home, $autologin->{desktop});
+ }
+}
+sub set_window_manager {
+ my ($home, $wm) = @_;
+ log::l("set_window_manager $home $wm");
+ my $p_home = "$::prefix$home";
+
+ #- for KDM/GDM
+ my $wm_number = sessions_with_order()->{$wm} || '';
+ update_gnomekderc("$p_home/.dmrc", 'Desktop', Session => "$wm_number$wm");
+ my $user = find { $home eq $_->[7] } list_passwd();
+ chown($user->[2], $user->[3], "$p_home/.dmrc");
+ chmod(0644, "$p_home/.dmrc");
+
+ #- for startx/autologin
+ {
+ my %l = getVarsFromSh("$p_home/.desktop");
+ $l{DESKTOP} = $wm;
+ setVarsInSh("$p_home/.desktop", \%l);
+ }
}
sub rotate_log {
@@ -348,506 +985,1041 @@ sub rotate_log {
}
sub rotate_logs {
my ($prefix) = @_;
- rotate_log("$prefix/root/$_") foreach qw(ddebug.log install.log);
+ rotate_log("$prefix/root/drakx/$_") foreach qw(stage1.log ddebug.log install.log updates.log);
}
sub writeandclean_ldsoconf {
my ($prefix) = @_;
my $file = "$prefix/etc/ld.so.conf";
- output $file,
- grep { !m|^(/usr)?/lib$| } #- no need to have /lib and /usr/lib in ld.so.conf
- uniq cat_($file), "/usr/X11R6/lib\n";
+ my @l = chomp_(cat_($file));
+
+ my @default = ('/lib', '/usr/lib'); #- no need to have /lib and /usr/lib in ld.so.conf
+ my @suggest = ('/usr/lib/qt3/lib'); #- needed for upgrade where package renaming can cause this to disappear
+
+ if (arch() =~ /x86_64/) {
+ @default = map { $_, $_ . '64' } @default;
+ @suggest = map { $_, $_ . '64' } @suggest;
+ }
+ push @l, grep { -d "$::prefix$_" } @suggest;
+ @l = difference2(\@l, \@default);
+
+ log::l("writeandclean_ldsoconf");
+ output($file, map { "$_\n" } uniq(@l));
}
-sub shells {
- my ($prefix) = @_;
- grep { -x "$prefix$_" } chomp_(cat_("$prefix/etc/shells"));
+sub shells() {
+ grep { -x "$::prefix$_" } chomp_(cat_("$::prefix/etc/shells"));
}
sub inspect {
- my ($part, $prefix, $rw) = @_;
+ my ($part, $o_prefix, $b_rw) = @_;
- isMountableRW($part) or return;
+ isMountableRW($part) || !$b_rw && isOtherAvailableFS($part) or return;
my $dir = $::isInstall ? "/tmp/inspect_tmp_dir" : "/root/.inspect_tmp_dir";
if ($part->{isMounted}) {
- $dir = ($prefix || '') . $part->{mntpoint};
+ $dir = ($o_prefix || '') . $part->{mntpoint};
} elsif ($part->{notFormatted} && !$part->{isFormatted}) {
$dir = '';
} else {
mkdir $dir, 0700;
- eval { fs::mount($part->{device}, $dir, type2fs($part), !$rw) };
+ eval { fs::mount::mount(fs::wild_device::from_part('', $part), $dir, $part->{fs_type}, !$b_rw) };
$@ and return;
}
my $h = before_leaving {
if (!$part->{isMounted} && $dir) {
- fs::umount($dir);
- unlink($dir)
+ fs::mount::umount($dir);
+ unlink($dir);
}
};
$h->{dir} = $dir;
$h;
}
-#-----modem conf
-sub pppConfig {
- my ($in, $modem, $prefix) = @_;
- $modem or return;
-
- if ($modem->{device} ne "/dev/modem") {
- devfssymlinkf($modem->{device}, 'modem', $prefix) or log::l("creation of $prefix/dev/modem failed")
- }
- $in->do_pkgs->install('ppp') if !$::testing;
-
- my %toreplace;
- $toreplace{$_} = $modem->{$_} foreach qw(connection phone login passwd auth domain dns1 dns2);
- $toreplace{kpppauth} = ${{ 'Script-based' => 0, 'PAP' => 1, 'Terminal-based' => 2, }}{$modem->{auth}};
- $toreplace{kpppauth} = ${{ 'Script-based' => 0, 'PAP' => 1, 'Terminal-based' => 2, 'CHAP' => 3 }}{$modem->{auth}};
- $toreplace{phone} =~ s/\D//g;
- $toreplace{dnsserver} = join ',', map { $modem->{$_} } "dns1", "dns2";
- $toreplace{dnsserver} .= $toreplace{dnsserver} && ',';
-
- #- using peerdns or dns1,dns2 avoid writing a /etc/resolv.conf file.
- $toreplace{peerdns} = "yes";
-
- $toreplace{connection} ||= 'DialupConnection';
- $toreplace{domain} ||= 'localdomain';
- $toreplace{intf} ||= 'ppp0';
- $toreplace{papname} = ($modem->{auth} eq 'PAP' || $modem->{auth} eq 'CHAP') && $toreplace{login};
-
- #- build ifcfg-ppp0.
- my $ifcfg = "$prefix/etc/sysconfig/network-scripts/ifcfg-ppp0";
- local *IFCFG; open IFCFG, ">$ifcfg" or die "Can't open $ifcfg";
- print IFCFG <<END;
-DEVICE="$toreplace{intf}"
-ONBOOT="no"
-USERCTL="no"
-MODEMPORT="/dev/modem"
-LINESPEED="115200"
-PERSIST="yes"
-DEFABORT="yes"
-DEBUG="yes"
-INITSTRING="ATZ"
-DEFROUTE="yes"
-HARDFLOWCTL="yes"
-ESCAPECHARS="no"
-PPPOPTIONS=""
-PAPNAME="$toreplace{papname}"
-REMIP=""
-NETMASK=""
-IPADDR=""
-MRU=""
-MTU=""
-DISCONNECTTIMEOUT="5"
-RETRYTIMEOUT="60"
-BOOTPROTO="none"
-PEERDNS="$toreplace{peerdns}"
-END
- foreach (1..2) {
- if ($toreplace{"dns$_"}) {
- print IFCFG <<END;
-DNS$_=$toreplace{"dns$_"}
-END
- }
- }
- close IFCFG;
-
- #- build chat-ppp0.
- my $chat = "$prefix/etc/sysconfig/network-scripts/chat-ppp0";
- local *CHAT; open CHAT, ">$chat" or die "Can't open $chat";
- print CHAT <<END;
-'ABORT' 'BUSY'
-'ABORT' 'ERROR'
-'ABORT' 'NO CARRIER'
-'ABORT' 'NO DIALTONE'
-'ABORT' 'Invalid Login'
-'ABORT' 'Login incorrect'
-'' 'ATZ'
-END
- if ($modem->{special_command}) {
- print CHAT <<END;
-'OK' '$modem->{special_command}'
-END
- }
- print CHAT <<END;
-'OK' 'ATDT$toreplace{phone}'
-'CONNECT' ''
-END
- if ($modem->{auth} eq 'Terminal-based' || $modem->{auth} eq 'Script-based') {
- print CHAT <<END;
-'ogin:--ogin:' '$toreplace{login}'
-'ord:' '$toreplace{passwd}'
-END
- }
- print CHAT <<END;
-'TIMEOUT' '5'
-'~--' ''
-END
- close CHAT;
- chmod 0600, $chat;
-
- if ($modem->{auth} eq 'PAP' || $modem->{auth} eq 'CHAP') {
- #- need to create a secrets file for the connection.
- my $secrets = "$prefix/etc/ppp/" . lc($modem->{auth}) . "-secrets";
- my @l = cat_($secrets);
- my $replaced = 0;
- do { $replaced ||= 1
- if s/^\s*"?$toreplace{login}"?\s+ppp0\s+(\S+)/"$toreplace{login}" ppp0 "$toreplace{passwd}"/; } foreach @l;
- if ($replaced) {
- local *F;
- open F, ">$secrets" or die "Can't open $secrets: $!";
- print F @l;
- } else {
- local *F;
- open F, ">>$secrets" or die "Can't open $secrets: $!";
- print F "$toreplace{login} ppp0 \"$toreplace{passwd}\"\n";
- }
- #- restore access right to secrets file, just in case.
- chmod 0600, $secrets;
- }
-
- #- install kppprc file according to used configuration.
- mkdir_p("$prefix/usr/share/config");
- local *KPPPRC;
- open KPPPRC, ">$prefix/usr/share/config/kppprc" or die "Can't open $prefix/usr/share/config/kppprc: $!";
- #chmod 0600, "$prefix/usr/share/config/kppprc";
- print KPPPRC <<END;
-# KDE Config File
-[Account0]
-ExDNSDisabled=0
-AutoName=0
-ScriptArguments=
-AccountingEnabled=0
-DialString=ATDT
-Phonenumber=$toreplace{phone}
-IPAddr=0.0.0.0
-Domain=$toreplace{domain}
-Name=$toreplace{connection}
-VolumeAccountingEnabled=0
-pppdArguments=
-Password=$toreplace{passwd}
-BeforeDisconnect=
-Command=
-ScriptCommands=
-Authentication=$toreplace{kpppauth}
-DNS=$toreplace{dnsserver}
-SubnetMask=0.0.0.0
-AccountingFile=
-DefaultRoute=1
-Username=$toreplace{login}
-Gateway=0.0.0.0
-StorePassword=1
-DisconnectCommand=
-[Modem]
-BusyWait=0
-Enter=CR
-FlowControl=CRTSCTS
-Volume=0
-Timeout=60
-UseCDLine=0
-UseLockFile=1
-Device=/dev/modem
-Speed=115200
-[Graph]
-InBytes=0,0,255
-Text=0,0,0
-Background=255,255,255
-Enabled=true
-OutBytes=255,0,0
-[General]
-QuitOnDisconnect=0
-ShowLogWindow=0
-DisconnectOnXServerExit=1
-DefaultAccount=$toreplace{connection}
-iconifyOnConnect=1
-Hint_QuickHelp=0
-AutomaticRedial=0
-PPPDebug=0
-NumberOfAccounts=1
-ShowClock=1
-DockIntoPanel=0
-pppdTimeout=30
-END
-
- miscellaneousNetwork($prefix);
-}
-
-sub miscellaneousNetwork {
- my ($prefix) = @_;
- setVarsInSh ("$prefix/etc/profile.d/proxy.sh", $::o->{miscellaneous}, qw(http_proxy ftp_proxy));
- setVarsInCsh("$prefix/etc/profile.d/proxy.csh", $::o->{miscellaneous}, qw(http_proxy ftp_proxy));
+sub ask_user {
+ my ($in, $users, $security, %options) = @_;
+
+ ask_user_and_root($in, undef, $users, $security, %options);
}
-sub setup_thiskind {
- my ($in, $type, $auto, $at_least_one) = @_;
+sub is_xguest_installed() {
+ -e "$::prefix/etc/security/namespace.d/xguest.conf";
+}
- my @l = setup_thiskind_backend ($type, $auto, $at_least_one, sub { my $w = wait_load_module($in, $type, @_); } );
+sub ask_user_and_root {
+ my ($in, $superuser, $users, $security, %options) = @_;
- if (!$::noauto) {
- if (my @err = grep { $_ } map { $_->{error} } @l) {
- $in->ask_warn('', join("\n", @err));
- }
- return @l if $auto && (@l || !$at_least_one);
- }
- @l = map { $_->{description} } @l;
- while (1) {
- (my $msg_type = $type) =~ s/\|.*//;
- my $msg = @l ?
- [ _("Found %s %s interfaces", join(", ", @l), $msg_type),
- _("Do you have another one?") ] :
- _("Do you have any %s interfaces?", $msg_type);
-
- my $opt = [ __("Yes"), __("No") ];
- push @$opt, __("See hardware info") if $::expert;
- my $r = "Yes";
- $r = $in->ask_from_list_('', $msg, $opt, "No") || die 'already displayed' unless $at_least_one && @l == 0;
- if ($r eq "No") { return @l }
- if ($r eq "Yes") {
- push @l, load_module($in, $type) || next;
- } else {
- $in->ask_warn('', [ detect_devices::stringlist() ]);
- }
+ my $xguest = is_xguest_installed();
+
+ $options{needauser} ||= $security >= 3;
+
+ my @icons = facesnames();
+ my @suggested_names = $::isInstall ? do {
+ my @l = grep { !/^\./ && $_ ne 'lost+found' && -d "$::prefix/home/$_" } all("$::prefix/home");
+ grep { ! defined getpwnam($_) } @l;
+ } : ();
+
+ my %high_security_groups = (
+ xgrp => N("access to X programs"),
+ rpm => N("access to rpm tools"),
+ wheel => N("allow \"su\""),
+ adm => N("access to administrative files"),
+ ntools => N("access to network tools"),
+ ctools => N("access to compilation tools"),
+ );
+
+ my $u = {};
+ $u->{password2} ||= $u->{password} ||= '';
+ $u->{shell} ||= '/bin/bash';
+ my $names = @$users ? N("(already added %s)", join(", ", map { $_->{realname} || $_->{name} } @$users)) : '';
+
+ my %groups;
+
+ require authentication;
+ my $validate_name = sub {
+ $u->{name} or $in->ask_warn('', N("Please give a user name")), return;
+ $u->{name} =~ /^[a-z]+[a-z0-9_-]*$/ or $in->ask_warn('', N("The user name must start with a lower case letter followed by only lower cased letters, numbers, `-' and `_'")), return;
+ length($u->{name}) <= 32 or $in->ask_warn('', N("The user name is too long")), return;
+ defined getpwnam($u->{name}) || member($u->{name}, map { $_->{name} } @$users) and $in->ask_warn('', N("This user name has already been added")), return;
+ 'ok';
+ };
+ my $validate_uid_gid = sub {
+ my ($field) = @_;
+ my $id = $u->{$field} or return 'ok';
+ my $name = $field eq 'uid' ? N("User ID") : N("Group ID");
+ $id =~ /^\d+$/ or $in->ask_warn('', N("%s must be a number", $name)), return;
+ $id >= 1000 or $in->ask_yesorno('', N("%s should be above 1000. Accept anyway?", $name)) or return;
+ 'ok';
+ };
+ my $ret = $in->ask_from_(
+ { title => N("User management"),
+ interactive_help_id => 'addUser',
+ if_($::isInstall && $superuser, cancel => ''),
+ }, [
+ $superuser ? (
+ if_(0,
+ { text => N("Enable guest account"), val => \$xguest, type => 'bool', advanced => 1 },
+ ),
+ { label => N("Set administrator (root) password"), title => 1 },
+ { label => N("Password"), val => \$superuser->{password}, hidden => 1, alignment => 'right', weakness_check => 1,
+ focus => sub { 1 },
+ validate => sub { authentication::check_given_password($in, $superuser, 2 * $security) } },
+ { label => N("Password (again)"), val => \$superuser->{password2}, hidden => 1, alignment => 'right' },
+ ) : (),
+ { label => N("Enter a user"), title => 1 }, if_($names, { label => $names }),
+ if_($security <= 3 && !$options{noicons} && @icons,
+ { label => N("Icon"), val => \ ($u->{icon} ||= 'default'), list => \@icons, icon2f => \&face2png,
+ alignment => 'right', format => \&translate },
+ ),
+ { label => N("Real name"), val => \$u->{realname}, alignment => 'right', focus_out => sub {
+ $u->{name} ||= lc(Locale::gettext::iconv($u->{realname}, "utf-8", "ascii//TRANSLIT"));
+ $u->{name} =~ s/[^a-zA-Z0-9_-]//g; # drop any character that would break login program
+ },
+ focus => sub { !$superuser },
+ },
+
+ { label => N("Login name"), val => \$u->{name}, list => \@suggested_names, alignment => 'right',
+ not_edit => 0, validate => $validate_name },
+ { label => N("Password"),val => \$u->{password}, hidden => 1, alignment => 'right', weakness_check => 1,
+ validate => sub { authentication::check_given_password($in, $u, $security > 3 ? 6 : 0) } },
+ { label => N("Password (again)"), val => \$u->{password2}, hidden => 1, alignment => 'right' },
+ { label => N("Shell"), val => \$u->{shell}, list => [ shells() ], advanced => 1 },
+ { label => N("User ID"), val => \$u->{uid}, advanced => 1, validate => sub { $validate_uid_gid->('uid') } },
+ { label => N("Group ID"), val => \$u->{gid}, advanced => 1, validate => sub { $validate_uid_gid->('gid') } },
+ if_($security >= 1,
+ { label => N("Extra Groups:"), advanced => 1, title => 1 },
+ map {
+ { label => $_, val => \$groups{$_}, text => $high_security_groups{$_}, type => 'bool', advanced => 1 };
+ } keys %high_security_groups,
+ ),
+ ],
+ );
+
+ if ($xguest && !is_xguest_installed()) {
+ $in->do_pkgs->ensure_is_installed('xguest', '/etc/security/namespace.d/xguest.conf');
+ } elsif (!$xguest && is_xguest_installed()) {
+ $in->do_pkgs->remove('xguest') or return;
}
-}
-# setup_thiskind_backend : setup the kind of hardware
-# input :
-# $type : typeof hardware to setup
-# $auto : automatic behaviour
-# $at_least_one :
-# output:
-# @l : list of loaded
-sub setup_thiskind_backend {
- my ($type, $auto, $at_least_one, $wait_function) = @_;
- #- for example $wait_function=sub { $w = wait_load_module($in, $type, @_) }
+ $u->{groups} = [ grep { $groups{$_} } keys %groups ];
+
+ push @$users, $u if $u->{name};
+ $ret && $u;
+}
+
+sub sessions() {
my @l;
- if (!$::noauto) {
- @l = modules::load_thiskind($type, $wait_function );
- return @l;# sorry to be a sucker, pixel... :)
- }
-}
-
-sub wait_load_module {
- my ($in, $type, $text, $module) = @_;
-#-PO: the first %s is the card type (scsi, network, sound,...)
-#-PO: the second is the vendor+model name
- $in->wait_message('',
- [ _("Installing driver for %s card %s", $type, $text),
- if_($::expert, _("(module %s)", $module))
- ]);
-}
-
-sub load_module {
- my ($in, $type) = @_;
- my @options;
-
- (my $msg_type = $type) =~ s/\|.*//;
- my $m = $in->ask_from_listf('',
-#-PO: the %s is the driver type (scsi, network, sound,...)
- _("Which %s driver should I try?", $msg_type),
- \&modules::module2text,
- [ modules::module_of_type($type) ]) or return;
- my $l = modules::module2text($m);
- require modparm;
- my @names = modparm::get_options_name($m);
-
- if ((@names != 0) && $in->ask_from_list_('',
-_("In some cases, the %s driver needs to have extra information to work
-properly, although it normally works fine without. Would you like to specify
-extra options for it or allow the driver to probe your machine for the
-information it needs? Occasionally, probing will hang a computer, but it should
-not cause any damage.", $l),
- [ __("Autoprobe"), __("Specify options") ], "Autoprobe") ne "Autoprobe") {
- ASK:
- if (@names >= 0) {
- my @l = $in->ask_from_entries('',
-_("You may now provide its options to module %s.", $l),
- \@names) or return;
- @options = modparm::get_options_result($m, @l);
- } else {
- @options = split ' ',
- $in->ask_from_entry('',
-_("You may now provide its options to module %s.
-Options are in format ``name=value name2=value2 ...''.
-For instance, ``io=0x300 irq=7''", $l),
- _("Module options:"),
- );
- }
- }
- eval {
- my $w = wait_load_module($in, $type, $l, $m);
- log::l("user asked for loading module $m (type $type, desc $l)");
- modules::load($m, $type, @options);
- };
- if ($@) {
- $in->ask_yesorno('',
-_("Loading module %s failed.
-Do you want to try again with other parameters?", $l), 1) or return;
- goto ASK;
+ my @dir_wm = qw(xsessions wayland-sessions);
+ foreach my $dwm (@dir_wm) {
+ push @l, map { s/.desktop$//; basename($_) } glob("$::prefix/usr/share/$dwm/*.desktop");
}
- $l;
+ @l;
+}
+sub sessions_with_order() {
+ my %h = map { /(.*)=(.*)/ } split(' ', run_program::rooted_get_stdout($::prefix, '/usr/sbin/chksession', '-L'));
+ \%h;
}
-sub ask_users {
- my ($prefix, $in, $users, $security) = @_;
+sub urpmi_add_all_media {
+ my ($in, $o_previous_release, $o_mirror_url) = @_;
+
+ $o_mirror_url = undef if $o_mirror_url eq '$MIRRORLIST';
+
+ my $binary = find { whereis_binary($_, $::prefix) } if_(check_for_xserver(), 'gurpmi.addmedia'), 'urpmi.addmedia';
+ if (!$binary) {
+ log::l("urpmi.addmedia not found!");
+ return;
+ }
+
+ #- configure urpmi media if network is up
+ require network::tools;
+ if (!network::tools::has_network_connection()) {
+ log::l("no network connexion!");
+ return;
+ }
+ # First remove all media:
+ run_program::rooted($::prefix, 'urpmi.removemedia', '-a');
+ # Then add online media:
+ my $wait;
+ my @options = $o_mirror_url ? ( '--distrib', $o_mirror_url) : ('--distrib', '--mirrorlist', '$MIRRORLIST');
+ if ($binary eq 'urpmi.addmedia') {
+ $wait = $in->wait_message(N("Please wait"), N("Please wait, adding media..."));
+ } elsif ($in->isa('interactive::gtk')) {
+ push @options, '--silent-success';
+ mygtk3::flush();
+ }
+
+ my $reason = join(',', $o_previous_release ?
+ ('reason=upgrade', 'upgrade_by=drakx', "upgrade_from=$o_previous_release->{version}") :
+ 'reason=install');
+ log::l("URPMI_ADDMEDIA_REASON $reason");
+ local $ENV{URPMI_ADDMEDIA_REASON} = $reason;
- my $u if 0; $u ||= {};
+ my $log_file = '/root/drakx/updates.log';
+ my $val = run_program::rooted($::prefix, $binary, '>>', $log_file, '2>>', $log_file, @options);
- my @shells = map { chomp; $_ } cat_("$prefix/etc/shells");
- my @icons = facesnames($prefix);
+ undef $wait;
+ $val;
+}
- while (1) {
- $u->{password2} ||= $u->{password} ||= '';
- $u->{shell} ||= '/bin/bash';
- my $names = @$users ? _("(already added %s)", join(", ", map { $_->{realname} || $_->{name} } @$users)) : '';
+sub urpmi_set_downloader {
+ my ($in, $urpm, $downloader) = @_;
- my $verif = sub {
- $u->{password} eq $u->{password2} or $in->ask_warn('', [ _("The passwords do not match"), _("Please try again") ]), return (1,2);
- $security > 3 && length($u->{password}) < 6 and $in->ask_warn('', _("This password is too simple")), return (1,2);
- $u->{name} or $in->ask_warn('', _("Please give a user name")), return (1,0);
- $u->{name} =~ /^[a-z0-9_-]+$/ or $in->ask_warn('', _("The user name must contain only lower cased letters, numbers, `-' and `_'")), return (1,0);
- member($u->{name}, map { $_->{name} } @$users) and $in->ask_warn('', _("This user name is already added")), return (1,0);
- return 0;
- };
- my $ret = $in->ask_from_(
- { title => _("Add user"),
- messages => _("Enter a user\n%s", $names),
- ok => _("Accept user"),
- cancel => $security < 4 || @$users ? _("Done") : '',
- callbacks => {
- focus_out => sub {
- if ($_[0] eq 0) {
- $u->{name} ||= lc first($u->{realname} =~ /((\w|-)+)/);
- }
- },
- complete => $verif,
- canceled => sub { $u->{name} ? &$verif : 0; },
- } }, [
- { label => _("Real name"), val => \$u->{realname} },
- { label => _("User name"), val => \$u->{name} },
- { label => _("Password"),val => \$u->{password}, hidden => 1 },
- { label => _("Password (again)"), val => \$u->{password2}, hidden => 1 },
- { label => _("Shell"), val => \$u->{shell}, list => [ shells($prefix) ], not_edit => !$::expert, advanced => 1 },
- if_($security <= 3 && @icons,
- { label => _("Icon"), val => \ ($u->{icon} ||= 'man'), list => \@icons, icon2f => sub { face2png($_[0], $prefix) }, format => \&translate },
- ),
- ],
- );
-
- push @$users, $u if $u->{name};
- $u = {};
- $ret or return;
+ if ($urpm->{global_config}{downloader} ne $downloader) {
+ my $binary = $downloader eq 'aria2' ? 'aria2c' : $downloader;
+ if ($in->do_pkgs->ensure_binary_is_installed($downloader, $binary, 1)) {
+ log::l("Setting urpmi downloader to '$downloader'");
+ $urpm->{global_config}{downloader} = $downloader;
+ urpm::media::write_config($urpm);
+ } else {
+ return;
+ }
}
+ 1;
+}
+
+sub format_wm {
+ my ($wm) = @_;
+ return {
+ cinnamon => 'Cinnamon',
+ enlightenment => 'Enlightenment',
+ 'gnome-classic' => 'GNOME Classic',
+ gnome => 'GNOME',
+ i3 => 'I3',
+ 'i3-with-shmlog' => 'I3 with shmlog',
+ lxqt => 'LxQt',
+ mate => 'Mate',
+ openbox => 'OpenBox',
+ 'plasma-mediacenter' => 'Plasma Mediacenter',
+ '01plasma' => 'Plasma',
+ sugar => 'Sugar',
+ xfce => 'Xfce',
+ }->{$wm};
}
sub autologin {
- my ($prefix, $o, $in) = @_;
+ my ($o, $in) = @_;
- my $cmd = $prefix ? "chroot $prefix" : "";
- my @wm = (split (' ', `$cmd /usr/sbin/chksession -l 2>/dev/null`));
+ my @wm = sessions();
my @users = map { $_->{name} } @{$o->{users} || []};
- if (@wm && @users && !$o->{authentication}{NIS} && $o->{security} <= 2) {
- add2hash_($o, { autologin => $users[0] });
+ my $kde_desktop = find { member($_, 'KDE', 'KDE4') } @wm;
+ if ($kde_desktop && @users == 1 && $o->{meta_class} eq 'desktop') {
+ $o->{desktop} = $kde_desktop;
+ $o->{autologin} = $users[0];
+ } elsif (@wm > 1 && @users && !$o->{authentication}{NIS} && $o->{security} <= 2) {
+ my $use_autologin = @users == 1;
$in->ask_from_(
- { title => _("Autologin"),
- messages => _("I can set up your computer to automatically log on one user.
-Do you want to use this feature?"),
- ok => _("Yes"),
- cancel => _("No") },
- [ { label => _("Choose the default user:"), val => \$o->{autologin}, list => [ '', @users ] },
- { label => _("Choose the window manager to run:"), val => \$o->{desktop}, list => \@wm } ]
- )
- or delete $o->{autologin};
+ { title => N("Autologin"),
+ messages => N("I can set up your computer to automatically log on one user.") },
+ [ { text => N("Use this feature"), val => \$use_autologin, type => 'bool' },
+ { label => N("Choose the default user:"), val => \$o->{autologin}, list => \@users, disabled => sub { !$use_autologin } },
+ { label => N("Choose the window manager to run:"), val => \$o->{desktop}, list => \@wm, disabled => sub { !$use_autologin }, format => \&format_wm } ]
+ );
+ delete $o->{autologin} if !$use_autologin;
+ } else {
+ delete $o->{autologin};
}
}
-sub selectLanguage {
- my ($in, $lang, $langs) = @_;
- $in->ask_from_(
- { messages => _("Please, choose a language to use."),
- title => 'language choice',
- advanced_messages => _("You can choose other languages that will be available after install"),
- callbacks => {
- focus_out => sub { $langs->{$lang} = 1 },
- },
- },
- [ { val => \$lang, separator => '|',
- format => \&lang::lang2text, list => [ lang::list() ] },
- (map {;
- { val => \$langs->{$_->[0]}, type => 'bool', disabled => sub { $langs->{all} },
- text => $_->[1], advanced => 1,
- }
- } sort { $a->[1] cmp $b->[1] } map { [ $_, lang::lang2text($_) ] } lang::list()),
- { val => \$langs->{all}, type => 'bool', text => _("All"), advanced => 1 }
- ]) or return;
- $lang;
-}
-
-sub write_passwd_user {
- my ($prefix, $u, $isMD5) = @_;
-
- $u->{pw} = &crypt($u->{password}, $isMD5) if $u->{password};
- $u->{shell} ||= '/bin/bash';
+sub display_release_notes {
+ my ($in, $release_notes) = @_;
+ if (!$in->isa('interactive::gtk')) {
+ $in->ask_from_({ title => N("Release Notes"),
+ messages => $release_notes,
+ }, [ {} ]);
+ return;
+ }
- substInFile {
- my $l = unpack_passwd($_);
- if ($l->{name} eq $u->{name}) {
- add2hash_($u, $l);
- $_ = pack_passwd($u);
- $u = {};
- }
- if (eof && $u->{name}) {
- $_ .= pack_passwd($u);
- }
- } "$prefix/etc/passwd";
+ require Gtk3::WebKit2;
+ Gtk3::WebKit2->import;
+ require ugtk3;
+ ugtk3->import(':all');
+ require mygtk3;
+ mygtk3->import('gtknew');
+ my $view = gtknew('WebKit2_WebView', no_popup_menu => 1);
+ $view->load_html($release_notes, '/');
+
+ my $w = ugtk3->new(N("Release Notes"), transient => $::main_window, modal => 1, pop_it => 1);
+ gtkadd($w->{rwindow},
+ gtkpack_(Gtk3::VBox->new,
+ 1, create_scrolled_window(ugtk3::gtkset_border_width($view, 5),
+ [ 'never', 'automatic' ],
+ ),
+ 0, gtkpack(create_hbox('end'),
+ gtknew('Button', text => N("Close"),
+ clicked => sub { Gtk3->main_quit })
+ ),
+ ),
+ );
+ mygtk3::set_main_window_size($w->{rwindow});
+ $w->{real_window}->grab_focus;
+ $w->{real_window}->show_all;
+ $w->main;
+ return;
+}
+
+sub get_release_notes {
+ my ($in) = @_;
+ my $ext = $in->isa('interactive::gtk') ? '.html' : '.txt';
+ my $separator = $in->isa('interactive::gtk') ? "\n\n" : '';
+
+ my $release_notes = join($separator, grep { $_ } map {
+ if ($::isInstall) {
+ my $f = install::any::getFile_($::o->{stage2_phys_medium}, $_);
+ $f && cat__($f);
+ } else {
+ my $file = $_;
+ my $d = find { -e "$_/$file" } glob_("/usr/share/doc/*-release-*");
+ $d && cat_("$d/$file");
+ }
+ } "release-notes$ext", 'release-notes.' . $ext);
+
+ # we do not handle links:
+ $release_notes =~ s!<a href=".*?">(.*?)</a>!$1!g;
+ $release_notes;
+}
+
+sub run_display_release_notes {
+ my ($release_notes) = @_;
+ output('/tmp/release_notes.html', $release_notes);
+ local $ENV{LC_ALL} = $::o->{locale}{lang} || 'C';
+ run_program::raw({ detach => 1 }, '/usr/bin/display_release_notes.pl');
+}
+
+sub acceptLicense {
+ my ($in) = @_;
+ require messages;
+
+ my $release_notes = get_release_notes($in);
+
+ my $r = $::testing ? 'Accept' : 'Refuse';
+
+ $in->ask_from_({ title => N("License agreement"),
+ focus_first => 1,
+ cancel => N("Quit"),
+ messages => formatAlaTeX(messages::main_license()),
+ interactive_help_id => 'acceptLicense',
+ callbacks => { ok_disabled => sub { $r eq 'Refuse' } },
+ },
+
+ [
+ { label => N("Do you accept this license ?"), title => 1, alignment => 'right' },
+ { list => [ N_("Accept"), N_("Refuse") ], val => \$r, type => 'list', alignment => 'right',
+ format => sub { translate($_[0]) } },
+ if_($release_notes,
+ { clicked => sub { run_display_release_notes($release_notes) }, do_not_expand => 1,
+ val => \ (my $_t1 = N("Release Notes")), install_button => 1, no_indent => 1 }
+ ),
+ ])
+ or reboot();
}
-sub runlevel {
- my ($prefix, $runlevel) = @_;
- my $f = "$prefix/etc/inittab";
- -r $f or log::l("missing inittab!!!"), return;
- if ($runlevel) {
- substInFile { s/^id:\d:initdefault:\s*$/id:$runlevel:initdefault:\n/ } $f;
+sub reboot() {
+ if ($::isInstall) {
+ my $o = $::o;
+ install::media::umount_phys_medium($o->{stage2_phys_medium});
+ install::media::openCdromTray($o->{stage2_phys_medium}{device}) if !detect_devices::is_xbox() && $o->{method} eq 'cdrom';
+ $o->exit;
} else {
- cat_($f) =~ /^id:(\d):initdefault:\s*$/ && $1;
+ # when refusing license in finish-install:
+ exec("/bin/reboot");
}
}
-sub report_bug {
- my ($prefix, @other) = @_;
+sub selectLanguage_install {
+ my ($in, $locale) = @_;
+
+ my $common = {
+ title => N("Please choose a language to use"),
+ interactive_help_id => 'selectLanguage' };
+
+ my $lang = $locale->{lang};
+ my $langs = $locale->{langs} ||= {};
+ my $using_images = $in->isa('interactive::gtk') && !$::o->{vga16};
+
+ my %name2l = map { lang::l2name($_) => $_ } lang::list_langs();
+ my $listval2val = sub { $_[0] =~ /\|(.*)/ ? $1 : $_[0] };
+
+ #- since gtk version will use images (function image2f) we need to sort differently
+ my $sort_func = $using_images ? \&lang::l2transliterated : \&lang::l2name;
+ my @langs = sort { $sort_func->($a) cmp $sort_func->($b) } lang::list_langs();
+
+ if (@langs > 15) {
+ my $add_location = sub {
+ my ($l) = @_;
+ map { "$_|$l" } lang::l2location($l);
+ };
+ @langs = map { $add_location->($_) } @langs;
+
+ #- to create the default value, use the first location for that value :/
+ $lang = first($add_location->($lang));
+ }
+
+ my $non_utf8 = 0;
+ add2hash($common, { cancel => '',
+ focus_first => 1,
+ advanced_messages => formatAlaTeX(N("%s can support multiple languages. Select
+the languages you would like to install. They will be available
+when your installation is complete and you restart your system.", N("Mageia"))),
+ advanced_label => N("Multiple languages"),
+ advanced_title => N("Select Additional Languages"),
+ });
+
+ $in->ask_from_($common, [
+ { val => \$lang, separator => '|',
+ if_($using_images, image2f => sub { $name2l{$_[0]} =~ /^[a-z]/ && "langs/lang-$name2l{$_[0]}" }),
+ format => sub { $_[0] =~ /(.*\|)(.*)/ ? $1 . lang::l2name($2) : lang::l2name($_[0]) },
+ list => \@langs, sort => !$in->isa('interactive::gtk'),
+ focus_out => sub { $langs->{$listval2val->($lang)} = 1 } },
+ { val => \$non_utf8, type => 'bool', text => N("Old compatibility (non UTF-8) encoding"), advanced => 1 },
+ { val => \$langs->{all}, type => 'bool', text => N("All languages"), advanced => 1 },
+ map {
+ { val => \$langs->{$_->[0]}, type => 'bool', disabled => sub { $langs->{all} },
+ text => $_->[1], advanced => 1,
+ image => "langs/lang-$_->[0]",
+ };
+ } sort { $a->[1] cmp $b->[1] } map { [ $_, $sort_func->($_) ] } lang::list_langs(),
+ ]) or return;
+ $locale->{utf8} = !$non_utf8;
+ %$langs = grep_each { $::b } %$langs; #- clean hash
+ $langs->{$listval2val->($lang)} = 1;
+
+ #- convert to the default locale for asked language
+ $locale->{lang} = $listval2val->($lang);
+ lang::lang_changed($locale);
+}
+
+sub selectLanguage_standalone {
+ my ($in, $locale) = @_;
+
+ my $old_lang = $locale->{lang};
+ my $common = { messages => N("Please choose a language to use"),
+ title => N("Language choice"),
+ interactive_help_id => 'selectLanguage' };
+
+ my @langs = sort { lang::l2name($a) cmp lang::l2name($b) } lang::list_langs(exclude_non_installed => 1);
+ my $non_utf8 = !$locale->{utf8};
+ $in->ask_from_($common, [
+ { val => \$locale->{lang}, type => 'list',
+ format => sub { lang::l2name($_[0]) }, list => \@langs, allow_empty_list => 1 },
+ { val => \$non_utf8, type => 'bool', text => N("Old compatibility (non UTF-8) encoding"), advanced => 1 },
+ ]);
+ $locale->{utf8} = !$non_utf8;
+ lang::set($locale);
+ c::init_setlocale() if $in->isa('interactive::gtk');
+ lang::lang_changed($locale) if $old_lang ne $locale->{lang};
+}
+
+sub selectLanguage_and_more_standalone {
+ my ($in, $locale) = @_;
+ eval {
+ local $::isWizard = 1;
+ language:
+ # keep around previous settings so that selectLanguage can keep UTF-8 flag:
+ local $::Wizard_no_previous = 1;
+ selectLanguage_standalone($in, $locale);
+ undef $::Wizard_no_previous;
+ selectCountry($in, $locale) or goto language;
+ };
+ if ($@) {
+ if ($@ !~ /wizcancel/) {
+ die;
+ } else {
+ $in->exit(0);
+ }
+ }
+}
+
+sub selectCountry {
+ my ($in, $locale) = @_;
+
+ my $country = $locale->{country};
+ my $country2locales = lang::countries_to_locales(exclude_non_installed => !$::isInstall);
+ my @countries = keys %$country2locales;
+ my @best = grep {
+ find {
+ $_->{main} eq lang::locale_to_main_locale($locale->{lang});
+ } @{$country2locales->{$_}};
+ } @countries;
+ @best == 1 and @best = ();
- sub header { "
+ my $other = !member($country, @best);
+ my $ext_country = $country;
+ $other and @best = ();
+
+ $in->ask_from_(
+ { title => N("Country / Region"),
+ messages => N("Please choose your country"),
+ interactive_help_id => 'selectCountry.html',
+ if_(@best, advanced_messages => N("Here is the full list of available countries")),
+ advanced_label => @best ? N("Other Countries") : N("Advanced"),
+ },
+ [ if_(@best, { val => \$country, type => 'list', format => \&lang::c2name,
+ list => \@best, sort => 1, changed => sub { $other = 0 } }),
+ { val => \$ext_country, type => 'list', format => \&lang::c2name,
+ list => [ @countries ], advanced => scalar(@best), changed => sub { $other = 1 } },
+ { val => \$locale->{IM}, type => 'combo', label => N("Input method:"),
+ sort => 0, separator => '|',
+ list => [ '', lang::get_ims($locale->{lang}) ],
+ format => sub { $_[0] ? uc($_[0] =~ /(.*)\+(.*)/ ? "$1|$1+$2" : $_[0]) : N("None") },
+ advanced => !$locale->{IM},
+ },
+ ]) or return;
+
+ $locale->{country} = $other || !@best ? $ext_country : $country;
+}
+
+sub set_login_serial_console {
+ my ($port, $speed) = @_;
+
+ my $line = "s$port:12345:respawn:/sbin/agetty ttyS$port $speed ansi\n";
+ substInFile { s/^s$port:.*//; $_ = $line if eof } "$::prefix/etc/inittab";
+}
+
+sub header { "
********************************************************************************
* $_[0]
********************************************************************************";
- }
+}
+
+sub fdisk() {
+ my @devs = grep { !m!^/dev/(loop|ram)\d+! && !/\d$/ } map { "/dev/$_->{dev}" } fs::proc_partitions::read_raw();
+ `fdisk -l @devs`;
+
+}
+
+sub report_bug {
+ my (@other) = @_;
join '', map { chomp; "$_\n" }
header("lspci"), detect_devices::stringlist(),
+ header("hid_devices"), (map { sprintf("%-16s: %s", $_->{driver} || "unknown", $_->{description}) } c::hid_probe()),
+ header("input devices"), cat_("/proc/bus/input/devices"),
+ header("libinput devices"), `libinput list-devices`,
header("pci_devices"), cat_("/proc/bus/pci/devices"),
- header("fdisk"), arch() =~ /ppc/ ? `$ENV{LD_LOADER} pdisk -l` : `$ENV{LD_LOADER} fdisk -l`,
+ header("dmidecode"), arch() =~ /86/ ? `dmidecode` : (),
+ header("fdisk"), fdisk(),
header("scsi"), cat_("/proc/scsi/scsi"),
+ header("/sys/bus/scsi/devices"), -d '/sys/bus/scsi/devices' ? `ls -l /sys/bus/scsi/devices` : (),
header("lsmod"), cat_("/proc/modules"),
header("cmdline"), cat_("/proc/cmdline"),
- header("pcmcia: stab"), cat_("/var/run/stab"),
- header("usb"), cat_("/proc/bus/usb/devices"),
+ header("pcmcia: stab"), cat_("$::prefix/var/lib/pcmcia/stab") || cat_("$::prefix/var/run/stab"),
+ header("usb"), cat_("/sys/kernel/debug/usb/devices"),
header("partitions"), cat_("/proc/partitions"),
+ header("PVs"), `pvs`,
+ header("VGs"), `vgs`,
+ header("LVs"), `lvs`,
+ header("dmsetup info"), `dmsetup info`,
+ header("dmsetup table"), `dmsetup table`,
+ header("dmsetup ls"), `dmsetup ls`,
header("cpuinfo"), cat_("/proc/cpuinfo"),
- header("syslog"), cat_("/tmp/syslog"),
- header("ddcxinfos"), `$ENV{LD_LOADER} ddcxinfos`,
- header("ddebug.log"), cat_("/tmp/ddebug.log"),
- header("install.log"), cat_("$prefix/root/install.log"),
- header("fstab"), cat_("$prefix/etc/fstab"),
+ header("syslog"), cat_("/tmp/syslog") || cat_("$::prefix/var/log/syslog") || `journalctl -q -D $::prefix/var/log/journal -b`,
+ header("Xorg.log"), cat_("/var/log/Xorg.0.log"),
+ header("monitor_full_edid"), monitor_full_edid(),
+ header("stage1.log"), cat_("/tmp/stage1.log") || cat_("$::prefix/root/drakx/stage1.log"),
+ header("ddebug.log"), cat_("/tmp/ddebug.log") || cat_("$::prefix/root/drakx/ddebug.log"),
+ header("install.log"), cat_("$::prefix/root/drakx/install.log"),
+ header("draklive-install.log"), cat_("/tmp/draklive-install.log") || cat_("$::prefix/root/drakx/draklive-install.log"),
+ header("fstab"), cat_("$::prefix/etc/fstab"),
+ header("modprobe.conf"), cat_("$::prefix/etc/modprobe.conf"),
+ header("lilo.conf"), cat_("$::prefix/etc/lilo.conf"),
+ header("grub: menu.lst"), join('', map { s/^(\s*password)\s+(.*)/$1 xxx/; $_ } cat_("$::prefix/boot/grub/menu.lst")),
+ header("grub: install.sh"), cat_("$::prefix/boot/grub/install.sh"),
+ header("grub: device.map"), cat_("$::prefix/boot/grub/device.map"),
+ header("grub2: grub"), cat_("$::prefix/etc/default/grub"),
+ header("grub2: grub.cfg"), join('', map { s/^(\s*password_pbkdf2)\s+grub.pbkdf2.*/$1 xxx/; $_ } cat_("$::prefix/boot/grub2/grub.cfg")),
+ header("grub2: install.sh"), cat_("$::prefix/boot/grub2/install.sh"),
+ header("xorg.conf"), cat_("$::prefix/etc/X11/xorg.conf"),
+ header("urpmi.cfg"), cat_("$::prefix/etc/urpmi/urpmi.cfg"),
+ header("modprobe.preload"), cat_("$::prefix/etc/modprobe.preload"),
+ header("sysconfig/i18n"), cat_("$::prefix/etc/sysconfig/i18n"),
+ header("locale.conf"), cat_("$::prefix/etc/locale.conf"),
+ header("/proc/iomem"), cat_("/proc/iomem"),
+ header("/proc/ioport"), cat_("/proc/ioports"),
map_index { even($::i) ? header($_) : $_ } @other;
}
-sub devfssymlinkf {
- my ($if, $of, $prefix) = @_;
- symlinkf($if, "$prefix/$_") foreach ("dev/$of", "lib/dev-state/$of");
+sub fix_broken_alternatives {
+ my ($force_default) = @_;
+ #- fix bad update-alternatives that may occurs after upgrade (and sometimes for install too).
+ -d "$::prefix/etc/alternatives" or return;
+
+ foreach (all("$::prefix/etc/alternatives")) {
+ if ($force_default) {
+ log::l("setting alternative $_");
+ } else {
+ next if run_program::rooted($::prefix, 'test', '-e', "/etc/alternatives/$_");
+ log::l("fixing broken alternative $_");
+ }
+ run_program::rooted($::prefix, 'update-alternatives', '--auto', $_);
+ }
+}
+
+
+sub fileshare_config {
+ my ($in, $type) = @_; #- $type is 'nfs', 'smb' or ''
+
+ my $file = '/etc/security/fileshare.conf';
+ my %conf = getVarsFromSh($file);
+
+ my @l = (N_("No sharing"), N_("Allow all users"), N_("Custom"));
+ my $restrict = exists $conf{RESTRICT} ? text2bool($conf{RESTRICT}) : 1;
+
+ my $r = $in->ask_from_list_('fileshare',
+N("Would you like to allow users to share some of their directories?
+Allowing this will permit users to simply click on \"Share\" in konqueror and nautilus.
+
+\"Custom\" permit a per-user granularity.
+"),
+ \@l, $l[$restrict ? (getgrnam('fileshare') ? 2 : 0) : 1]) or return;
+ $restrict = $r ne $l[1];
+ my $custom = $r eq $l[2];
+ if ($r ne $l[0]) {
+ require services;
+ my %types = (
+ nfs => [ 'nfs-utils', 'nfs-server',
+ N("NFS: the traditional Unix file sharing system, with less support on Mac and Windows.")
+ ],
+ smb => [ 'samba', 'smb',
+ N("SMB: a file sharing system used by Windows, Mac OS X and many modern Linux systems.")
+ ],
+ );
+ my %l;
+ if ($type) {
+ %l = ($type => 1);
+ } else {
+ %l = map_each { $::a => services::starts_on_boot($::b->[1]) } %types;
+ $in->ask_from_({ messages => N("You can export using NFS or SMB. Please select which you would like to use."),
+ callbacks => { ok_disabled => sub { !any { $_ } values %l } },
+ },
+ [ map { { text => $types{$_}[2], val => \$l{$_}, type => 'bool' } } keys %l ]) or return;
+ }
+ foreach (keys %types) {
+ my ($pkg, $service, $_descr) = @{$types{$_}};
+ my $file = "/usr/lib/systemd/system/${service}.service";
+ if ($l{$_}) {
+ $in->do_pkgs->ensure_is_installed($pkg, $file) or return;
+ services::start($service);
+ services::start_service_on_boot($service);
+ } elsif (-e $file) {
+ services::stop($service);
+ services::do_not_start_service_on_boot($service);
+ }
+ }
+ if ($in->do_pkgs->is_installed('nautilus')) {
+ $in->do_pkgs->ensure_is_installed('nautilus-filesharing') or return;
+ }
+ }
+ $conf{RESTRICT} = bool2yesno($restrict);
+ setVarsInSh($file, \%conf);
+
+ if ($custom) {
+ run_program::rooted($::prefix, 'groupadd', '-r', 'fileshare');
+ if ($in->ask_from_no_check(
+ {
+ -e '/usr/sbin/userdrake' ? (ok => N("Launch userdrake"), cancel => N("Close")) : (cancel => ''),
+ messages =>
+N("The per-user sharing uses the group \"fileshare\".
+You can use userdrake to add a user to this group.")
+ }, [])) {
+ run_program::run('userdrake');
+ }
+ }
+}
+
+sub monitor_full_edid() {
+ return if $::noauto || $::local_install;
+
+ my ($vbe, $edid);
+ {
+ # prevent warnings in install's logs:
+ local $ENV{LC_ALL} = 'C';
+ # don't use --try-in-console as it can cause a GNOME session to die (mga#28124)
+ # with most DMs the DE is running in vt1, so it does nothing anyway
+ run_program::raw({ timeout => 20 },
+ 'monitor-edid', '>', \$edid, '2>', \$vbe,
+ '-v', '--perl');
+ }
+ if ($::isInstall) {
+ foreach (['edid', \$edid], ['vbe', \$vbe]) {
+ my ($name, $val) = @$_;
+ if (-e "/tmp/$name") {
+ my $old = cat_("/tmp/$name");
+ if (length($$val) < length($old)) {
+ log::l("new $name is worse, keeping the previous one");
+ $$val = $old;
+ } elsif (length($$val) > length($old)) {
+ log::l("new $name is better, dropping the previous one");
+ }
+ }
+ output("/tmp/$name", $$val);
+ }
+ }
+ ($edid, $vbe);
+}
+
+# FIXME: is buggy regarding multiple sessions
+sub running_window_manager() {
+ my @window_managers = qw(drakx-matchbox-window-manager ksmserver kwin kwin_x11 kwin_wayland gnome-session icewm wmaker afterstep fvwm fvwm2 fvwm95 mwm twm enlightenment xfce4-session blackbox sawfish olvwm fluxbox compiz lxsession);
+
+ foreach (@window_managers) {
+ my @pids = fuzzy_pidofs(qr/\b$_\b/) or next;
+ return wantarray() ? ($_, @pids) : $_;
+ }
+ undef;
+}
+
+sub set_wm_hints_if_needed {
+ my ($o_in) = @_;
+ my $wm = any::running_window_manager();
+ $o_in->{no_Window_Manager} = !$wm if $o_in;
+ $::set_dialog_hint = $wm eq 'drakx-matchbox-window-manager';
+}
+
+sub ask_window_manager_to_logout {
+ my ($wm) = @_;
+
+ my %h = (
+ 'ksmserver' => '/usr/lib/qt4/bin/qdbus org.kde.ksmserver /KSMServer logout 1 0 0',
+ 'kwin' => "dcop kdesktop default logout",
+ 'gnome-session' => "gnome-session-save --kill",
+ 'icewm' => "killall -QUIT icewm",
+ 'xfce4-session' => "xfce4-session-logout --logout",
+ 'lxsession' => "lxde-logout",
+ );
+ my $cmd = $h{$wm} or return;
+ if (member($wm, 'ksmserver', 'kwin', 'gnome-session') && $> == 0) {
+ #- we cannot use dcop when we are root
+ if (my $user = $ENV{USERHELPER_UID} && getpwuid($ENV{USERHELPER_UID})) {
+ $cmd = "su $user -c '$cmd'";
+ } else {
+ log::l('missing or unknown $USERHELPER_UID');
+ }
+ }
+ system($cmd);
+ 1;
+}
+
+sub ask_window_manager_to_logout_then_do {
+ my ($wm, $pid, $action) = @_;
+ if (fork()) {
+ ask_window_manager_to_logout($wm);
+ return;
+ }
+
+ open STDIN, "</dev/zero";
+ open STDOUT, ">/dev/null";
+ open STDERR, ">&STDERR";
+ c::setsid();
+ exec 'perl', '-e', q(
+ my ($wm, $pid, $action) = @ARGV;
+ my $nb;
+ for ($nb = 30; $nb && -e "/proc/$pid"; $nb--) { sleep 1 }
+ system($action) if $nb;
+ ), $wm, $pid, $action;
+}
+
+sub ask_for_X_restart {
+ my ($in) = @_;
+
+ $::isStandalone && $in->isa('interactive::gtk') or return;
+
+ my ($wm, $pid) = running_window_manager();
+
+ if (!$wm) {
+ # no window manager, ctrl-alt-del may not be supported, but we still have to restart X..
+ $in->ask_okcancel('', N("You need to logout and back in again for changes to take effect. Press OK to logout now."), 1) or return;
+ system('killall', 'Xorg');
+ }
+ else {
+ $in->ask_okcancel('', N("You need to log out and back in again for changes to take effect"), 1) or return;
+ ask_window_manager_to_logout_then_do($wm, $pid, 'killall Xorg');
+ }
+}
+
+sub alloc_raw_device {
+ my ($prefix, $device) = @_;
+ my $used = 0;
+ my $raw_dev;
+ substInFile {
+ $used = max($used, $1) if m|^\s*/dev/raw/raw(\d+)|;
+ if (eof) {
+ $raw_dev = "raw/raw" . ($used + 1);
+ $_ .= "/dev/$raw_dev /dev/$device\n";
+ }
+ } "$prefix/etc/sysconfig/rawdevices";
+ $raw_dev;
+}
+
+sub config_mtools {
+ my ($prefix) = @_;
+ my $file = "$prefix/etc/mtools.conf";
+ -e $file or return;
+
+ my ($f1, $f2) = detect_devices::floppies_dev();
+ substInFile {
+ s|drive a: file="(.*?)"|drive a: file="/dev/$f1"|;
+ s|drive b: file="(.*?)"|drive b: file="/dev/$f2"| if $f2;
+ } $file;
+}
+
+sub configure_timezone {
+ my ($in, $timezone, $ask_gmt, $o_hide_ntp) = @_;
+
+ require timezone;
+ my $selected_timezone = $in->ask_from_treelist(N("Timezone"), N("Which is your timezone?"), '/', [ timezone::getTimeZones() ], $timezone->{timezone}) or return;
+ $timezone->{timezone} = $selected_timezone;
+
+ configure_time_more($in, $timezone, $o_hide_ntp)
+ or goto &configure_timezone if $ask_gmt || to_bool($timezone->{ntp});
+
+ 1;
+}
+
+sub configure_time_more {
+ my ($in, $timezone, $o_hide_ntp) = @_;
+
+ my $ntp = to_bool($timezone->{ntp});
+ my $servers = timezone::ntp_servers();
+ $timezone->{ntp} ||= 'pool.ntp.org';
+
+ require POSIX;
+ use POSIX qw(strftime);
+ my $time_format = "%H:%M:%S";
+ my $tz_prefix = timezone::get_timezone_prefix();
+ local $ENV{TZ} = ':' . $tz_prefix . '/' . $timezone->{timezone};
+
+ $in->ask_from_({ interactive_help_id => 'configureTimezoneUTC',
+ title => N("Date, Clock & Time Zone Settings"),
+ }, [
+ { label => N("Date, Clock & Time Zone Settings"), title => 1 },
+ { label => N("What is the best time?") },
+ { val => \$timezone->{UTC},
+ type => 'list', list => [ 0, 1 ], format => sub {
+ $_[0] ?
+ N("%s (hardware clock set to UTC)", POSIX::strftime($time_format, localtime())) :
+ N("%s (hardware clock set to local time)", POSIX::strftime($time_format, gmtime()));
+ } },
+ { label => N("NTP Server"), title => 1, advanced => $o_hide_ntp },
+ { text => N("Automatic time synchronization (using NTP)"), val => \$ntp, type => 'bool',
+ advanced => $o_hide_ntp },
+ { val => \$timezone->{ntp}, disabled => sub { !$ntp }, advanced => $o_hide_ntp,
+ type => "list", separator => '|',
+ list => [ keys %$servers ], format => sub { $servers->{$_[0]} } },
+ ]) or return;
+
+ $timezone->{ntp} = '' if !$ntp;
+
+ 1;
+}
+
+sub disable_x_screensaver() {
+ run_program::run("xset", "s", "off");
+ run_program::run("xset", "-dpms");
+}
+
+sub enable_x_screensaver() {
+ run_program::run("xset", "+dpms");
+ run_program::run("xset", "s", "on");
+ run_program::run("xset", "s", "reset");
+}
+
+=item ask_url($in, $o_url)
+
+Asks URL of the mirror
+
+=cut
+
+sub ask_url {
+ my ($in, $o_url) = @_;
+
+ my $url = $o_url;
+ $in->ask_from_({ messages => N("URL of the mirror?"), focus_first => 1 }, [
+ { val => \$url,
+ validate => sub {
+ if ($url =~ m!^(https?|ftp)://!) {
+ 1;
+ } else {
+ $in->ask_warn('', N("URL must start with ftp:// or http:// or https://"));
+ 0;
+ }
+ } } ]) && $url;
+}
+
+=item ask_mirror($in, $type, $o_url)
+
+Retrieves list of mirrors and offers to pick one
+
+=cut
+
+sub ask_mirror {
+ my ($in, $type, $o_url) = @_;
+
+ require mirror;
+
+ my $mirrors = eval {
+ my $_w = $in->wait_message('', N("Contacting %s web site to get the list of available mirrors...", N("Mageia")));
+ mirror::list($in->{product_id}, $type);
+ };
+ my $err = $@;
+ if (!$mirrors) {
+ $in->ask_warn('', N("Failed contacting %s web site to get the list of available mirrors", N("Mageia")) . "\n$err");
+ return ask_url($in, $o_url);
+ }
+
+ my $give_url = { country => '-', host => 'URL' };
+
+ my $mirror;
+ if ($o_url) {
+ $mirror = (find { $_->{url} eq $o_url } @$mirrors) || $give_url;
+ } else {
+ #- use current time zone to select best mirror
+ require urpm::mirrors;
+ my $urpm = $in->{packages} || { log => \&log::l };
+ urpm::mirrors::add_proximity_and_sort($urpm, $mirrors);
+ $mirror = @$mirrors[0] || $give_url;
+ }
+ $in->ask_from_({ messages => N("Choose a mirror from which to get the packages"),
+ cancel => N("Cancel"),
+ }, [ { separator => '|',
+ format => \&mirror::mirror2text,
+ list => [ @$mirrors, $give_url ],
+ val => \$mirror,
+ },
+ ]) or return;
+
+ my $url;
+ if ($mirror eq $give_url) {
+ $url = ask_url($in, $o_url) or goto &ask_mirror;
+ } else {
+ $url = $mirror->{url};
+ }
+ $url =~ s!/main/?$!!;
+ log::l("chosen mirror: $url");
+ $url;
+}
+
+=item ask_mirror_and_downloader($in, $options, $o_downloader_only)
+
+Asks whether to automatically select the mirror (using $MIRRORLIST) or use
+one specified by the user. Also asks whether to use the default downloader
+or to use one specified by the user.
+
+Default values are supplied and user-entered values are returned in $options
+which should be a reference to a hash containing the following fields:
+
+=over 4
+
+=item * B<mirror_url>: the currently selected mirror URL ('$MIRRORLIST' for automatic selection)
+
+=item * B<downloader>: the currently selected downloader (undefined when using the default downloader)
+
+=back
+
+If $o_downloader_only is true, the mirror selection choice is not displayed.
+
+=cut
+
+sub ask_mirror_and_downloader {
+ my ($in, $options, $o_downloader_only) = @_;
+
+ my $mirror_url = $options->{mirror_url} || '';
+ my $downloader = $options->{downloader} || 'default';
+
+ my $mirror_choice = $mirror_url eq '$MIRRORLIST' ? 'automatic' : 'specific';
+
+ my $enable_aria2 = $::isInstall || $in->do_pkgs->is_installed('aria2', '/usr/bin/aria2c');
+ my $enable_curl = $::isInstall || $in->do_pkgs->is_installed('curl', '/usr/bin/curl');
+ my $enable_wget = $::isInstall || $in->do_pkgs->is_installed('wget', '/usr/bin/wget');
+
+ $in->ask_from_(
+ {
+ },
+ [
+ if_(!$o_downloader_only,
+ { label => N("Mirror choice"), val => \$mirror_choice,
+ type => 'combo', list => [ 'automatic', 'specific' ],
+ format => sub {
+ my ($choice) = @_;
+ +{
+ 'automatic' => N("Automatic"),
+ 'specific' => N("Specific"),
+ }->{$choice};
+ },
+ },
+ ),
+ { label => N("Downloader"), val => \$downloader,
+ type => 'combo', list => [ 'default', 'aria2', 'curl', 'wget' ],
+ format => sub {
+ my ($choice) = @_;
+ +{
+ 'default' => N("Default"),
+ if_($enable_aria2, 'aria2' => 'aria2'),
+ if_($enable_curl, 'curl' => 'curl'),
+ if_($enable_wget, 'wget' => 'wget'),
+ }->{$choice};
+ },
+ },
+ ]
+ ) or return;
+
+ if ($mirror_choice eq 'automatic') {
+ $mirror_url = '$MIRRORLIST';
+ } elsif ($mirror_url eq '$MIRRORLIST') {
+ $mirror_url = undef;
+ }
+ if ($downloader eq 'default') {
+ $downloader = undef;
+ }
+
+ $options->{mirror_url} = $mirror_url;
+ $options->{downloader} = $downloader;
+
+ 1;
}
1;