/[soft]/drakx/trunk/perl-install/any.pm
ViewVC logotype

Contents of /drakx/trunk/perl-install/any.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3571 - (show annotations) (download)
Mon Mar 19 18:33:40 2012 UTC (12 years, 5 months ago) by colin
File size: 59344 byte(s)
- use "splash" on the kernel command line vs. "splash=silent" as per upstream
  code (e.g. plymouth, systemd and others)
- support the "quiet" kernel command line argument to hide kernel text


1 package any; # $Id$
2
3 use diagnostics;
4 use strict;
5
6 #-######################################################################################
7 #- misc imports
8 #-######################################################################################
9 use common;
10 use detect_devices;
11 use partition_table;
12 use fs::type;
13 use lang;
14 use run_program;
15 use devices;
16 use modules;
17 use log;
18 use fs;
19 use c;
20
21 sub facesdir() {
22 "$::prefix/usr/share/mga/faces/";
23 }
24 sub face2png {
25 my ($face) = @_;
26 facesdir() . $face . ".png";
27 }
28 sub facesnames() {
29 my $dir = facesdir();
30 my @l = grep { /^[A-Z]/ } all($dir);
31 map { if_(/(.*)\.png/, $1) } (@l ? @l : all($dir));
32 }
33
34 sub addKdmIcon {
35 my ($user, $icon) = @_;
36 my $dest = "$::prefix/usr/share/faces/$user.png";
37 eval { cp_af(facesdir() . $icon . ".png", $dest) } if $icon;
38 }
39
40 sub alloc_user_faces {
41 my ($users) = @_;
42 my @m = my @l = facesnames();
43 foreach (grep { !$_->{icon} || $_->{icon} eq "automagic" } @$users) {
44 $_->{auto_icon} = splice(@m, rand(@m), 1); #- known biased (see cookbook for better)
45 log::l("auto_icon is $_->{auto_icon}");
46 @m = @l unless @m;
47 }
48 }
49
50 sub create_user {
51 my ($u, $authentication) = @_;
52
53 my @existing = stat("$::prefix/home/$u->{name}");
54
55 if (!getpwnam($u->{name})) {
56 my $uid = $u->{uid} || $existing[4];
57 if ($uid && getpwuid($uid)) {
58 undef $uid; #- suggested uid already in use
59 }
60 my $gid = $u->{gid} || $existing[5] || int getgrnam($u->{name});
61 if ($gid) {
62 if (getgrgid($gid)) {
63 undef $gid if getgrgid($gid) ne $u->{name};
64 } else {
65 run_program::rooted($::prefix, 'groupadd', '-g', $gid, $u->{name});
66 }
67 } elsif ($u->{rename_from}) {
68 run_program::rooted($::prefix, 'groupmod', '-n', $u->{name}, $u->{rename_from});
69 }
70
71 require authentication;
72 my $symlink_home_from = $u->{rename_from} && (getpwnam($u->{rename_from}))[7];
73 run_program::raw({ root => $::prefix, sensitive_arguments => 1 },
74 ($u->{rename_from} ? 'usermod' : 'adduser'),
75 '-p', authentication::user_crypted_passwd($u, $authentication),
76 if_($uid, '-u', $uid), if_($gid, '-g', $gid),
77 if_($u->{realname}, '-c', $u->{realname}),
78 if_($u->{home}, '-d', $u->{home}, if_($u->{rename_from}, '-m')),
79 if_($u->{shell}, '-s', $u->{shell}),
80 ($u->{rename_from}
81 ? ('-l', $u->{name}, $u->{rename_from})
82 : $u->{name}));
83 symlink($u->{home}, $symlink_home_from) if $symlink_home_from;
84 }
85
86 my (undef, undef, $uid, $gid, undef, undef, undef, $home) = getpwnam($u->{name});
87
88 if (@existing && $::isInstall && ($uid != $existing[4] || $gid != $existing[5])) {
89 log::l("chown'ing $home from $existing[4].$existing[5] to $uid.$gid");
90 eval { common::chown_('recursive', $uid, $gid, "$::prefix$home") };
91 }
92 }
93
94 sub add_users {
95 my ($users, $authentication) = @_;
96
97 alloc_user_faces($users);
98
99 foreach (@$users) {
100 create_user($_, $authentication);
101 run_program::rooted($::prefix, "usermod", "-G", join(",", @{$_->{groups}}), $_->{name}) if !is_empty_array_ref($_->{groups});
102 addKdmIcon($_->{name}, delete $_->{auto_icon} || $_->{icon});
103 }
104 }
105
106 sub install_bootloader_pkgs {
107 my ($do_pkgs, $b) = @_;
108
109 bootloader::ensure_pkg_is_installed($do_pkgs, $b);
110 install_acpi_pkgs($do_pkgs, $b);
111 }
112
113 sub install_acpi_pkgs {
114 my ($do_pkgs, $b) = @_;
115
116 my $acpi = bootloader::get_append_with_key($b, 'acpi');
117 my $use_acpi = !member($acpi, 'off', 'ht');
118 if ($use_acpi) {
119 $do_pkgs->ensure_is_installed('acpi', '/usr/bin/acpi', $::isInstall);
120 $do_pkgs->ensure_is_installed('acpid', '/usr/sbin/acpid', $::isInstall);
121 }
122 require services;
123 services::set_status($_, $use_acpi, $::isInstall) foreach qw(acpi acpid);
124 }
125
126 sub setupBootloaderBeforeStandalone {
127 my ($do_pkgs, $b, $all_hds, $fstab) = @_;
128 require keyboard;
129 my $keyboard = keyboard::read_or_default();
130 my $allow_fb = listlength(cat_("/proc/fb"));
131 my $cmdline = cat_('/proc/cmdline');
132 my $vga_fb = first($cmdline =~ /\bvga=(\S+)/);
133 my $splash = $cmdline =~ /\bsplash\b/;
134 my $quiet = $cmdline =~ /\bquiet\b/;
135 setupBootloaderBefore($do_pkgs, $b, $all_hds, $fstab, $keyboard, $allow_fb, $vga_fb, $splash, $quiet);
136 }
137
138 sub setupBootloaderBefore {
139 my ($_do_pkgs, $bootloader, $all_hds, $fstab, $keyboard, $allow_fb, $vga_fb, $splash, $quiet) = @_;
140 require bootloader;
141
142 #- auto_install backward compatibility
143 #- one should now use {message_text}
144 if ($bootloader->{message} =~ m!^[^/]!) {
145 $bootloader->{message_text} = delete $bootloader->{message};
146 }
147
148 #- remove previous ide-scsi lines
149 bootloader::modify_append($bootloader, sub {
150 my ($_simple, $dict) = @_;
151 @$dict = grep { $_->[1] ne 'ide-scsi' } @$dict;
152 });
153
154 if (cat_("/proc/cmdline") =~ /mem=nopentium/) {
155 bootloader::set_append_with_key($bootloader, mem => 'nopentium');
156 }
157 if (cat_("/proc/cmdline") =~ /\b(pci)=(\S+)/) {
158 bootloader::set_append_with_key($bootloader, $1, $2);
159 }
160 if (my ($acpi) = cat_("/proc/cmdline") =~ /\bacpi=(\w+)/) {
161 if ($acpi eq 'ht') {
162 #- the user is using the default, which may not be the best
163 my $year = detect_devices::computer_info()->{BIOS_Year};
164 if ($year >= 2002) {
165 log::l("forcing ACPI on recent bios ($year)");
166 $acpi = '';
167 }
168 }
169 bootloader::set_append_with_key($bootloader, acpi => $acpi);
170 }
171 if (cat_("/proc/cmdline") =~ /\bnoapic/) {
172 bootloader::set_append_simple($bootloader, 'noapic');
173 }
174 if (cat_("/proc/cmdline") =~ /\bnoresume/) {
175 bootloader::set_append_simple($bootloader, 'noresume');
176 } elsif (bootloader::get_append_simple($bootloader, 'noresume')) {
177 } else {
178 if (my ($biggest_swap) = sort { $b->{size} <=> $a->{size} } grep { isSwap($_) } @$fstab) {
179 bootloader::set_append_with_key($bootloader, resume => fs::wild_device::from_part('', $biggest_swap));
180 }
181 }
182
183 #- set nokmsboot if a conflicting driver is configured.
184 if (-x "$::prefix/sbin/display_driver_helper" && !run_program::rooted($::prefix, "/sbin/display_driver_helper", "--is-kms-allowed")) {
185 bootloader::set_append_simple($bootloader, 'nokmsboot');
186 }
187
188 #- check for valid fb mode to enable a default boot with frame buffer.
189 my $vga = $allow_fb && (!detect_devices::matching_desc__regexp('3D Rage LT') &&
190 !detect_devices::matching_desc__regexp('Rage Mobility [PL]') &&
191 !detect_devices::matching_desc__regexp('i740') &&
192 !detect_devices::matching_desc__regexp('Matrox') &&
193 !detect_devices::matching_desc__regexp('Tseng.*ET6\d00') &&
194 !detect_devices::matching_desc__regexp('SiS.*SG86C2.5') &&
195 !detect_devices::matching_desc__regexp('SiS.*559[78]') &&
196 !detect_devices::matching_desc__regexp('SiS.*300') &&
197 !detect_devices::matching_desc__regexp('SiS.*540') &&
198 !detect_devices::matching_desc__regexp('SiS.*6C?326') &&
199 !detect_devices::matching_desc__regexp('SiS.*6C?236') &&
200 !detect_devices::matching_desc__regexp('Voodoo [35]|Voodoo Banshee') && #- 3d acceleration seems to bug in fb mode
201 !detect_devices::matching_desc__regexp('828[14][05].* CGC') #- i810 & i845 now have FB support during install but we disable it afterwards
202 );
203 my $force_vga = $allow_fb && (detect_devices::matching_desc__regexp('SiS.*630') || #- SiS 630 need frame buffer.
204 detect_devices::matching_desc__regexp('GeForce.*Integrated') #- needed for fbdev driver (hack).
205 );
206
207 #- propose the default fb mode for kernel fb, if bootsplash is installed.
208 my $need_fb = -e "$::prefix/usr/share/bootsplash/scripts/make-boot-splash";
209 bootloader::suggest($bootloader, $all_hds,
210 vga_fb => ($force_vga || $vga && $need_fb) && $vga_fb,
211 splash => $splash,
212 quiet => $quiet);
213
214 $bootloader->{keytable} ||= keyboard::keyboard2kmap($keyboard);
215 log::l("setupBootloaderBefore end");
216 }
217
218 sub setupBootloader {
219 my ($in, $b, $all_hds, $fstab, $security) = @_;
220
221 require bootloader;
222 general:
223 {
224 local $::Wizard_no_previous = 1 if $::isStandalone;
225 setupBootloader__general($in, $b, $all_hds, $fstab, $security) or return 0;
226 }
227 setupBootloader__boot_bios_drive($in, $b, $all_hds->{hds}) or goto general;
228 {
229 local $::Wizard_finished = 1 if $::isStandalone;
230 setupBootloader__entries($in, $b, $all_hds, $fstab) or goto general;
231 }
232 1;
233 }
234
235 sub setupBootloaderUntilInstalled {
236 my ($in, $b, $all_hds, $fstab, $security) = @_;
237 do {
238 my $before = fs::fstab_to_string($all_hds);
239 setupBootloader($in, $b, $all_hds, $fstab, $security) or $in->exit;
240 if ($before ne fs::fstab_to_string($all_hds)) {
241 #- for /tmp using tmpfs when "clean /tmp" is chosen
242 fs::write_fstab($all_hds);
243 }
244 } while !installBootloader($in, $b, $all_hds);
245 }
246
247 sub installBootloader {
248 my ($in, $b, $all_hds) = @_;
249 return if detect_devices::is_xbox();
250
251 if (arch() =~ /mips|arm/) {
252 return 1;
253 }
254 install_bootloader_pkgs($in->do_pkgs, $b);
255
256 eval { run_program::rooted($::prefix, 'echo | lilo -u') } if $::isInstall && !$::o->{isUpgrade} && -e "$::prefix/etc/lilo.conf" && glob("$::prefix/boot/boot.*");
257
258 retry:
259 eval {
260 my $_w = $in->wait_message(N("Please wait"), N("Bootloader installation in progress"));
261 bootloader::install($b, $all_hds);
262 };
263
264 if (my $err = $@) {
265 $err =~ /wizcancel/ and return;
266 $err =~ s/^\w+ failed// or die;
267 $err = formatError($err);
268 while ($err =~ s/^Warning:.*//m) {}
269 if (my ($dev) = $err =~ /^Reference:\s+disk\s+"(.*?)".*^Is the above disk an NT boot disk?/ms) {
270 if ($in->ask_yesorno('',
271 formatAlaTeX(N("LILO wants to assign a new Volume ID to drive %s. However, changing
272 the Volume ID of a Windows NT, 2000, or XP boot disk is a fatal Windows error.
273 This caution does not apply to Windows 95 or 98, or to NT data disks.
274
275 Assign a new Volume ID?", $dev)))) {
276 $b->{force_lilo_answer} = 'n';
277 } else {
278 $b->{'static-bios-codes'} = 1;
279 }
280 goto retry;
281 } else {
282 $in->ask_warn('', [ N("Installation of bootloader failed. The following error occurred:"), $err ]);
283 return;
284 }
285 } elsif (arch() =~ /ppc/) {
286 if (detect_devices::get_mac_model() !~ /IBM/) {
287 my $of_boot = bootloader::dev2yaboot($b->{boot});
288 $in->ask_warn('', N("You may need to change your Open Firmware boot-device to\n enable the bootloader. If you do not see the bootloader prompt at\n reboot, hold down Command-Option-O-F at reboot and enter:\n setenv boot-device %s,\\\\:tbxi\n Then type: shut-down\nAt your next boot you should see the bootloader prompt.", $of_boot));
289 }
290 }
291 1;
292 }
293
294
295 sub setupBootloader_simple {
296 my ($in, $b, $all_hds, $fstab, $security) = @_;
297 my $hds = $all_hds->{hds};
298
299 require bootloader;
300 bootloader::ensafe_first_bios_drive($hds)
301 || $b->{bootUnsafe} || arch() =~ /ppc/ or return 1; #- default is good enough
302
303 if (arch() !~ /ia64/) {
304 setupBootloader__mbr_or_not($in, $b, $hds, $fstab) or return 0;
305 } else {
306 general:
307 setupBootloader__general($in, $b, $all_hds, $fstab, $security) or return 0;
308 }
309 setupBootloader__boot_bios_drive($in, $b, $hds) or goto general;
310 1;
311 }
312
313
314 sub setupBootloader__boot_bios_drive {
315 my ($in, $b, $hds) = @_;
316
317 if (arch() =~ /ppc/ ||
318 !is_empty_hash_ref($b->{bios})) {
319 #- some bios mapping already there
320 return 1;
321 } elsif (bootloader::mixed_kind_of_disks($hds) && $b->{boot} =~ /\d$/) { #- on a partition
322 # see below
323 } else {
324 return 1;
325 }
326
327 log::l("_ask_boot_bios_drive");
328 my $hd = $in->ask_from_listf('', N("You decided to install the bootloader on a partition.
329 This implies you already have a bootloader on the hard disk drive you boot (eg: System Commander).
330
331 On which drive are you booting?"), \&partition_table::description, $hds) or return 0;
332 log::l("mixed_kind_of_disks chosen $hd->{device}");
333 $b->{first_hd_device} = "/dev/$hd->{device}";
334 1;
335 }
336
337 sub _ask_mbr_or_not {
338 my ($in, $default, @l) = @_;
339 $in->ask_from_({ title => N("Bootloader Installation"),
340 interactive_help_id => 'setupBootloaderBeginner',
341 },
342 [
343 { label => N("Where do you want to install the bootloader?"), title => 1 },
344 { val => \$default, list => \@l, format => sub { $_[0][0] }, type => 'list' },
345 ]
346 );
347 $default;
348 }
349
350 sub setupBootloader__mbr_or_not {
351 my ($in, $b, $hds, $fstab) = @_;
352
353 log::l("setupBootloader__mbr_or_not");
354
355 if (arch() =~ /ppc/) {
356 if (defined $partition_table::mac::bootstrap_part) {
357 $b->{boot} = $partition_table::mac::bootstrap_part;
358 log::l("set bootstrap to $b->{boot}");
359 } else {
360 die "no bootstrap partition - yaboot.conf creation failed";
361 }
362 } else {
363 my $floppy = detect_devices::floppy();
364
365 my @l = (
366 bootloader::ensafe_first_bios_drive($hds) ?
367 (map { [ N("First sector (MBR) of drive %s", partition_table::description($_)) => '/dev/' . $_->{device} ] } @$hds)
368 :
369 [ N("First sector of drive (MBR)") => '/dev/' . $hds->[0]{device} ],
370
371 [ N("First sector of the root partition") => '/dev/' . fs::get::root($fstab, 'boot')->{device} ],
372 if_($floppy,
373 [ N("On Floppy") => "/dev/$floppy" ],
374 ),
375 [ N("Skip") => '' ],
376 );
377
378 my $default = find { $_->[1] eq $b->{boot} } @l;
379 if (!$::isInstall) {
380 $default = _ask_mbr_or_not($in, $default, @l);
381 }
382 my $new_boot = $default->[1];
383
384 #- remove bios mapping if the user changed the boot device
385 delete $b->{bios} if $new_boot && $new_boot ne $b->{boot};
386 $b->{boot} = $new_boot or return;
387 }
388 1;
389 }
390
391 sub get_apple_boot_parts {
392 my ($fstab) = @_;
393 map { "/dev/$_" } (map { $_->{device} } (grep { isAppleBootstrap($_) } @$fstab));
394 }
395
396 sub setupBootloader__general {
397 my ($in, $b, $all_hds, $fstab, $_security) = @_;
398
399 return if detect_devices::is_xbox();
400 my @method_choices = bootloader::method_choices($all_hds);
401 my $prev_force_acpi = my $force_acpi = bootloader::get_append_with_key($b, 'acpi') !~ /off|ht/;
402 my $prev_enable_apic = my $enable_apic = !bootloader::get_append_simple($b, 'noapic');
403 my $prev_enable_lapic = my $enable_lapic = !bootloader::get_append_simple($b, 'nolapic');
404 my $prev_enable_smp = my $enable_smp = !bootloader::get_append_simple($b, 'nosmp');
405 my $prev_clean_tmp = my $clean_tmp = any { $_->{mntpoint} eq '/tmp' } @{$all_hds->{special} ||= []};
406 my $prev_boot = $b->{boot};
407 my $prev_method = $b->{method};
408
409 $b->{password2} ||= $b->{password} ||= '';
410 $::Wizard_title = N("Boot Style Configuration");
411 if (arch() !~ /ppc/) {
412 my (@boot_devices, %boot_devices);
413 foreach (bootloader::allowed_boot_parts($b, $all_hds)) {
414 my $dev = "/dev/$_->{device}";
415 push @boot_devices, $dev;
416 my $name = $_->{info} || $_->{device_LABEL};
417 $boot_devices{$dev} = $name ? "$dev ($name)" : $dev;
418 }
419
420 $in->ask_from_({ #messages => N("Bootloader main options"),
421 title => N("Bootloader main options"),
422 interactive_help_id => 'setupBootloader',
423 }, [
424 #title => N("Bootloader main options"),
425 { label => N("Bootloader"), title => 1 },
426 { label => N("Bootloader to use"), val => \$b->{method},
427 list => \@method_choices, format => \&bootloader::method2text },
428 if_(arch() !~ /ia64/,
429 { label => N("Boot device"), val => \$b->{boot}, list => \@boot_devices,
430 format => sub { $boot_devices{$_[0]} } },
431 ),
432 { label => N("Main options"), title => 1 },
433 { label => N("Delay before booting default image"), val => \$b->{timeout} },
434 { text => N("Enable ACPI"), val => \$force_acpi, type => 'bool', advanced => 1 },
435 { text => N("Enable SMP"), val => \$enable_smp, type => 'bool', advanced => 1 },
436 { text => N("Enable APIC"), val => \$enable_apic, type => 'bool', advanced => 1,
437 disabled => sub { !$enable_lapic } },
438 { text => N("Enable Local APIC"), val => \$enable_lapic, type => 'bool', advanced => 1 },
439 { label => N("Security"), title => 1 },
440 { label => N("Password"), val => \$b->{password}, hidden => 1,
441 validate => sub {
442 my $ok = $b->{password} eq $b->{password2}
443 or $in->ask_warn('', [ N("The passwords do not match"), N("Please try again") ]);
444 my $ok2 = !($b->{password} && $b->{method} eq 'grub-graphic')
445 or $in->ask_warn('', N("You cannot use a password with %s",
446 bootloader::method2text($b->{method})));
447 $ok && $ok2;
448 } },
449 { label => N("Password (again)"), val => \$b->{password2}, hidden => 1 },
450 { text => N("Clean /tmp at each boot"), val => \$clean_tmp, type => 'bool', advanced => 1 },
451 ]) or return 0;
452 } else {
453 $b->{boot} = $partition_table::mac::bootstrap_part;
454 $in->ask_from_({ messages => N("Bootloader main options"),
455 title => N("Bootloader main options"),
456 interactive_help_id => 'setupYabootGeneral',
457 }, [
458 { label => N("Bootloader to use"), val => \$b->{method},
459 list => \@method_choices, format => \&bootloader::method2text },
460 { label => N("Init Message"), val => \$b->{'init-message'} },
461 { label => N("Boot device"), val => \$b->{boot}, list => [ get_apple_boot_parts($fstab) ] },
462 { label => N("Open Firmware Delay"), val => \$b->{delay} },
463 { label => N("Kernel Boot Timeout"), val => \$b->{timeout} },
464 { label => N("Enable CD Boot?"), val => \$b->{enablecdboot}, type => "bool" },
465 { label => N("Enable OF Boot?"), val => \$b->{enableofboot}, type => "bool" },
466 { label => N("Default OS?"), val => \$b->{defaultos}, list => [ 'linux', 'macos', 'macosx', 'darwin' ] },
467 ]) or return 0;
468 }
469
470 #- remove bios mapping if the user changed the boot device
471 delete $b->{bios} if $b->{boot} ne $prev_boot;
472
473 if ($b->{boot} =~ m!/dev/md\d+$!) {
474 $b->{'raid-extra-boot'} = 'mbr';
475 } else {
476 delete $b->{'raid-extra-boot'} if $b->{'raid-extra-boot'} eq 'mbr';
477 }
478
479 bootloader::ensure_pkg_is_installed($in->do_pkgs, $b) or goto &setupBootloader__general;
480
481 bootloader::suggest_message_text($b) if ! -e "$::prefix/boot/message-text"; #- in case we switch from grub to lilo
482
483 if ($prev_force_acpi != $force_acpi) {
484 bootloader::set_append_with_key($b, acpi => ($force_acpi ? '' : 'ht'));
485 }
486
487 if ($prev_enable_smp != $enable_smp) {
488 ($enable_smp ? \&bootloader::remove_append_simple : \&bootloader::set_append_simple)->($b, 'nosmp');
489 }
490
491 if ($prev_enable_apic != $enable_apic) {
492 ($enable_apic ? \&bootloader::remove_append_simple : \&bootloader::set_append_simple)->($b, 'noapic');
493 ($enable_apic ? \&bootloader::set_append_simple : \&bootloader::remove_append_simple)->($b, 'apic');
494 }
495 if ($prev_enable_lapic != $enable_lapic) {
496 ($enable_lapic ? \&bootloader::remove_append_simple : \&bootloader::set_append_simple)->($b, 'nolapic');
497 ($enable_lapic ? \&bootloader::set_append_simple : \&bootloader::remove_append_simple)->($b, 'lapic');
498 }
499
500 if ($prev_clean_tmp != $clean_tmp) {
501 if ($clean_tmp && !fs::get::has_mntpoint('/tmp', $all_hds)) {
502 push @{$all_hds->{special}}, { device => 'none', mntpoint => '/tmp', fs_type => 'tmpfs' };
503 } else {
504 @{$all_hds->{special}} = grep { $_->{mntpoint} ne '/tmp' } @{$all_hds->{special}};
505 }
506 }
507
508 if (bootloader::main_method($prev_method) eq 'lilo' &&
509 bootloader::main_method($b->{method}) eq 'grub') {
510 log::l("switching for lilo to grub, ensure we don't read lilo.conf anymore");
511 renamef("$::prefix/etc/lilo.conf", "$::prefix/etc/lilo.conf.unused");
512 }
513 1;
514 }
515
516 sub setupBootloader__entries {
517 my ($in, $b, $all_hds, $fstab) = @_;
518
519 require Xconfig::resolution_and_depth;
520
521 my $Modify = sub {
522 require network::network; #- to list network profiles
523 my ($e) = @_;
524 my $default = my $old_default = $e->{label} eq $b->{default};
525 my $vga = Xconfig::resolution_and_depth::from_bios($e->{vga});
526 my ($append, $netprofile) = bootloader::get_append_netprofile($e);
527
528 my %hd_infos = map { $_->{device} => $_->{info} } fs::get::hds($all_hds);
529 my %root_descr = map {
530 my $info = delete $hd_infos{$_->{rootDevice}};
531 my $dev = "/dev/$_->{device}";
532 my $hint = $info || $_->{info} || $_->{device_LABEL};
533 my $info_ = $hint ? "$dev ($hint)" : $dev;
534 ($dev => $info_, fs::wild_device::from_part('', $_) => $info_);
535 } @$fstab;
536
537 my @l;
538 if ($e->{type} eq "image") {
539 @l = (
540 { label => N("Image"), val => \$e->{kernel_or_dev}, list => [ map { "/boot/$_" } bootloader::installed_vmlinuz() ], not_edit => 0 },
541 { label => N("Root"), val => \$e->{root}, list => [ map { fs::wild_device::from_part('', $_) } @$fstab ], format => sub { $root_descr{$_[0]} } },
542 { label => N("Append"), val => \$append },
543 if_($e->{xen},
544 { label => N("Xen append"), val => \$e->{xen_append} }
545 ),
546 if_($b->{password}, { label => N("Requires password to boot"), val => \$e->{lock}, type => "bool" }),
547 if_(arch() !~ /ppc|ia64/,
548 { label => N("Video mode"), val => \$vga, list => [ '', Xconfig::resolution_and_depth::bios_vga_modes() ], format => \&Xconfig::resolution_and_depth::to_string, advanced => 1 },
549 ),
550 { label => N("Initrd"), val => \$e->{initrd}, list => [ map { if_(/^initrd/, "/boot/$_") } all("$::prefix/boot") ], not_edit => 0, advanced => 1 },
551 { label => N("Network profile"), val => \$netprofile, list => [ sort(uniq('', $netprofile, network::network::netprofile_list())) ], advanced => 1 },
552 );
553 } else {
554 @l = (
555 { label => N("Root"), val => \$e->{kernel_or_dev}, list => [ map { "/dev/$_->{device}" } @$fstab, detect_devices::floppies() ] },
556 );
557 }
558 if (arch() !~ /ppc/) {
559 @l = (
560 { label => N("Label"), val => \$e->{label} },
561 @l,
562 { text => N("Default"), val => \$default, type => 'bool' },
563 );
564 } else {
565 unshift @l, { label => N("Label"), val => \$e->{label}, list => ['macos', 'macosx', 'darwin'] };
566 if ($e->{type} eq "image") {
567 @l = ({ label => N("Label"), val => \$e->{label} },
568 (@l[1..2], { label => N("Append"), val => \$append }),
569 { label => N("NoVideo"), val => \$e->{novideo}, type => 'bool' },
570 { text => N("Default"), val => \$default, type => 'bool' }
571 );
572 }
573 }
574
575 $in->ask_from_(
576 {
577 interactive_help_id => arch() =~ /ppc/ ? 'setupYabootAddEntry' : 'setupBootloaderAddEntry',
578 callbacks => {
579 complete => sub {
580 $e->{label} or $in->ask_warn('', N("Empty label not allowed")), return 1;
581 $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;
582 member(lc $e->{label}, map { lc $_->{label} } grep { $_ != $e } @{$b->{entries}}) and $in->ask_warn('', N("This label is already used")), return 1;
583 0;
584 } } }, \@l) or return;
585
586 $b->{default} = $old_default || $default ? $default && $e->{label} : $b->{default};
587 my $new_vga = ref($vga) ? $vga->{bios} : $vga;
588 if ($new_vga ne $e->{vga}) {
589 $e->{vga} = $new_vga;
590 $e->{initrd} and bootloader::add_boot_splash($e->{initrd}, $e->{vga});
591 }
592 bootloader::set_append_netprofile($e, $append, $netprofile);
593 bootloader::configure_entry($b, $e); #- hack to make sure initrd file are built.
594 1;
595 };
596
597 my $Add = sub {
598 my @labels = map { $_->{label} } @{$b->{entries}};
599 my ($e, $prefix);
600 if ($in->ask_from_list_('', N("Which type of entry do you want to add?"),
601 [ N_("Linux"), arch() =~ /sparc/ ? N_("Other OS (SunOS...)") : arch() =~ /ppc/ ?
602 N_("Other OS (MacOS...)") : N_("Other OS (Windows...)") ]
603 ) eq "Linux") {
604 $e = { type => 'image',
605 root => '/dev/' . fs::get::root($fstab)->{device}, #- assume a good default.
606 };
607 $prefix = "linux";
608 } else {
609 $e = { type => 'other' };
610 $prefix = arch() =~ /sparc/ ? "sunos" : arch() =~ /ppc/ ? "macos" : "windows";
611 }
612 $e->{label} = $prefix;
613 for (my $nb = 0; member($e->{label}, @labels); $nb++) {
614 $e->{label} = "$prefix-$nb";
615 }
616 $Modify->($e) or return;
617 bootloader::add_entry($b, $e);
618 $e;
619 };
620
621 my $Remove = sub {
622 my ($e) = @_;
623 delete $b->{default} if $b->{default} eq $e->{label};
624 @{$b->{entries}} = grep { $_ != $e } @{$b->{entries}};
625 1;
626 };
627
628 my $Up = sub {
629 my ($e) = @_;
630 my @entries = @{$b->{entries}};
631 my ($index) = grep { $entries[$_]{label} eq $e->{label} } 0..$#entries;
632 if ($index > 0) {
633 ($b->{entries}[$index - 1], $b->{entries}[$index]) = ($b->{entries}[$index], $b->{entries}[$index - 1]);
634 }
635 1;
636 };
637
638 my $Down = sub {
639 my ($e) = @_;
640 my @entries = @{$b->{entries}};
641 my ($index) = grep { $entries[$_]{label} eq $e->{label} } 0..$#entries;
642 if ($index < $#entries) {
643 ($b->{entries}[$index + 1], $b->{entries}[$index]) = ($b->{entries}[$index], $b->{entries}[$index + 1]);
644 }
645 1;
646 };
647
648 my @prev_entries = @{$b->{entries}};
649 if ($in->ask_from__add_modify_remove(N("Bootloader Configuration"),
650 N("Here are the entries on your boot menu so far.
651 You can create additional entries or change the existing ones."), [ {
652 format => sub {
653 my ($e) = @_;
654 ref($e) ?
655 ($b->{default} eq $e->{label} ? " * " : " ") . "$e->{label} ($e->{kernel_or_dev})" :
656 translate($e);
657 }, list => $b->{entries},
658 } ], Add => $Add, Modify => $Modify, Remove => $Remove, Up => $Up, Down => $Down)) {
659 1;
660 } else {
661 @{$b->{entries}} = @prev_entries;
662 '';
663 }
664 }
665
666 sub get_autologin() {
667 my %desktop = getVarsFromSh("$::prefix/etc/sysconfig/desktop");
668 my $gdm_file = "$::prefix/etc/X11/gdm/custom.conf";
669 my $kdm_file = common::read_alternative('kdm4-config');
670 my $autologin_file = "$::prefix/etc/sysconfig/autologin";
671 my $desktop = $desktop{DESKTOP} || first(sessions());
672 my %desktop_to_dm = (
673 GNOME => 'gdm',
674 KDE4 => 'kdm',
675 xfce4 => 'gdm',
676 LXDE => 'lxdm',
677 );
678 my %dm_canonical = (
679 gnome => 'gdm',
680 kde => 'kdm',
681 );
682 my $dm =
683 lc($desktop{DISPLAYMANAGER}) ||
684 $desktop_to_dm{$desktop} ||
685 basename(chomp_(run_program::rooted_get_stdout($::prefix, "/etc/X11/lookupdm")));
686 $dm = $dm_canonical{$dm} if exists $dm_canonical{$dm};
687
688 my $autologin_user;
689 if ($dm eq "gdm") {
690 my %conf = read_gnomekderc($gdm_file, 'daemon');
691 $autologin_user = text2bool($conf{AutomaticLoginEnable}) && $conf{AutomaticLogin};
692 } elsif ($dm eq "kdm") {
693 my %conf = read_gnomekderc($kdm_file, 'X-:0-Core');
694 $autologin_user = text2bool($conf{AutoLoginEnable}) && $conf{AutoLoginUser};
695 } else {
696 my %conf = getVarsFromSh($autologin_file);
697 $autologin_user = text2bool($conf{AUTOLOGIN}) && $conf{USER};
698 }
699
700 { user => $autologin_user, desktop => $desktop, dm => $dm };
701 }
702
703 sub set_autologin {
704 my ($do_pkgs, $autologin) = @_;
705 log::l("set_autologin $autologin->{user} $autologin->{desktop}");
706 my $do_autologin = bool2text($autologin->{user});
707
708 $autologin->{dm} ||= 'xdm';
709 $do_pkgs->ensure_is_installed($autologin->{dm})
710 or return;
711 if ($autologin->{user} && $autologin->{dm} eq 'xdm') {
712 $do_pkgs->ensure_is_installed('autologin', '/usr/bin/startx.autologin')
713 or return;
714 }
715
716 #- Configure KDM / MDKKDM
717 my $kdm_conffile = common::read_alternative('kdm4-config');
718 eval { common::update_gnomekderc_no_create($kdm_conffile, 'X-:0-Core' => (
719 AutoLoginEnable => $do_autologin,
720 AutoLoginUser => $autologin->{user},
721 )) } if -e $kdm_conffile;
722
723 #- Configure GDM
724 my $gdm_conffile = "$::prefix/etc/X11/gdm/custom.conf";
725 eval { update_gnomekderc($gdm_conffile, daemon => (
726 AutomaticLoginEnable => $do_autologin,
727 AutomaticLogin => $autologin->{user},
728 )) } if -e $gdm_conffile;
729
730 my $xdm_autologin_cfg = "$::prefix/etc/sysconfig/autologin";
731 if ($autologin->{dm} eq 'xdm') {
732 setVarsInShMode($xdm_autologin_cfg, 0644,
733 { USER => $autologin->{user}, AUTOLOGIN => bool2yesno($autologin->{user}), EXEC => '/usr/bin/startx.autologin' });
734 } else {
735 unlink $xdm_autologin_cfg;
736 }
737
738 my $sys_conffile = "$::prefix/etc/sysconfig/desktop";
739 my %desktop = getVarsFromSh($sys_conffile);
740 $desktop{DESKTOP} = $autologin->{desktop};
741 $desktop{DISPLAYMANAGER} = $autologin->{dm};
742 setVarsInSh($sys_conffile, \%desktop);
743
744 if ($autologin->{user}) {
745 my $home = (getpwnam($autologin->{user}))[7];
746 set_window_manager($home, $autologin->{desktop});
747 }
748 }
749 sub set_window_manager {
750 my ($home, $wm) = @_;
751 log::l("set_window_manager $home $wm");
752 my $p_home = "$::prefix$home";
753
754 #- for KDM/GDM
755 my $wm_number = sessions_with_order()->{$wm} || '';
756 update_gnomekderc("$p_home/.dmrc", 'Desktop', Session => "$wm_number$wm");
757 my $user = find { $home eq $_->[7] } list_passwd();
758 chown($user->[2], $user->[3], "$p_home/.dmrc");
759 chmod(0644, "$p_home/.dmrc");
760
761 #- for startx/autologin
762 {
763 my %l = getVarsFromSh("$p_home/.desktop");
764 $l{DESKTOP} = $wm;
765 setVarsInSh("$p_home/.desktop", \%l);
766 }
767 }
768
769 sub rotate_log {
770 my ($f) = @_;
771 if (-e $f) {
772 my $i = 1;
773 for (; -e "$f$i" || -e "$f$i.gz"; $i++) {}
774 rename $f, "$f$i";
775 }
776 }
777 sub rotate_logs {
778 my ($prefix) = @_;
779 rotate_log("$prefix/root/drakx/$_") foreach qw(stage1.log ddebug.log install.log updates.log);
780 }
781
782 sub writeandclean_ldsoconf {
783 my ($prefix) = @_;
784 my $file = "$prefix/etc/ld.so.conf";
785 my @l = chomp_(cat_($file));
786
787 my @default = ('/lib', '/usr/lib'); #- no need to have /lib and /usr/lib in ld.so.conf
788 my @suggest = ('/usr/X11R6/lib', '/usr/lib/qt3/lib'); #- needed for upgrade where package renaming can cause this to disappear
789
790 if (arch() =~ /x86_64/) {
791 @default = map { $_, $_ . '64' } @default;
792 @suggest = map { $_, $_ . '64' } @suggest;
793 }
794 push @l, grep { -d "$::prefix$_" } @suggest;
795 @l = difference2(\@l, \@default);
796
797 log::l("writeandclean_ldsoconf");
798 output($file, map { "$_\n" } uniq(@l));
799 }
800
801 sub shells() {
802 grep { -x "$::prefix$_" } chomp_(cat_("$::prefix/etc/shells"));
803 }
804
805 sub inspect {
806 my ($part, $o_prefix, $b_rw) = @_;
807
808 isMountableRW($part) || !$b_rw && isOtherAvailableFS($part) or return;
809
810 my $dir = $::isInstall ? "/tmp/inspect_tmp_dir" : "/root/.inspect_tmp_dir";
811
812 if ($part->{isMounted}) {
813 $dir = ($o_prefix || '') . $part->{mntpoint};
814 } elsif ($part->{notFormatted} && !$part->{isFormatted}) {
815 $dir = '';
816 } else {
817 mkdir $dir, 0700;
818 eval { fs::mount::mount(fs::wild_device::from_part('', $part), $dir, $part->{fs_type}, !$b_rw) };
819 $@ and return;
820 }
821 my $h = before_leaving {
822 if (!$part->{isMounted} && $dir) {
823 fs::mount::umount($dir);
824 unlink($dir);
825 }
826 };
827 $h->{dir} = $dir;
828 $h;
829 }
830
831 sub ask_user {
832 my ($in, $users, $security, %options) = @_;
833
834 ask_user_and_root($in, undef, $users, $security, %options);
835 }
836
837 sub is_xguest_installed() {
838 -e "$::prefix/etc/security/namespace.d/xguest.conf";
839 }
840
841 sub ask_user_and_root {
842 my ($in, $superuser, $users, $security, %options) = @_;
843
844 my $xguest = is_xguest_installed();
845
846 $options{needauser} ||= $security >= 3;
847
848 my @icons = facesnames();
849 my @suggested_names = $::isInstall ? do {
850 my @l = grep { !/^\./ && $_ ne 'lost+found' && -d "$::prefix/home/$_" } all("$::prefix/home");
851 grep { ! defined getpwnam($_) } @l;
852 } : ();
853
854 my %high_security_groups = (
855 xgrp => N("access to X programs"),
856 rpm => N("access to rpm tools"),
857 wheel => N("allow \"su\""),
858 adm => N("access to administrative files"),
859 ntools => N("access to network tools"),
860 ctools => N("access to compilation tools"),
861 );
862
863 my $u = {};
864 $u->{password2} ||= $u->{password} ||= '';
865 $u->{shell} ||= '/bin/bash';
866 my $names = @$users ? N("(already added %s)", join(", ", map { $_->{realname} || $_->{name} } @$users)) : '';
867
868 my %groups;
869
870 require authentication;
871 my $validate_name = sub {
872 $u->{name} or $in->ask_warn('', N("Please give a user name")), return;
873 $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;
874 length($u->{name}) <= 32 or $in->ask_warn('', N("The user name is too long")), return;
875 defined getpwnam($u->{name}) || member($u->{name}, map { $_->{name} } @$users) and $in->ask_warn('', N("This user name has already been added")), return;
876 'ok';
877 };
878 my $validate_uid_gid = sub {
879 my ($field) = @_;
880 my $id = $u->{$field} or return 'ok';
881 my $name = $field eq 'uid' ? N("User ID") : N("Group ID");
882 $id =~ /^\d+$/ or $in->ask_warn('', N("%s must be a number", $name)), return;
883 $id >= 500 or $in->ask_yesorno('', N("%s should be above 500. Accept anyway?", $name)) or return;
884 'ok';
885 };
886 my $ret = $in->ask_from_(
887 { title => N("User management"),
888 interactive_help_id => 'addUser',
889 if_($::isInstall && $superuser, cancel => ''),
890 }, [
891 $superuser ? (
892 { text => N("Enable guest account"), val => \$xguest, type => 'bool', advanced => 1 },
893 { label => N("Set administrator (root) password"), title => 1 },
894 { label => N("Password"), val => \$superuser->{password}, hidden => 1, alignment => 'right', weakness_check => 1,
895 focus => sub { 1 },
896 validate => sub { authentication::check_given_password($in, $superuser, 2 * $security) } },
897 { label => N("Password (again)"), val => \$superuser->{password2}, hidden => 1, alignment => 'right' },
898 ) : (),
899 { label => N("Enter a user"), title => 1 }, if_($names, { label => $names }),
900 if_($security <= 3 && !$options{noicons} && @icons,
901 { label => N("Icon"), val => \ ($u->{icon} ||= 'default'), list => \@icons, icon2f => \&face2png,
902 alignment => 'right', format => \&translate },
903 ),
904 { label => N("Real name"), val => \$u->{realname}, alignment => 'right', focus_out => sub {
905 $u->{name} ||= lc(Locale::gettext::iconv($u->{realname}, "utf-8", "ascii//TRANSLIT"));
906 $u->{name} =~ s/[^a-zA-Z0-9_-]//g; # drop any charcter that would break login program
907 },
908 focus => sub { !$superuser },
909 },
910
911 { label => N("Login name"), val => \$u->{name}, list => \@suggested_names, alignment => 'right',
912 not_edit => 0, validate => $validate_name },
913 { label => N("Password"),val => \$u->{password}, hidden => 1, alignment => 'right', weakness_check => 1,
914 validate => sub { authentication::check_given_password($in, $u, $security > 3 ? 6 : 0) } },
915 { label => N("Password (again)"), val => \$u->{password2}, hidden => 1, alignment => 'right' },
916 { label => N("Shell"), val => \$u->{shell}, list => [ shells() ], advanced => 1 },
917 { label => N("User ID"), val => \$u->{uid}, advanced => 1, validate => sub { $validate_uid_gid->('uid') } },
918 { label => N("Group ID"), val => \$u->{gid}, advanced => 1, validate => sub { $validate_uid_gid->('gid') } },
919 if_($security > 3,
920 map {
921 { label => $_, val => \$groups{$_}, text => $high_security_groups{$_}, type => 'bool' };
922 } keys %high_security_groups,
923 ),
924 ],
925 );
926
927 if ($xguest && !is_xguest_installed()) {
928 $in->do_pkgs->ensure_is_installed('xguest', '/etc/security/namespace.d/xguest.conf');
929 } elsif (!$xguest && is_xguest_installed()) {
930 $in->do_pkgs->remove('xguest') or return;
931 }
932
933 $u->{groups} = [ grep { $groups{$_} } keys %groups ];
934
935 push @$users, $u if $u->{name};
936
937 $ret && $u;
938 }
939
940 sub sessions() {
941 split(' ', run_program::rooted_get_stdout($::prefix, '/usr/sbin/chksession', '-l'));
942 }
943 sub sessions_with_order() {
944 my %h = map { /(.*)=(.*)/ } split(' ', run_program::rooted_get_stdout($::prefix, '/usr/sbin/chksession', '-L'));
945 \%h;
946 }
947
948 sub urpmi_add_all_media {
949 my ($in, $o_previous_release) = @_;
950
951 my $binary = find { whereis_binary($_, $::prefix) } 'gurpmi.addmedia', 'urpmi.addmedia' or return;
952
953 #- configure urpmi media if network is up
954 require network::tools;
955 return if !network::tools::has_network_connection();
956 my $wait;
957 my @options = ('--distrib', '--mirrorlist', '$MIRRORLIST');
958 if ($binary eq 'urpmi.addmedia') {
959 $wait = $in->wait_message(N("Please wait"), N("Please wait, adding media..."));
960 } elsif ($in->isa('interactive::gtk')) {
961 push @options, '--silent-success';
962 mygtk2::flush();
963 }
964
965 my $reason = join(',', $o_previous_release ?
966 ('reason=upgrade', 'upgrade_by=drakx', "upgrade_from=$o_previous_release->{version}") :
967 'reason=install');
968 log::l("URPMI_ADDMEDIA_REASON $reason");
969 local $ENV{URPMI_ADDMEDIA_REASON} = $reason;
970
971 my $log_file = '/root/drakx/updates.log';
972 run_program::rooted($::prefix, $binary, '>>', $log_file, '2>>', $log_file, @options);
973 }
974
975 sub autologin {
976 my ($o, $in) = @_;
977
978 my @wm = sessions();
979 my @users = map { $_->{name} } @{$o->{users} || []};
980
981 my $kde_desktop = find { member($_, 'KDE', 'KDE4') } @wm;
982 if ($kde_desktop && @users == 1 && $o->{meta_class} eq 'desktop') {
983 $o->{desktop} = $kde_desktop;
984 $o->{autologin} = $users[0];
985 } elsif (@wm > 1 && @users && !$o->{authentication}{NIS} && $o->{security} <= 2) {
986 my $use_autologin = @users == 1;
987
988 $in->ask_from_(
989 { title => N("Autologin"),
990 messages => N("I can set up your computer to automatically log on one user.") },
991 [ { text => N("Use this feature"), val => \$use_autologin, type => 'bool' },
992 { label => N("Choose the default user:"), val => \$o->{autologin}, list => \@users, disabled => sub { !$use_autologin } },
993 { label => N("Choose the window manager to run:"), val => \$o->{desktop}, list => \@wm, disabled => sub { !$use_autologin } } ]
994 );
995 delete $o->{autologin} if !$use_autologin;
996 } else {
997 delete $o->{autologin};
998 }
999 }
1000
1001 sub display_release_notes {
1002 my ($in, $release_notes) = @_;
1003 if (!$in->isa('interactive::gtk')) {
1004 $in->ask_from_({ title => N("Release Notes"),
1005 messages => $release_notes, #formatAlaTeX(messages::main_license()),
1006 }, [ {} ]);
1007 return;
1008 }
1009
1010 # workaround too small fonts:
1011 $release_notes =~ s!(<head>)!$1 <style type="text/css">
1012 body { font-family: sans-serif; font-size: 13px }
1013 table { font-family: sans-serif; font-size: 13px }
1014 </style>!x;
1015
1016 require Gtk2::WebKit;
1017 require ugtk2;
1018 ugtk2->import(':all');
1019 require mygtk2;
1020 mygtk2->import('gtknew');
1021 my $view = gtknew('WebKit_View', no_popup_menu => 1);
1022 $view->load_html_string($release_notes, '/');
1023
1024 my $w = ugtk2->new(N("Release Notes"), transient => $::main_window, modal => 1, pop_it => 1);
1025 gtkadd($w->{rwindow},
1026 gtkpack_(Gtk2::VBox->new,
1027 1, create_scrolled_window(ugtk2::gtkset_border_width($view, 5),
1028 [ 'never', 'automatic' ],
1029 ),
1030 0, gtkpack(create_hbox('end'),
1031 gtknew('Button', text => N("Close"),
1032 clicked => sub { Gtk2->main_quit })
1033 ),
1034 ),
1035 );
1036 mygtk2::set_main_window_size($w->{rwindow});
1037 $w->{real_window}->grab_focus;
1038 $w->{real_window}->show_all;
1039 $w->main;
1040 return;
1041 }
1042
1043 sub get_release_notes {
1044 my ($in) = @_;
1045 my $ext = $in->isa('interactive::gtk') ? '.html' : '.txt';
1046 my $separator = $in->isa('interactive::gtk') ? "\n\n" : '';
1047
1048 my $release_notes = join($separator, grep { $_ } map {
1049 if ($::isInstall) {
1050 my $f = install::any::getFile_($::o->{stage2_phys_medium}, $_);
1051 $f && cat__($f);
1052 } else {
1053 my $file = $_;
1054 my $d = find { -e "$_/$file" } glob_("/usr/share/doc/*-release-*");
1055 $d && cat_("$d/$file");
1056 }
1057 } "release-notes$ext", 'release-notes.' . arch() . $ext);
1058
1059 # we do not handle links:
1060 $release_notes =~ s!<a href=".*?">(.*?)</a>!$1!g;
1061 $release_notes;
1062 }
1063
1064 sub run_display_release_notes {
1065 my ($release_notes) = @_;
1066 output('/tmp/release_notes.html', $release_notes);
1067 run_program::raw({ detach => 1 }, '/usr/bin/display_release_notes.pl');
1068 }
1069
1070 sub acceptLicense {
1071 my ($in) = @_;
1072 require messages;
1073
1074 my $release_notes = get_release_notes($in);
1075
1076 my $r = $::testing ? 'Accept' : 'Refuse';
1077
1078 $in->ask_from_({ title => N("License agreement"),
1079 focus_first => 1,
1080 cancel => N("Quit"),
1081 messages => formatAlaTeX(messages::main_license() . "\n\n\n" . messages::warning_about_patents()),
1082 interactive_help_id => 'acceptLicense',
1083 callbacks => { ok_disabled => sub { $r eq 'Refuse' } },
1084 },
1085
1086 [
1087 { label => N("Do you accept this license ?"), title => 1, alignment => 'right' },
1088 { list => [ N_("Accept"), N_("Refuse") ], val => \$r, type => 'list', alignment => 'right',
1089 format => sub { translate($_[0]) } },
1090 if_($release_notes,
1091 { clicked => sub { run_display_release_notes($release_notes) }, do_not_expand => 1,
1092 val => \ (my $_t1 = N("Release Notes")), install_button => 1, no_indent => 1 }
1093 ),
1094 ])
1095 or reboot();
1096 }
1097
1098 sub reboot() {
1099 if ($::isInstall) {
1100 my $o = $::o;
1101 install::media::umount_phys_medium($o->{stage2_phys_medium});
1102 install::media::openCdromTray($o->{stage2_phys_medium}{device}) if !detect_devices::is_xbox() && $o->{method} eq 'cdrom';
1103 $o->exit;
1104 } else {
1105 # when refusing license in finish-install:
1106 exec("/sbin/reboot");
1107 }
1108 }
1109
1110 sub selectLanguage_install {
1111 my ($in, $locale) = @_;
1112
1113 my $common = {
1114 title => N("Please choose a language to use"),
1115 interactive_help_id => 'selectLanguage' };
1116
1117 my $lang = $locale->{lang};
1118 my $langs = $locale->{langs} ||= {};
1119 my $using_images = $in->isa('interactive::gtk') && !$::o->{vga16};
1120
1121 my %name2l = map { lang::l2name($_) => $_ } lang::list_langs();
1122 my $listval2val = sub { $_[0] =~ /\|(.*)/ ? $1 : $_[0] };
1123
1124 #- since gtk version will use images (function image2f) we need to sort differently
1125 my $sort_func = $using_images ? \&lang::l2transliterated : \&lang::l2name;
1126 my @langs = sort { $sort_func->($a) cmp $sort_func->($b) } lang::list_langs();
1127
1128 if (@langs > 15) {
1129 my $add_location = sub {
1130 my ($l) = @_;
1131 map { "$_|$l" } lang::l2location($l);
1132 };
1133 @langs = map { $add_location->($_) } @langs;
1134
1135 #- to create the default value, use the first location for that value :/
1136 $lang = first($add_location->($lang));
1137 }
1138
1139 my $non_utf8 = 0;
1140 add2hash($common, { cancel => '',
1141 focus_first => 1,
1142 advanced_messages => formatAlaTeX(N("%s can support multiple languages. Select
1143 the languages you would like to install. They will be available
1144 when your installation is complete and you restart your system.", N("Mageia"))),
1145 advanced_label => N("Multiple languages"),
1146 });
1147
1148 $in->ask_from_($common, [
1149 { val => \$lang, separator => '|',
1150 if_($using_images, image2f => sub { $name2l{$_[0]} =~ /^[a-z]/ && "langs/lang-$name2l{$_[0]}" }),
1151 format => sub { $_[0] =~ /(.*\|)(.*)/ ? $1 . lang::l2name($2) : lang::l2name($_[0]) },
1152 list => \@langs, sort => !$in->isa('interactive::gtk'),
1153 focus_out => sub { $langs->{$listval2val->($lang)} = 1 } },
1154 { val => \$non_utf8, type => 'bool', text => N("Old compatibility (non UTF-8) encoding"), advanced => 1 },
1155 { val => \$langs->{all}, type => 'bool', text => N("All languages"), advanced => 1 },
1156 map {
1157 { val => \$langs->{$_->[0]}, type => 'bool', disabled => sub { $langs->{all} },
1158 text => $_->[1], advanced => 1,
1159 image => "langs/lang-$_->[0]",
1160 };
1161 } sort { $a->[1] cmp $b->[1] } map { [ $_, $sort_func->($_) ] } lang::list_langs(),
1162 ]) or return;
1163 $locale->{utf8} = !$non_utf8;
1164 %$langs = grep_each { $::b } %$langs; #- clean hash
1165 $langs->{$listval2val->($lang)} = 1;
1166
1167 #- convert to the default locale for asked language
1168 $locale->{lang} = $listval2val->($lang);
1169 lang::lang_changed($locale);
1170 }
1171
1172 sub selectLanguage_standalone {
1173 my ($in, $locale) = @_;
1174
1175 my $old_lang = $locale->{lang};
1176 my $common = { messages => N("Please choose a language to use"),
1177 title => N("Language choice"),
1178 interactive_help_id => 'selectLanguage' };
1179
1180 my @langs = sort { lang::l2name($a) cmp lang::l2name($b) } lang::list_langs(exclude_non_installed => 1);
1181 my $non_utf8 = !$locale->{utf8};
1182 $in->ask_from_($common, [
1183 { val => \$locale->{lang}, type => 'list',
1184 format => sub { lang::l2name($_[0]) }, list => \@langs, allow_empty_list => 1 },
1185 { val => \$non_utf8, type => 'bool', text => N("Old compatibility (non UTF-8) encoding"), advanced => 1 },
1186 ]);
1187 $locale->{utf8} = !$non_utf8;
1188 lang::set($locale);
1189 Gtk2->set_locale if $in->isa('interactive::gtk');
1190 lang::lang_changed($locale) if $old_lang ne $locale->{lang};
1191 }
1192
1193 sub selectLanguage_and_more_standalone {
1194 my ($in, $locale) = @_;
1195 eval {
1196 local $::isWizard = 1;
1197 language:
1198 # keep around previous settings so that selectLanguage can keep UTF-8 flag:
1199 local $::Wizard_no_previous = 1;
1200 selectLanguage_standalone($in, $locale);
1201 undef $::Wizard_no_previous;
1202 selectCountry($in, $locale) or goto language;
1203 };
1204 if ($@) {
1205 if ($@ !~ /wizcancel/) {
1206 die;
1207 } else {
1208 $in->exit(0);
1209 }
1210 }
1211 }
1212
1213 sub selectCountry {
1214 my ($in, $locale) = @_;
1215
1216 my $country = $locale->{country};
1217 my $country2locales = lang::countries_to_locales(exclude_non_installed => !$::isInstall);
1218 my @countries = keys %$country2locales;
1219 my @best = grep {
1220 find {
1221 $_->{main} eq lang::locale_to_main_locale($locale->{lang});
1222 } @{$country2locales->{$_}};
1223 } @countries;
1224 @best == 1 and @best = ();
1225
1226 my $other = !member($country, @best);
1227 my $ext_country = $country;
1228 $other and @best = ();
1229
1230 $in->ask_from_(
1231 { title => N("Country / Region"),
1232 messages => N("Please choose your country"),
1233 interactive_help_id => 'misc-params.html#drakxid-selectCountry',
1234 if_(@best, advanced_messages => N("Here is the full list of available countries")),
1235 advanced_label => @best ? N("Other Countries") : N("Advanced"),
1236 },
1237 [ if_(@best, { val => \$country, type => 'list', format => \&lang::c2name,
1238 list => \@best, sort => 1, changed => sub { $other = 0 } }),
1239 { val => \$ext_country, type => 'list', format => \&lang::c2name,
1240 list => [ @countries ], advanced => scalar(@best), changed => sub { $other = 1 } },
1241 { val => \$locale->{IM}, type => 'combo', label => N("Input method:"),
1242 sort => 0, separator => '|',
1243 list => [ '', lang::get_ims($locale->{lang}) ],
1244 format => sub { $_[0] ? uc($_[0] =~ /(.*)\+(.*)/ ? "$1|$1+$2" : $_[0]) : N("None") },
1245 advanced => !$locale->{IM},
1246 },
1247 ]) or return;
1248
1249 $locale->{country} = $other || !@best ? $ext_country : $country;
1250 }
1251
1252 sub set_login_serial_console {
1253 my ($port, $speed) = @_;
1254
1255 my $line = "s$port:12345:respawn:/sbin/agetty ttyS$port $speed ansi\n";
1256 substInFile { s/^s$port:.*//; $_ = $line if eof } "$::prefix/etc/inittab";
1257 }
1258
1259 sub report_bug {
1260 my (@other) = @_;
1261
1262 sub header { "
1263 ********************************************************************************
1264 * $_[0]
1265 ********************************************************************************";
1266 }
1267
1268 join '', map { chomp; "$_\n" }
1269 header("lspci"), detect_devices::stringlist(),
1270 header("pci_devices"), cat_("/proc/bus/pci/devices"),
1271 header("dmidecode"), arch() =~ /86/ ? `dmidecode` : (),
1272 header("fdisk"), arch() =~ /ppc/ ? `pdisk -l` : `fdisk -l`,
1273 header("scsi"), cat_("/proc/scsi/scsi"),
1274 header("/sys/bus/scsi/devices"), -d '/sys/bus/scsi/devices' ? `ls -l /sys/bus/scsi/devices` : (),
1275 header("lsmod"), cat_("/proc/modules"),
1276 header("cmdline"), cat_("/proc/cmdline"),
1277 header("pcmcia: stab"), cat_("$::prefix/var/lib/pcmcia/stab") || cat_("$::prefix/var/run/stab"),
1278 header("usb"), cat_("/proc/bus/usb/devices"),
1279 header("partitions"), cat_("/proc/partitions"),
1280 header("cpuinfo"), cat_("/proc/cpuinfo"),
1281 header("syslog"), cat_("/tmp/syslog") || cat_("$::prefix/var/log/syslog"),
1282 header("Xorg.log"), cat_("/var/log/Xorg.0.log"),
1283 header("monitor_full_edid"), monitor_full_edid(),
1284 header("stage1.log"), cat_("/tmp/stage1.log") || cat_("$::prefix/root/drakx/stage1.log"),
1285 header("ddebug.log"), cat_("/tmp/ddebug.log") || cat_("$::prefix/root/drakx/ddebug.log"),
1286 header("install.log"), cat_("$::prefix/root/drakx/install.log"),
1287 header("fstab"), cat_("$::prefix/etc/fstab"),
1288 header("modprobe.conf"), cat_("$::prefix/etc/modprobe.conf"),
1289 header("lilo.conf"), cat_("$::prefix/etc/lilo.conf"),
1290 header("grub: menu.lst"), join('', map { s/^(\s*password)\s+(.*)/$1 xxx/; $_ } cat_("$::prefix/boot/grub/menu.lst")),
1291 header("grub: install.sh"), cat_("$::prefix/boot/grub/install.sh"),
1292 header("grub: device.map"), cat_("$::prefix/boot/grub/device.map"),
1293 header("xorg.conf"), cat_("$::prefix/etc/X11/xorg.conf"),
1294 header("urpmi.cfg"), cat_("$::prefix/etc/urpmi/urpmi.cfg"),
1295 header("modprobe.preload"), cat_("$::prefix/etc/modprobe.preload"),
1296 header("sysconfig/i18n"), cat_("$::prefix/etc/sysconfig/i18n"),
1297 header("/proc/iomem"), cat_("/proc/iomem"),
1298 header("/proc/ioport"), cat_("/proc/ioports"),
1299 map_index { even($::i) ? header($_) : $_ } @other;
1300 }
1301
1302 sub fix_broken_alternatives {
1303 my ($force_default) = @_;
1304 #- fix bad update-alternatives that may occurs after upgrade (and sometimes for install too).
1305 -d "$::prefix/etc/alternatives" or return;
1306
1307 foreach (all("$::prefix/etc/alternatives")) {
1308 if ($force_default) {
1309 log::l("setting alternative $_");
1310 } else {
1311 next if run_program::rooted($::prefix, 'test', '-e', "/etc/alternatives/$_");
1312 log::l("fixing broken alternative $_");
1313 }
1314 run_program::rooted($::prefix, 'update-alternatives', '--auto', $_);
1315 }
1316 }
1317
1318
1319 sub fileshare_config {
1320 my ($in, $type) = @_; #- $type is 'nfs', 'smb' or ''
1321
1322 my $file = '/etc/security/fileshare.conf';
1323 my %conf = getVarsFromSh($file);
1324
1325 my @l = (N_("No sharing"), N_("Allow all users"), N_("Custom"));
1326 my $restrict = exists $conf{RESTRICT} ? text2bool($conf{RESTRICT}) : 1;
1327
1328 my $r = $in->ask_from_list_('fileshare',
1329 N("Would you like to allow users to share some of their directories?
1330 Allowing this will permit users to simply click on \"Share\" in konqueror and nautilus.
1331
1332 \"Custom\" permit a per-user granularity.
1333 "),
1334 \@l, $l[$restrict ? (getgrnam('fileshare') ? 2 : 0) : 1]) or return;
1335 $restrict = $r ne $l[1];
1336 my $custom = $r eq $l[2];
1337 if ($r ne $l[0]) {
1338 require services;
1339 my %types = (
1340 nfs => [ 'nfs-utils', 'nfs-server',
1341 N("NFS: the traditional Unix file sharing system, with less support on Mac and Windows.")
1342 ],
1343 smb => [ 'samba-server', 'smb',
1344 N("SMB: a file sharing system used by Windows, Mac OS X and many modern Linux systems.")
1345 ],
1346 );
1347 my %l;
1348 if ($type) {
1349 %l = ($type => 1);
1350 } else {
1351 %l = map_each { $::a => services::starts_on_boot($::b->[1]) } %types;
1352 $in->ask_from_({ messages => N("You can export using NFS or SMB. Please select which you would like to use."),
1353 callbacks => { ok_disabled => sub { !any { $_ } values %l } },
1354 },
1355 [ map { { text => $types{$_}[2], val => \$l{$_}, type => 'bool' } } keys %l ]) or return;
1356 }
1357 foreach (keys %types) {
1358 my ($pkg, $service, $_descr) = @{$types{$_}};
1359 my $file = "/etc/init.d/$service";
1360 if ($l{$_}) {
1361 $in->do_pkgs->ensure_is_installed($pkg, $file) or return;
1362 services::start($service);
1363 services::start_service_on_boot($service);
1364 } elsif (-e $file) {
1365 services::stop($service);
1366 services::do_not_start_service_on_boot($service);
1367 }
1368 }
1369 if ($in->do_pkgs->is_installed('nautilus')) {
1370 $in->do_pkgs->ensure_is_installed('nautilus-filesharing') or return;
1371 }
1372 }
1373 $conf{RESTRICT} = bool2yesno($restrict);
1374 setVarsInSh($file, \%conf);
1375
1376 if ($custom) {
1377 run_program::rooted($::prefix, 'groupadd', '-r', 'fileshare');
1378 if ($in->ask_from_no_check(
1379 {
1380 -e '/usr/sbin/userdrake' ? (ok => N("Launch userdrake"), cancel => N("Close")) : (cancel => ''),
1381 messages =>
1382 N("The per-user sharing uses the group \"fileshare\".
1383 You can use userdrake to add a user to this group.")
1384 }, [])) {
1385 run_program::run('userdrake');
1386 }
1387 }
1388 }
1389
1390 sub monitor_full_edid() {
1391 return if $::noauto;
1392
1393 devices::make('zero');
1394 my ($vbe, $edid);
1395 {
1396 # prevent warnings in install's logs:
1397 local $ENV{LC_ALL} = 'C';
1398 run_program::raw({ timeout => 20 },
1399 'monitor-edid', '>', \$edid, '2>', \$vbe,
1400 '-v', '--perl', if_($::isStandalone, '--try-in-console'));
1401 }
1402 if ($::isInstall) {
1403 foreach (['edid', \$edid], ['vbe', \$vbe]) {
1404 my ($name, $val) = @$_;
1405 if (-e "/tmp/$name") {
1406 my $old = cat_("/tmp/$name");
1407 if (length($$val) < length($old)) {
1408 log::l("new $name is worse, keeping the previous one");
1409 $$val = $old;
1410 } elsif (length($$val) > length($old)) {
1411 log::l("new $name is better, dropping the previous one");
1412 }
1413 }
1414 output("/tmp/$name", $$val);
1415 }
1416 }
1417 ($edid, $vbe);
1418 }
1419
1420 # FIXME: is buggy regarding multiple sessions
1421 sub running_window_manager() {
1422 my @window_managers = qw(ksmserver kwin gnome-session icewm wmaker afterstep fvwm fvwm2 fvwm95 mwm twm enlightenment xfce4-session blackbox sawfish olvwm fluxbox compiz drakx-matchbox-window-manager lxsession);
1423
1424 foreach (@window_managers) {
1425 my @pids = fuzzy_pidofs(qr/\b$_\b/) or next;
1426 return wantarray() ? ($_, @pids) : $_;
1427 }
1428 undef;
1429 }
1430
1431 sub set_wm_hints_if_needed {
1432 my ($o_in) = @_;
1433 my $wm = any::running_window_manager();
1434 $o_in->{no_Window_Manager} = !$wm if $o_in;
1435 $::set_dialog_hint = $wm eq 'drakx-matchbox-window-manager';
1436 }
1437
1438 sub ask_window_manager_to_logout {
1439 my ($wm) = @_;
1440
1441 my %h = (
1442 'ksmserver' => '/usr/lib/qt4/bin/qdbus org.kde.ksmserver /KSMServer logout 1 0 0',
1443 'kwin' => "dcop kdesktop default logout",
1444 'gnome-session' => "gnome-session-save --kill",
1445 'icewm' => "killall -QUIT icewm",
1446 'xfce4-session' => "xfce4-session-logout --logout",
1447 'lxsession' => "lxde-logout",
1448 );
1449 my $cmd = $h{$wm} or return;
1450 if (member($wm, 'ksmserver', 'kwin', 'gnome-session') && $> == 0) {
1451 #- we cannot use dcop when we are root
1452 if (my $user = $ENV{USERHELPER_UID} && getpwuid($ENV{USERHELPER_UID})) {
1453 $cmd = "su $user -c '$cmd'";
1454 } else {
1455 log::l('missing or unknown $USERHELPER_UID');
1456 }
1457 }
1458 system($cmd);
1459 1;
1460 }
1461
1462 sub ask_window_manager_to_logout_then_do {
1463 my ($wm, $pid, $action) = @_;
1464 if (fork()) {
1465 ask_window_manager_to_logout($wm);
1466 return;
1467 }
1468
1469 open STDIN, "</dev/zero";
1470 open STDOUT, ">/dev/null";
1471 open STDERR, ">&STDERR";
1472 c::setsid();
1473 exec 'perl', '-e', q(
1474 my ($wm, $pid, $action) = @ARGV;
1475 my $nb;
1476 for ($nb = 30; $nb && -e "/proc/$pid"; $nb--) { sleep 1 }
1477 system($action) if $nb;
1478 ), $wm, $pid, $action;
1479 }
1480
1481 sub ask_for_X_restart {
1482 my ($in) = @_;
1483
1484 $::isStandalone && $in->isa('interactive::gtk') or return;
1485
1486 my ($wm, $pid) = running_window_manager();
1487
1488 if (!$wm) {
1489 # no window manager, ctrl-alt-del may not be supported, but we still have to restart X..
1490 $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;
1491 system('killall', 'Xorg');
1492 }
1493 else {
1494 $in->ask_okcancel('', N("You need to log out and back in again for changes to take effect"), 1) or return;
1495 ask_window_manager_to_logout_then_do($wm, $pid, 'killall Xorg');
1496 }
1497 }
1498
1499 sub alloc_raw_device {
1500 my ($prefix, $device) = @_;
1501 my $used = 0;
1502 my $raw_dev;
1503 substInFile {
1504 $used = max($used, $1) if m|^\s*/dev/raw/raw(\d+)|;
1505 if (eof) {
1506 $raw_dev = "raw/raw" . ($used + 1);
1507 $_ .= "/dev/$raw_dev /dev/$device\n";
1508 }
1509 } "$prefix/etc/sysconfig/rawdevices";
1510 $raw_dev;
1511 }
1512
1513 sub config_mtools {
1514 my ($prefix) = @_;
1515 my $file = "$prefix/etc/mtools.conf";
1516 -e $file or return;
1517
1518 my ($f1, $f2) = detect_devices::floppies_dev();
1519 substInFile {
1520 s|drive a: file="(.*?)"|drive a: file="/dev/$f1"|;
1521 s|drive b: file="(.*?)"|drive b: file="/dev/$f2"| if $f2;
1522 } $file;
1523 }
1524
1525 sub configure_timezone {
1526 my ($in, $timezone, $ask_gmt, $o_hide_ntp) = @_;
1527
1528 require timezone;
1529 my $selected_timezone = $in->ask_from_treelist(N("Timezone"), N("Which is your timezone?"), '/', [ timezone::getTimeZones() ], $timezone->{timezone}) or return;
1530 $timezone->{timezone} = $selected_timezone;
1531
1532 configure_time_more($in, $timezone, $o_hide_ntp)
1533 or goto &configure_timezone if $ask_gmt || to_bool($timezone->{ntp});
1534
1535 1;
1536 }
1537
1538 sub configure_time_more {
1539 my ($in, $timezone, $o_hide_ntp) = @_;
1540
1541 my $ntp = to_bool($timezone->{ntp});
1542 my $servers = timezone::ntp_servers();
1543 $timezone->{ntp} ||= 'pool.ntp.org';
1544
1545 require POSIX;
1546 use POSIX qw(strftime);
1547 my $time_format = "%H:%M:%S";
1548 my $tz_prefix = timezone::get_timezone_prefix();
1549 local $ENV{TZ} = ':' . $tz_prefix . '/' . $timezone->{timezone};
1550
1551 $in->ask_from_({ interactive_help_id => 'misc-params#drakxid-configureTimezoneGMT',
1552 title => N("Date, Clock & Time Zone Settings"),
1553 }, [
1554 { label => N("Date, Clock & Time Zone Settings"), title => 1 },
1555 { label => N("What is the best time?") },
1556 { val => \$timezone->{UTC},
1557 type => 'list', list => [ 0, 1 ], format => sub {
1558 $_[0] ?
1559 N("%s (hardware clock set to UTC)", POSIX::strftime($time_format, localtime())) :
1560 N("%s (hardware clock set to local time)", POSIX::strftime($time_format, gmtime()));
1561 } },
1562 { label => N("NTP Server"), title => 1, advanced => $o_hide_ntp },
1563 { text => N("Automatic time synchronization (using NTP)"), val => \$ntp, type => 'bool',
1564 advanced => $o_hide_ntp },
1565 { val => \$timezone->{ntp}, disabled => sub { !$ntp }, advanced => $o_hide_ntp,
1566 type => "list", separator => '|',
1567 list => [ keys %$servers ], format => sub { $servers->{$_[0]} } },
1568 ]) or return;
1569
1570 $timezone->{ntp} = '' if !$ntp;
1571
1572 1;
1573 }
1574
1575 sub disable_x_screensaver() {
1576 run_program::run("xset", "s", "off");
1577 run_program::run("xset", "-dpms");
1578 }
1579
1580 sub enable_x_screensaver() {
1581 run_program::run("xset", "+dpms");
1582 run_program::run("xset", "s", "on");
1583 run_program::run("xset", "s", "reset");
1584 }
1585
1586 1;

  ViewVC Help
Powered by ViewVC 1.1.30