3 # This program checks the whole Wine environment configuration.
4 # (or that's at least what it's supposed to do once it's finished)
5 # Copyright (C) 2001 Andreas Mohr
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 # - implement cmdline arguments e.g. for confirmation keypress
23 # in case of a problem
26 # - implement it in a much more systematic way. This is a quick hack for now
27 # (like every Perl program ;-)
28 # And much more so since I'm NOT a Perl hacker
29 # - test/tweak on non-Linux systems
39 my $count_suspect = 0;
41 my $count_critical = 0;
44 my $is_notchecked = 0;
51 my $factor_suspect = 0.995;
52 my $factor_bad = 0.95;
53 my $factor_critical = 0.85;
54 my $factor_failed = 0.15;
56 my $correctness = 100.0;
60 my ($level, $reason, $advice);
62 my $advice_chmod = "If your user account is supposed to be able to access
63 it properly, use chmod as root to fix it (\"man chmod\")";
64 my $advice_fs = "The Filesystem option indicates the filesystem behaviour Wine is supposed to *emulate*, not the filesystem which is there";
70 select(STDERR); $| = 1; # make unbuffered
71 select(STDOUT); $| = 1; # make unbuffered
73 #--------------------------------- main program --------------------------------
79 &Check_WindowsFiles();
82 #------------------------------- support functions -----------------------------
85 my $len = length($str);
86 my $num = int((80 - $len - 2)/2);
90 for ($i = 0; $i < $num; $i++) {
94 for ($i = 0; $i < $num; $i++) {
110 $test_no = sprintf("%03d", $count_tests);
111 for (my $i = 0; $i < $indent; $i++)
113 $indent_str = $indent_str." ";
115 print sprintf("%.60s", $test_no.".".$indent_str." Checking ".$text."... ");
119 my($level, $str, $advice, $skip_score) = @_;
123 if ($level == $is_notchecked)
125 $err = "NOT CHECKED";
129 elsif ($level == $is_ok)
136 elsif ($level == $is_suspect)
142 $correctness *= $factor_suspect;
145 elsif ($level == $is_bad)
151 $correctness *= $factor_bad;
154 elsif ($level == $is_critical)
160 $correctness *= $factor_critical;
163 elsif ($level == $is_failed)
169 $correctness *= $factor_failed;
180 print " Press Enter.";
189 print "- ADVICE: ".$advice.".\n";
193 #-------------------------------- main functions ------------------------------
195 print "This script verifies the configuration of the whole Wine environment.\n";
196 print "Note that this is an ALPHA version, and thus it doesn't catch all problems !\n";
197 print "The results of the checks are printed on the right side:\n";
198 print "OK - test passed without problems.\n";
199 print "SUSPICIOUS - potentially problematic. You might want to look into that.\n";
200 print "BAD - This is a problem, and it leads to configuration score penalty.\n";
201 print "CRITICAL - A critical problem which can easily lead to malfunction.\n";
202 print "FAILED - This problem leads to Wine failure almost certainly.\n";
203 print "\nThe result will be printed as a percentage score indicating config completeness.\n";
208 print "Press Enter to continue or Ctrl-C to exit.";
213 sub Check_BaseFiles {
216 Do_PrintHeader("checking Wine base files");
219 Do_Check("for file \"wine\"");
220 $line = `which wine`;
224 $reason = "file not found";
225 $advice = "Make sure the \"wine\" command is in your PATH (echo \$PATH; export PATH=xxx)";
227 Do_PrintResult($level, $reason, $advice);
229 # check for config mess
232 Do_Check("for correct .so lib config (please wait)");
234 # Build list of library directories.
235 # First parse ld.so.conf to find system-wide lib directories.
237 open (LDCONF, "</etc/ld.so.conf");
239 s/\#.*//; # eliminate comments
241 if (-d $_) { push @dirlist, $_; }
244 # Next parse LD_LIBRARY_PATH to find user-specific lib dirs.
245 my (@ld_dirs) = split (/:/, $ENV{'LD_LIBRARY_PATH'});
247 foreach $dir (@ld_dirs) {
248 if (-d $dir) { push @dirlist, $dir; }
251 # Now check for a libwine.so in each directory
252 foreach $dir (@dirlist) {
253 my ($target) = $dir . "/libwine.so";
254 if (-f $target) { push @output, $target; }
256 print "DEBUG: found libwine: @output\n";
260 $level = $is_suspect;
262 foreach $line (@output) {
264 $dirs = $dirs." ".$line;
266 $reason = "libwine.so found ".@output." times:".$dirs;
267 $advice = "check whether this is really ok";
269 Do_PrintResult($level, $reason, $advice);
272 sub Do_Config_Drive {
273 my ($drive, $entries, $values) = @_;
284 my $my_advice_fat = "If that doesn't help, change mount options in case of VFAT (\"umask\" option)";
286 print "\n>>> Checking drive ".$drive." settings:\n";
288 while (@$entries[$index])
290 $arg = @$values[$index];
291 SWITCH: for (@$entries[$index]) {
292 /^path$/i && do { $path = $arg; last; };
293 /^type$/i && do { $type = $arg; last; };
294 /^label$/i && do { $label = $arg; last; };
295 /^serial$/i && do { $serial = $arg; last; };
296 /^device$/i && do { $device = $arg; last; };
297 /^filesystem$/i && do { $fs = $arg; last; };
298 $unknown = @$entries[$index];
305 my $serious = ($drive =~ /^C$/i) || ($type =~ /^cdrom$/i);
307 ##### check Path #####
308 Do_Check("Path option");
310 $advice = "The syntax of the Path option has to be something like /my/mount/point";
313 $level = $serious ? $is_failed : $is_bad;
314 $reason = "no Path option given in config file";
316 elsif ($path =~ /\\/)
318 $level = $serious ? $is_failed : $is_bad;
319 $reason = "wrong Path format ".$path;
321 elsif ($path =~ /\$\{(.*)\}$/)
323 # get path assigned to environment variable
324 my $envpath = $ENV{$1};
327 $level = $serious ? $is_failed : $is_critical;
328 $reason = "Path \"".$path."\" references environment variable \"".$1."\" which is undefined";
329 $advice = "set environment variable before starting Wine or give a \"real\" directory instead";
334 goto PERMCHECK; # hmpf
342 $level = $serious ? $is_failed : $is_suspect;
343 $reason = $path." does not exist !";
344 $advice = "create this directory or point Path to a real directory";
348 $level = $serious ? $is_failed : $is_bad;
349 $reason = $path." is not readable for you";
350 $advice = $advice_chmod.". ".$my_advice_fat;
352 elsif ((! ($type =~ /^cdrom$/i)) && (!-w $path))
354 $level = ($drive =~ /^C$/i) ? $is_failed : $is_suspect;
355 $reason = $path." is not writable for you";
356 $advice = $advice_chmod.". ".$my_advice_fat;
358 else # check permissions of the drive's directories
361 push (@output, `find $path 2>&1 1>/dev/null`);
362 foreach my $line (@output) {
363 if ($line =~ /find:\ (.*):\ Permission denied$/)
365 $level = ($drive =~ /^C$/i) ? $is_critical : $is_suspect;
366 $reason = "directory $1 is not accessible for you";
367 $advice = $advice_chmod.". ".$my_advice_fat;
373 Do_PrintResult($level, $reason, $advice);
375 ##### check Type #####
378 Do_Check("Type option");
380 SWITCH: for ($type) {
381 /^floppy$/i && do { last; };
382 /^hd$/i && do { last; };
383 /^network$/i && do { last; };
387 $level = $is_critical;
388 $reason = "no Device option found -> CD-ROM labels can''t be read";
389 $advice = "add Device option and make sure the device given is accessible by you";
393 /^ramdisk$/i && do { last; };
397 $reason = "invalid Type setting ".$type;
398 $advice = "use one of \"floppy\", \"hd\", \"network\" or \"cdrom\"";
401 Do_PrintResult($level, $reason, $advice);
404 ##### FIXME: check Label and Serial here #####
406 ##### check Device #####
409 my $mode = ($type =~ /^cdrom$/i) ? $dev_read : $dev_read|$dev_write;
410 &Do_CheckDevice("device", $device, 1, $mode);
413 ##### check Filesystem #####
416 Do_Check("Filesystem option");
419 /^(dos|fat|msdos|unix)$/i && do {
421 $reason = "You probably don't want to use \"".$fs."\". ".$advice_fs;
422 if ($fs =~ /^unix$/i)
424 $advice = "This should almost never be used";
428 $advice = "only use ".$fs." if you only have a crappy 8.3 filename (i.e.: non-LFN) DOS FAT kernel filesystem driver";
432 /^vfat$/i && do { last; };
433 /^win95$/i && do { last; };
437 $reason = "invalid Filesystem setting ".$type;
438 $advice = "use one of \"win95\", \"msdos\" or \"unix\"";
441 Do_PrintResult($level, $reason, $advice);
445 print "--> PROBLEM.\n";
457 my (@entries, @values);
458 LINE: while (<$file>)
461 next LINE if ($line =~ /[\ ]*[;#]/); # skip comments
463 #print "line: ".$line."\n";
464 if ($line =~ /\[(.*)\]/) # end of section/next section ?
466 my $nextsection = $1;
468 SWITCH: for ($section) {
469 /Drive\ (.)/i && do { &Do_Config_Drive($1, \@entries, \@values); last; };
475 $section = $found ? $nextsection : "";
476 @entries = (); @values = ();
479 if ($line =~ /^[\ \t]*\"(.*)\"[\ \t]*\=[\ \t]*\"(.*)\"/)
487 sub Check_ConfigFile {
488 my $config = "$ENV{'HOME'}/.wine/config";
491 Do_PrintHeader("checking config file");
493 Do_Check("config file access");
494 open(CFGFILE, $config);
498 $reason = $config." does not exist";
499 $advice = "it is ok in case you have ~/.winerc. If you don''t, then you''re in trouble !";
501 elsif (!-r $config) {
502 $reason = $config." not readable";
503 $advice = $advice_chmod;
505 Do_PrintResult($is_failed, $reason, $advice);
510 Do_PrintResult($is_failed, $config." not writable", "wineserver needs to be able to write to config file. ".$advice_chmod);
514 Do_PrintResult($is_ok);
516 Do_Config_Main(\*CFGFILE);
521 my($descr, $dev, $output, $mode) = @_;
527 $mode = $dev_read|$dev_write|$dev_open;
529 ($output != -1) && Do_Check($descr." ".$dev);
531 my $err_level = ($output == 1) ? $is_critical : $is_bad;
536 $reason = $dev." does not exist";
537 $advice = "use MAKEDEV script to create it";
540 if (($mode & $dev_read) && (!-r $dev))
543 $reason = $dev." is not readable for you";
544 $advice = $advice_chmod;
547 if (($mode & $dev_write) && (!-w $dev))
550 $reason = $dev." is not writable for you";
551 $advice = $advice_chmod;
554 if (($mode & $dev_open) && (!open(DEVICE, ">$dev")))
557 $reason = "no kernel driver for ".$dev."?";
558 $advice = "module loading problems ? Read /usr/src/linux/Documentation/modules.txt";
564 ($output != -1) && Do_PrintResult($level, $reason, $advice);
568 # FIXME: check joystick and scsi devices !
569 my $dev_sound = "/dev/dsp";
570 my $dev_mixer = "/dev/mixer";
571 my $dev_sequencer = "/dev/sequencer";
572 my $dev_mem = "/dev/mem";
574 Do_PrintHeader("checking system devices used by Wine");
575 &Do_CheckDevice("sound device", $dev_sound, 1);
576 &Do_CheckDevice("audio mixer device", $dev_mixer, 1);
577 &Do_CheckDevice("MIDI sequencer device", $dev_sequencer, 0);
582 my $regfile = $ENV{'HOME'}."/.wine/system.reg";
584 Do_PrintHeader("checking registry configuration");
586 Do_Check("availability of winedefault.reg entries");
587 push (@entries, `grep "SHAREDMEMLOCATION" $regfile`);
590 Do_PrintResult($is_ok);
594 Do_PrintResult($is_critical, "entry \"SHAREDMEMLOCATION\" not found in system.reg registry file", "file winedefault.reg doesn't seem to have been applied using regapi");
598 Do_Check("availability of windows registry entries");
599 # FIXME: use a different key for check if Wine adds this one to its
601 push (@entries, `grep "Default Taskbar" $regfile`);
604 Do_PrintResult($is_ok);
608 Do_PrintResult($is_critical, "entry \"Default Taskbar\" not found", "Windows registry does not seem to be added to Wine, as this typical Windows registry entry does not exist in Wine's registry. This can affect many newer programs. A complete original Windows registry entry set will *not* be available with a no-windows install, of course, so you'll have to live with that.");
613 sub Check_WindowsFiles {
617 # my ($score_total, $score_reached, $score_percent);
619 # $score_total = $count_tests * 20;
620 # $score_reached = $count_ok * 20 +
622 # $count_critical * 5 +
624 # $score_percent = $score_reached * 100 / $score_total;
627 print $count_tests." tests. ".$count_suspect." suspicious, ".$count_bad." bad, ".$count_critical." critical, ".$count_failed." failed.\n";
628 print sprintf "Wine configuration correctness score: %2.2f%%\n", $correctness;