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; |