/[soft]/drakx/trunk/perl-install/standalone/service_harddrake
ViewVC logotype

Contents of /drakx/trunk/perl-install/standalone/service_harddrake

Parent Directory Parent Directory | Revision Log Revision Log


Revision 917 - (show annotations) (download)
Sun Apr 17 14:33:49 2011 UTC (13 years ago) by anssi
File size: 15118 byte(s)
service_harddrake: Factorize ask_with_timeout for a following commit.
1 #!/usr/bin/perl
2
3 use lib qw(/usr/lib/libDrakX);
4
5 # prevent firing up drakbug (doesn't work w/o X11):
6 BEGIN { $ENV{DISABLE_DRAKBUG} = 1 }
7
8 use strict;
9 use diagnostics;
10
11 # fix translating reasons for 2nd stage warning
12 use lang;
13 BEGIN {
14 my $locale = lang::read($>);
15 lang::set($locale);
16 }
17
18 use standalone; #- warning, standalone must be loaded very first, for 'explanations'
19 use c;
20 use common;
21 use interactive;
22 use detect_devices;
23 use harddrake::data;
24 use harddrake::autoconf;
25 use harddrake::sound;
26 use Xconfig::card;
27 use modules;
28 use Storable qw(store retrieve);
29
30
31 my $force = member('--force', @ARGV);
32
33 my $invert_do_it = $ARGV[0] eq 'X11' ? 1 : 0;
34 my ($hw_sysconfdir, $timeout) = ("/etc/sysconfig/harddrake2", $invert_do_it ? 600 : 25);
35 my $last_boot_config = "$hw_sysconfdir/previous_hw";
36
37 $last_boot_config .= '_X11' if $invert_do_it;
38
39 # first run ? if not read old hw config
40 my $previous_config;
41 if (-f $last_boot_config && -s $last_boot_config) {
42 eval { $previous_config = Storable::retrieve($last_boot_config) };
43 log::explanations("resetting previous hardware file ($@)") if $@;
44 }
45 $previous_config ||= {};
46 $previous_config = $$previous_config if ref($previous_config) !~ /HASH/;
47 my $first_run = is_empty_hash_ref($previous_config);
48
49 my $modules_conf = modules::any_conf->read;
50
51 my $isLaptop = detect_devices::isLaptop();
52 my $curr_kernel = c::kernel_version();
53 my ($kernel_major) = $curr_kernel =~ /^(\d+\.\d+)/;
54
55 my %previous_kernel_config = getVarsFromSh("$hw_sysconfdir/kernel");
56 my %previous_xorg_config = getVarsFromSh("$hw_sysconfdir/xorg");
57 setVarsInSh("$hw_sysconfdir/kernel", { KERNEL => $kernel_major, IS_LAPTOP => bool2text($isLaptop) });
58 my %cfg = getVarsFromSh("$hw_sysconfdir/service.conf");
59
60 # default to 'yes' on upgrade:
61 $cfg{AUTORECONFIGURE_RIGHT_XORG_DRIVER} = 'yes' if !exists $cfg{AUTORECONFIGURE_RIGHT_XORG_DRIVER};
62
63 # autoreconfigure laptop-dependent services when switching from laptop to desktop, and vice versa
64 if (!exists $previous_kernel_config{IS_LAPTOP} || $force || $isLaptop != text2bool($previous_kernel_config{IS_LAPTOP})) {
65 log::explanations("Autoconfiguring laptop tools since we switched between laptop and desktop systems");
66 harddrake::autoconf::laptop($isLaptop);
67 }
68
69 my $known_kernels = "$hw_sysconfdir/kernels";
70 if (!member($curr_kernel, chomp_(cat_($known_kernels)))) {
71 harddrake::autoconf::fix_aliases($modules_conf) if !$first_run;
72 append_to_file($known_kernels, "$curr_kernel\n");
73 }
74
75 sub ask_with_timeout {
76 my ($title, $msg, $timeout, $plymouth) = @_;
77 my ($pid, $res, $timed_out);
78
79 $SIG{ALRM} = sub { $timed_out = 1; kill 15, $pid };
80 unless ($pid = fork()) {
81 $plymouth and system('plymouth', 'hide-splash');
82 exec("/usr/share/harddrake/confirm", $title, $msg);
83 }
84 alarm($timeout);
85 wait();
86 $res = $?;
87 alarm(0);
88 return $res, $timed_out;
89 }
90
91 sub get_xorg_driver() {
92 my $x = Xconfig::xfree->read;
93 if ($x) {
94 my ($dev_section) = grep { $_->{name} eq 'Device' } @{$x->{raw}};
95 $dev_section && $dev_section->{l}{Driver}{val};
96 }
97 }
98
99 sub schedule_warn_about_switch {
100 my ($reason) = @_;
101 output('/var/run/harddrake-notify-x11-free-driver-switch', $reason);
102 }
103
104 my $lib = arch() =~ /x86_64/ ? "lib64" : "lib";
105
106 sub find_xorg_driver {
107 my ($new_driver) = @_;
108 # nvidia driver has special place:
109 -e "/usr/$lib/xorg/modules/drivers/${new_driver}_drv.so"
110 || -e "/usr/$lib/xorg/extra-modules/${new_driver}_drv.so";
111 }
112
113 sub switch_x_driver {
114 my ($old_driver, $new_driver, $reason) = @_;
115 if (!find_xorg_driver($new_driver)) {
116 log::explanations("would switch X.org driver from '$old_driver' to '$new_driver' ($reason); but new driver is not installed");
117 return;
118 }
119 cp_af('/etc/X11/xorg.conf', "/etc/X11/xorg.conf.mga$^T");
120 substInFile { s!Driver "($old_driver)"!Driver "$new_driver"!g } '/etc/X11/xorg.conf';
121 log::explanations("switch X.org driver from '$old_driver' to '$new_driver' ($reason)");
122 Xconfig::card::libgl_config_and_more({ Driver => $new_driver });
123 }
124
125 sub should_reconfigure_x_driver {
126 my ($card_data, $device, $current_driver) = @_;
127 my $reason;
128 my $reconfigure;
129 my $new_key = $card_data->{Driver} . $card_data->{Driver2};
130 setVarsInSh("$hw_sysconfdir/xorg", { XORG_DRV => $new_key });
131 # auto reconfigure x11 only on first time default driver have changed:
132 if ($previous_xorg_config{XORG_DRV} ne $new_key) {
133 if (!member($current_driver, $card_data->{Driver}, $card_data->{Driver2}, 'fbdev', 'vesa')) {
134 $reason = N("The graphic card '%s' is no more supported by the '%s' driver",
135 $device->{description}, $current_driver);
136 $reconfigure = 1;
137 }
138 } elsif ((stat('/etc/X11/xorg.conf'))[9] < (stat('/etc/product.id'))[9]) {
139 # when switching to a new release (product.id is newer than xorg.conf),
140 # regenerate xorg.conf even if the driver used is vesa or fbdev, this
141 # way we handle switches like "no driver for the card in older releases
142 # but good driver in new release", see bug #53753
143 if (!member($current_driver, $card_data->{Driver}, $card_data->{Driver2})) {
144 $reason = N("New release, reconfiguring X for %s", $device->{description});
145 $reconfigure = 1;
146 }
147 }
148
149 ($reconfigure, $reason);
150 }
151
152 my @cards = (
153 {
154 ldetect_driver_regexp => 'Card:NVIDIA',
155 xorg_driver_regexp => 'nv.+',
156 module_names => [ qw(NVdriver nvidia.o nvidia.ko nvidia71xx.ko nvidia96xx.ko nvidia97xx.ko nvidia173.ko nvidia-current.ko) ]
157 },
158 {
159 ldetect_driver_regexp => 'Card:ATI Radeon',
160 xorg_driver_regexp => 'fglrx',
161 module_names => [ qw(fglrx.ko fglrx-hd2000.ko) ]
162 }
163 );
164
165
166 my @devices;
167 @devices = grep { $_->{driver} =~ /^Card:/ } detect_devices::probeall()
168 if -f '/etc/X11/xorg.conf';
169
170 # do not auto reconfigure if more than one graphic card:
171 $cfg{AUTORECONFIGURE_RIGHT_XORG_DRIVER} = 'no' if scalar(@devices) > 1;
172
173 foreach my $device (@devices) {
174 next if !text2bool($cfg{AUTORECONFIGURE_RIGHT_XORG_DRIVER});
175
176 my $id = $device->{driver} =~ /Card:(.*)/ && $1;
177 my $card_data = Xconfig::card::readCardsDB("/usr/share/ldetect-lst/Cards+")->{$id};
178 my $current_driver = get_xorg_driver();
179
180 # nvidia proprietary driver in ldetect-lst can be 'nvidia173', 'nvidia-current', ...
181 # but really is just 'nvidia' in xorg.conf:
182 $card_data->{Driver2} =~ s/(nvidia).*/$1/;
183
184 # auto reconfigure x11 only on first time default driver have changed:
185 my ($should_reconfigure, $reason) = should_reconfigure_x_driver($card_data, $device, $current_driver);
186 if ($should_reconfigure) {
187 switch_x_driver($current_driver, $card_data->{Driver}, $reason);
188 schedule_warn_about_switch($reason) if any { $current_driver =~ $_->{xorg_driver_regexp} } @cards;
189 # Update $current_driver with the new one
190 $current_driver = $card_data->{Driver};
191 }
192
193 # nv->nouveau or non_kms_nouveau->kms_nouveau can't have "Disable dri"!
194 if ($current_driver eq "nouveau") {
195 my $raw_x = Xconfig::xfree->read;
196 if ($raw_x) {
197 if (member("dri", $raw_x->get_disabled_modules)) {
198 $raw_x->remove_disable_module("dri");
199 $raw_x->write;
200 }
201 }
202 }
203 }
204
205
206 foreach my $card (@cards) {
207 my $device = find { $_->{driver} =~ /$card->{ldetect_driver_regexp}/ } @devices;
208 next if !$device;
209
210 if (find { -e join('', "/lib/modules/", c::kernel_version(), $_) }
211 map { ("/dkms/$_", "/dkms-binary/$_", "/kernel/$_") } map { "/drivers/$_" } map { ("extra/$_", "video/$_", "char/$_", "char/drm/$_") } map { $_, "$_.gz" } @{$card->{module_names}}) {
212
213 # do not automatically switch from nv to nvidia (in order to handle
214 # cases where nvidia module crashes the system):
215 #
216 # substInFile {
217 # log::explanations("switch XFree86 driver from nv to nvidia") if /Driver "nv"/;
218 # s!Driver "nv.*"!Driver "nvidia"!g;
219 # s!#*( Load.*glx)!\1!g;
220 # } $_ foreach "/etc/X11/XF86Config-4", "/etc/X11/XF86Config";
221 } else {
222 my @cards = Xconfig::card::probe();
223 my $driver = $cards[0]{Driver};
224 my $old_driver = cat_('/etc/X11/xorg.conf') =~ /Driver "($card->{xorg_driver_regexp})"/ && $1;
225 if ($old_driver) {
226 my $reason = N("The proprietary kernel driver was not found for '%s' X.org driver",
227 $old_driver);
228 switch_x_driver($card->{xorg_driver_regexp}, $driver, $reason);
229 schedule_warn_about_switch($reason);
230 }
231 }
232 }
233
234 my $is_globetrotter = -f '/usr/sbin/mdkmove';
235
236 my (%config, $wait);
237 my $in;
238 my $plymouth = -x '/bin/plymouth';
239
240 # For each hw, class, detect device, compare and offer to reconfigure if needed
241 foreach my $hw_class (@harddrake::data::tree) {
242 my ($Ident, $item, $configurator, $detector, $do_it) = @$hw_class{qw(class string configurator detector checked_on_boot)};
243 next if member($cfg{"DETECT_$Ident"}, qw(NO no));
244
245 $configurator ||= $hw_class->{configurator};
246
247 next unless $do_it ^ $invert_do_it;
248 # No detector ? (should never happen but who know ?)
249 ref($detector) eq 'CODE' or next;
250
251 my %ID = map {
252 my $i = $_;
253 my $id = defined $i->{device} ? $i->{device} : join(':', map { $i->{$_} } qw(vendor id subvendor subid));
254 $id => $i;
255 } eval { $detector->({}) };
256 $config{$Ident} = \%ID;
257 next if !$is_globetrotter && !$force && $first_run; # do not fsck on first run but if --force
258
259 my $oldconfig = $force ? {} : $previous_config->{$Ident};
260
261 my $msg;
262 my @was_removed = difference2([ keys %$oldconfig ], [ keys %ID ]);
263 if (@was_removed) {
264 $msg .= N("Some devices in the \"%s\" hardware class were removed:\n", $item) .
265 join('', map { N("- %s was removed\n", harddrake::data::custom_id($oldconfig->{$_}, $item)) } @was_removed) . "\n";
266 }
267 my @added = difference2([ keys %ID ], [ keys %$oldconfig ]);
268 $msg .= N("Some devices were added: %s\n", $item) if @added;
269 $msg .= N("- %s was added\n", harddrake::data::custom_id($ID{$_}, $item)) foreach @added;
270 log::explanations("removed $Ident: " . harddrake::data::custom_id($oldconfig->{$_}, $item)) foreach @was_removed;
271 log::explanations("added $Ident: " . harddrake::data::custom_id($ID{$_}, $item)) foreach @added;
272
273 if ($Ident eq 'FIREWIRE_CONTROLLER' && any { $_->{driver} eq 'ohci1394' } @ID{@added}) {
274 modules::load_and_configure($modules_conf, 'ohci1394');
275 $modules_conf->write;
276 }
277
278 @added || @was_removed or $cfg{"DETECT_$Ident"} ne 'force' and next;
279
280 next if $Ident eq 'MOUSE' && $kernel_major ne $previous_kernel_config{KERNEL} && $cfg{"DETECT_$Ident"} ne 'force';
281
282 my @configurator_pool = $configurator;
283
284 if ($Ident eq "AUDIO") {
285 # automatic sound slots configuration
286 rm_rf("/etc/asound.state") if -e "/etc/asound.state";
287 harddrake::sound::configure_sound_slots($modules_conf);
288 next;
289 } elsif ($Ident eq "ETHERNET") {
290 $modules_conf->remove_alias_regexp('^(wlan|eth)[0-9]*$');
291 modules::load_category($modules_conf, 'network/main|gigabit|usb|wireless|firewire|pcmcia');
292 require network::connection::ethernet;
293 network::connection::ethernet::configure_eth_aliases($modules_conf);
294 require network::rfswitch;
295 network::rfswitch::configure();
296 require network::shorewall;
297 network::shorewall::update_interfaces_list();
298 $modules_conf->write;
299 next;
300 } elsif (member($Ident, qw(ATA_STORAGE CARD_READER RAID_STORAGE SATA_STORAGE SCSI_CONTROLLER))) {
301 # set scsi_hostadapter in modprobe.conf:
302 modules::load_category($modules_conf, 'disk/' . {
303 ATA_STORAGE => 'ide',
304 SATA_STORAGE => 'sata',
305 SCSI_CONTROLLER => 'scsi',
306 RAID_STORAGE => 'hardware_raid',
307 CARD_READER => 'card_reader'
308 }->{$Ident});
309 $modules_conf->write;
310 next;
311 } elsif (member($Ident, qw(AGP DVB TV))) {
312 my @old_drivers = uniq(map { $_->{driver} } values %$oldconfig);
313 my @new_drivers = uniq(map { $_->{driver} } values %ID);
314 # load DVB & TV drivers (eg: for One), not for AGP (done by X):
315 modules::load_category($modules_conf, 'multimedia/' . lc($Ident)) if member($Ident, qw(DVB TV));
316 $modules_conf->remove_module(difference2(\@old_drivers, \@new_drivers));
317 # add agpgart and the like modules to modprobe.preload if needed:
318 $modules_conf->write;
319 foreach (difference2(\@new_drivers, \@old_drivers)) {
320 eval { modules::load($_) };
321 warn "warning: $@" if $@;
322 }
323 next;
324 } elsif ($Ident eq "BLUETOOTH") {
325 harddrake::autoconf::bluetooth(scalar keys %ID);
326 } elsif ($Ident eq "PCMCIA_CONTROLLER") {
327 harddrake::autoconf::pcmcia(keys %ID ? first(values(%ID))->{driver} : '');
328 } elsif ($Ident eq "USB_CONTROLLER") {
329 # nearly useless (only mkinitrd uses it):
330 modules::load_category($modules_conf, 'bus/usb');
331 $modules_conf->write;
332 } elsif ($Ident eq "VIDEO") {
333 # explicitely NOT read the existing config (eg: new profile with globetrotter)
334 harddrake::autoconf::xconf($modules_conf, {}, member($cfg{SETUP_FB}, qw(NO no)), $cfg{RESOLUTION_WANTED});
335 next;
336 } elsif ($Ident eq "MOUSE") {
337 harddrake::autoconf::mouse_conf($modules_conf);
338 next;
339 } elsif ($Ident eq "CPU") {
340 harddrake::autoconf::cpufreq();
341 } elsif ($Ident eq "FLOPPY") {
342 harddrake::autoconf::floppy();
343 }
344
345 next if $is_globetrotter && !$hw_class->{automatic};
346 next unless $configurator_pool[0];
347 if (ref($configurator) ne 'CODE' && !-x first(split /\s+/, $configurator_pool[0])) {
348 log::explanations(qw(skip $Ident configuration since "$configurator" is not executable));
349 next;
350 }
351 my ($no, $res);
352 $hw_class->{automatic} ||= ref($configurator) eq 'CODE';
353
354 if (!$hw_class->{automatic}) {
355 ($res, $no) = ask_with_timeout(N("Hardware changes in \"%s\" class (%s seconds to answer)", $Ident, $timeout),
356 $msg . N("Do you want to run the appropriate config tool?"), $timeout, $plymouth);
357 } else {
358 $res = 1;
359 }
360 if (ref($configurator) eq 'CODE') {
361 eval { $configurator->() };
362 log::explanations(qw(cannot run "$configurator": $@)) if $@;
363 } elsif (!$no && $res) {
364 foreach my $program (@configurator_pool) {
365 if (fork()) {
366 wait();
367 } else {
368 log::explanations(qq(run "$program"));
369 exec("$program 2>/dev/null") or do {
370 log::explanations(qq(cannot run "$program"));
371 require POSIX;
372 POSIX::_exit();
373 };
374 }
375 }
376 }
377 if (!$hw_class->{automatic}) {
378 require interactive;
379 undef $wait;
380 $in ||= interactive->vnew;
381 $wait = $in->wait_message(N("Please wait"), N("Hardware probing in progress"));
382 }
383
384 }
385
386 # output new hw config
387 log::explanations("created file $last_boot_config");
388 Storable::store(\%config, $last_boot_config);
389
390 $in->exit(0) if $in;

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.30