wineconf 15.2 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1
#!/usr/bin/perl -w
Alexandre Julliard's avatar
Alexandre Julliard committed
2 3

# This program generates wine.conf files on STDOUT.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
# Copyright (C) 1996 Stephen Simmons
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# NOTES:
#
Alexandre Julliard's avatar
Alexandre Julliard committed
22 23 24
# This program examines the contents of the DOS filesystems and
# attempts to generate a sensible wine.conf file.  This is output
# to STDOUT.
Andreas Mohr's avatar
Andreas Mohr committed
25
# It reads /etc/fstab to find mounting locations of the hard disk drives
Alexandre Julliard's avatar
Alexandre Julliard committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
# It uses the correct algorithm for ordering DOS drives, with the
# exception of the case of multiple drive controller types, where I don't
# know what DOS's algorithm is.
# It uses find to find all of the win.ini files on any DOS partition
# and sorts them by age to guess which is part of the active Windows
# installation.
# It reads the autoexec.bat file (if found) and records all variable
# settings.   There are some inaccuracies in its determination.
# First, while variables are interpolated properly, no control
# structures are supported so calls and execs to other batch files are
# ignored, and all variable settings take effect regardless of whether
# they would in DOS (i,e., both if and else clauses are read).
# This is used to determine the path and temp directories.  Duplicate
# path directories and path directories that don't exist are thrown
# out.
# On failing to find C:\AUTOEXEC.BAT, wineconf finds all executables
# in the windows directory and subdirectories, and generates an
# optimized path statement encompassing all the executables.
# Then it also looks for \TEMP and \TMP on all drives taking the first
# one it finds.
# wineconf doesn't support floppy drives, network drives, printers,
# and serial device configuration is hardcoded and not configured for
# the machine it runs on.  Similarly, spy parameters are hard coded.

50
# It would make sense to incorporate much of the heuristic code in
Alexandre Julliard's avatar
Alexandre Julliard committed
51 52 53 54 55 56 57 58 59
# this program into a library to be shared with a dosemu configuration
# program, because it seems that at least some of the same stuff will
# be wanted.  The program needs to be cleaned up still.  A better tmp
# search algorithm could be written.  A fast option is planned.  Less
# Linux-dependence is desired.  Should look for devices independent
# of /etc/fstab; then sanity checks on /etc/fstab can be performed.

use Getopt::Long;
use File::Basename;
60
use strict;
Alexandre Julliard's avatar
Alexandre Julliard committed
61 62
use Carp;

63
GetOptions('windir=s', 'sysdir=s', 'thorough', 'debug:s', 'inifile=s') || &Usage;
Alexandre Julliard's avatar
Alexandre Julliard committed
64

65 66
print "WINE REGISTRY Version 2\n";
print ";; All keys relative to \\\\Machine\\\\Software\\\\Wine\\\\Wine\\\\Config\n\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
67 68 69 70 71 72 73 74 75 76 77
&ReadFSTAB();
&FindWindowsDir();
&ReadAutoexecBat();
&StandardStuff();

sub Usage {
    print "Usage: $0 <options>\n";
#    print "-fstab <filename>    Location of alternate fstab file\n";
    print "-windir <filename>   Location of windows dir in DOS space\n";
    print "-thorough            Do careful analysis (default)\n";
    print "-sysdir <filename>   Location of systems dir in DOS space\n";
78
    print "-inifile <filename>  Path to the wine.ini file (by default './wine.ini')\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
79 80 81 82 83 84 85 86 87
#    print "-tmpdir <filename>   Location of tmp directory\n";
    print "Generates (to STDOUT) a wine configuration file based on\n";
    print "/etc/fstab and searching around in DOS directories\n";
    print "The options above can override certain values\n";
    print "This should be considered ALPHA code\n";
    exit(0);
}

sub ReadFSTAB {
88 89
    $::opt_f = $::opt_f ? $::opt_f : '/etc/fstab';
    open(FSTAB, $::opt_f) || die "Cannot read $::opt_f\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
90 91 92
    while(<FSTAB>) {
	next if /^\s*\#/;
	next if /^\s*$/;
93 94

	my ($device, $mntpoint, $type, @rest) = split(' ', $_);
Alexandre Julliard's avatar
Alexandre Julliard committed
95
	if ($device !~ m"^/dev/fd") {
96 97 98 99
	    if ($type eq "ntfs") {
		push(@::FatDrives, [$device, $mntpoint, 'win95']);
	    }
	    elsif ($type eq "msdos" || $type eq "vfat") {
100
		push(@::FatDrives, [$device, $mntpoint, $type]);
Alexandre Julliard's avatar
Alexandre Julliard committed
101
	    }
102
	    elsif ($type eq "iso9660" ||
103
		   ($mntpoint eq "/cdrom" && ! $type eq 'supermount') ||
104 105
		   ($device eq '/dev/cdrom' && $type eq 'auto') ) {
		push(@::CdromDrives, [$device, $mntpoint, 'win95']);
Alexandre Julliard's avatar
Alexandre Julliard committed
106
	    }
107
	    elsif ( ($mntpoint eq '/mnt/cdrom' || $mntpoint eq '/cdrom')
108 109 110
		  && $type eq 'supermount') {
		push(@::CdromDrives, [ '/dev/cdrom', $mntpoint, 'win95']);
	    }
Alexandre Julliard's avatar
Alexandre Julliard committed
111 112
	}
    }
113
    if (!@::FatDrives) {
Alexandre Julliard's avatar
Alexandre Julliard committed
114 115 116 117 118
	warn "ERROR ($0): Cannot find any MSDOS drives.\n";
	warn "This does not mean you cannot run Wine, but $0\n";
	warn "cannot help you (yet)\n";
	exit(1);
    }
119 120
    push(@::UnixDrives, ['', '/tmp', 'hd']);
    push(@::UnixDrives, ['', '${HOME}', 'network']);
121 122 123 124
    my $MagicDrive = 'C';
    @::FatDrives = sort byDriveOrder @::FatDrives;
    @::CdromDrives = sort byCdOrder @::CdromDrives;
    foreach my $FatDrive (@::FatDrives) {
Alexandre Julliard's avatar
Alexandre Julliard committed
125
	print "[Drive $MagicDrive]\n";
126
	my $MntPoint = $FatDrive->[1];
127
	my $FileSys = $FatDrive->[2];
128 129 130
	print "\"Path\" = \"$MntPoint\"\n";
	print "\"Type\" = \"hd\"\n";
	print "\"Filesystem\" = \"$FileSys\"\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
131 132 133
	print "\n";
	&RegisterDrive($MagicDrive, $FatDrive);
	if(!&IsMounted($FatDrive->[0])) {
134
	    warn "WARNING: DOS Drive $MagicDrive (" . $FatDrive->[0] .
Alexandre Julliard's avatar
Alexandre Julliard committed
135 136 137 138
		") is not mounted\n";
	}
	$MagicDrive++;
    }
139
    foreach my $CdromDrive (@::CdromDrives) {
Alexandre Julliard's avatar
Alexandre Julliard committed
140
	print "[Drive $MagicDrive]\n";
141
	my $Device = $CdromDrive->[0];
142
	my $MntPoint = $CdromDrive->[1];
143
	my $FileSys = $CdromDrive->[2];
144 145 146 147
	print "\"Path\" = \"$MntPoint\"\n";
	print "\"Type\" = \"cdrom\"\n";
	print "\"Device\" = \"$Device\"\n";
	print "\"Filesystem\" = \"$FileSys\"\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
148 149 150 151
	print "\n";
	&RegisterDrive($MagicDrive, $CdromDrive);
	$MagicDrive++;
    }
152 153 154 155
    foreach my $UnixDrive (@::UnixDrives) {
	print "[Drive $MagicDrive]\n";
	my $MntPoint = $UnixDrive->[1];
	my $Type = $UnixDrive->[2];
156 157 158
	print "\"Path\" = \"$MntPoint\"\n";
	print "\"Type\" = \"$Type\"\n";
	print "\"Filesystem\" = \"win95\"\n";
159 160 161
	print "\n";
	$MagicDrive++;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
162 163 164 165
}

sub FindWindowsDir {
    my($MagicDrive) = 'C';
166
    my(@FATD)=@::FatDrives;
Alexandre Julliard's avatar
Alexandre Julliard committed
167
    my(@wininis) = ();
168
    my ($winini);
169
    my ($ThisDrive);
170 171 172

    if (!$::opt_windir && !$::opt_fast && !$::opt_thorough) {
	$::opt_thorough++;
Alexandre Julliard's avatar
Alexandre Julliard committed
173
    }
174 175
    if ($::opt_windir) {
	$winini = &ToUnix($::opt_windir);
Alexandre Julliard's avatar
Alexandre Julliard committed
176 177 178 179
	if (!-e $winini) {
	    die "ERROR: Specified winini file does not exist\n";
	}
    }
180
    elsif ($::opt_fast) {
Alexandre Julliard's avatar
Alexandre Julliard committed
181 182
	die "-fast code can be implemented\n";
    }
183 184
    elsif ($::opt_thorough) {
	if ($::opt_debug) { print STDERR "DEBUG: Num FATD = ", $#FATD+1, "\n"; }
185
       foreach $ThisDrive (@FATD) {
186
	    my $MntPoint = $ThisDrive->[1];
187
	    push(@wininis, `find $MntPoint -iname win.ini -print`);
Alexandre Julliard's avatar
Alexandre Julliard committed
188 189 190 191
	}
	foreach $winini (@wininis) {
	    chomp $winini;
	}
192
	my ($winini_cnt) = $#wininis+1;
193
	if ($::opt_debug) {
Alexandre Julliard's avatar
Alexandre Julliard committed
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
	    print STDERR "DEBUG: Num wininis found: $winini_cnt\n";}
	if ($winini_cnt > 1) {
	    warn "$winini_cnt win.ini files found:\n";
	    @wininis = sort byFileAge @wininis;
	    warn join("\n", @wininis), "\n";
	    $winini = $wininis[0];
	    warn "Using most recent one: $winini\n";
	}
	elsif ($winini_cnt == 0) {
	    die "ERROR: No win.ini found in DOS partitions\n";
	}
	else {
	    $winini = $wininis[0];
	}
    }
    else {
	die "ERROR: None of -windir, -fast, or -thorough set\n";
    }
212
    $::windir = &ToDos(dirname($winini));
Alexandre Julliard's avatar
Alexandre Julliard committed
213
    print "[wine]\n";
214
    print "\"windows\" = ", &marshall ($::windir), "\n";
215
    if ($::opt_sysdir) {
216
	print "\"system\" = ", &marshall ($::opt_sysdir), "\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
217 218
    }
    else {
219
	print "\"system\" = ", &marshall ("$::windir\\SYSTEM"), "\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
220 221 222 223 224 225 226 227 228 229
    }
}

# Returns 1 if the device is mounted; -1 if mount check failed; 0 if not
# mounted.
# This code is Linux specific, and needs to be broadened.
sub IsMounted {
    my($Device) = @_;
    if (-d "/proc") {
	if (-e "/proc/mounts") {
230
	    open(MOUNTS, "/proc/mounts") ||
Alexandre Julliard's avatar
Alexandre Julliard committed
231 232 233
		(warn "Cannot open /proc/mounts, although it exists\n" &&
		 return -1);
	    while(<MOUNTS>) {
234
		if (/^$Device/) {
Alexandre Julliard's avatar
Alexandre Julliard committed
235 236 237 238 239 240 241 242 243 244
		    return 1; # Tested 1.4
		}
	    }
	    return 0; # Tested 1.4
	}
    }
    return -1;
}

sub RegisterDrive {
Ove Kaaven's avatar
Ove Kaaven committed
245
    my($DOSdrive, $Drive) = @_;
246 247 248 249 250
    $::DOS2Unix{$DOSdrive} = $Drive;
    $::Device2DOS{$Drive->[0]} = $DOSdrive;
    $::MntPoint2DOS{$Drive->[1]} = $DOSdrive;
    $::DOS2MntPoint{$DOSdrive} = $Drive->[1];
    $::DOS2Device{$DOSdrive} = $Drive->[0];
Alexandre Julliard's avatar
Alexandre Julliard committed
251 252 253
}

sub ReadAutoexecBat {
254 255
    if (!%::DOS2Unix) { &ReadFSTAB; }
    my($DriveC) = $::DOS2MntPoint{"C"};
Alexandre Julliard's avatar
Alexandre Julliard committed
256 257
    $DriveC =~ s%/$%%;
    my($path);
258
    if ($::opt_debug) {
Alexandre Julliard's avatar
Alexandre Julliard committed
259 260 261
	print STDERR "DEBUG: Looking for $DriveC/autoexec.bat\n"; }
    if (-e "$DriveC/autoexec.bat") {
	# Tested 1.4
262
        open(AUTOEXEC, "$DriveC/autoexec.bat") ||
Alexandre Julliard's avatar
Alexandre Julliard committed
263 264 265 266 267 268 269 270 271
            die "Cannot read autoexec.bat\n";
        while(<AUTOEXEC>) {
	    s/\015//;
            if (/^\s*(set\s+)?(\w+)\s*[\s\=]\s*(.*)$/i) {
		my($varname) = $2;
	        my($varvalue) = $3;
		chomp($varvalue);
		$varname =~ tr/A-Z/a-z/;
		while ($varvalue =~ /%(\w+)%/) {
272 273
		    my $matchname = $1;
		    my $subname = $1;
Alexandre Julliard's avatar
Alexandre Julliard committed
274
		    $subname =~ tr/A-Z/a-z/;
275
		    if (($::opt_debug) && ($::opt_debug =~ /path/i)) {
Alexandre Julliard's avatar
Alexandre Julliard committed
276 277 278
			print STDERR "DEBUG: Found $matchname as $subname\n";
			print STDERR "DEBUG: Old varvalue:\n$varvalue\n";
			print STDERR "DEBUG: Old subname value:\n" .
279
			    $::DOSenv{$subname} . "\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
280
		    }
281 282
		    if ($::DOSenv{$subname}) {
			$varvalue =~ s/\%$matchname\%/$::DOSenv{$subname}/;
Alexandre Julliard's avatar
Alexandre Julliard committed
283 284
		    }
		    else {
285
			warn "DOS environment variable $subname not\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
286 287 288 289
			warn "defined in autoexec.bat. (Reading config.sys\n";
			warn "is not implemented.)  Using null value\n";
			$varvalue =~ s/%$matchname%//;
		    }
290
		    if (($::opt_debug) && ($::opt_debug =~ /path/i)) {
Alexandre Julliard's avatar
Alexandre Julliard committed
291 292 293
			print STDERR "DEBUG: New varvalue:\n$varvalue\n";
		    }
		}
294
		if ($::opt_debug) {
Alexandre Julliard's avatar
Alexandre Julliard committed
295 296
		    print STDERR "DEBUG: $varname = $varvalue\n";
		}
297
		$::DOSenv{$varname} = $varvalue;
Alexandre Julliard's avatar
Alexandre Julliard committed
298 299 300 301 302 303
            }
        }
	close(AUTOEXEC);
    }
    else {
	# Tested 1.4
Alexandre Julliard's avatar
Alexandre Julliard committed
304
	warn "WARNING: C:\\AUTOEXEC.BAT was not found.\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
305 306
    }

307 308
    if ($::DOSenv{"path"}) {
	my @pathdirs = split(/\s*;\s*/, $::DOSenv{"path"});
309
	if (($::opt_debug) && ($::opt_debug =~ /path/i)) {
Alexandre Julliard's avatar
Alexandre Julliard committed
310 311
	    print STDERR "DEBUG (path): @pathdirs\n";
	}
312
	foreach my $pathdir (@pathdirs) {
Alexandre Julliard's avatar
Alexandre Julliard committed
313
	    if (-d &ToUnix($pathdir)) {
314
		if ($::DOSpathdir{$pathdir}++) {
Alexandre Julliard's avatar
Alexandre Julliard committed
315 316 317
		    warn "Ignoring duplicate DOS path entry $pathdir\n";
		}
		else {
318
		    if (($::opt_debug) && ($::opt_debug =~ /path/i)) {
Alexandre Julliard's avatar
Alexandre Julliard committed
319 320
			print STDERR "DEBUG (path): Found $pathdir\n";
		    }
321
		    push(@::DOSpathlist, $pathdir);
Alexandre Julliard's avatar
Alexandre Julliard committed
322 323 324 325 326 327 328
		}
	    }
	    else {
	        warn "Ignoring DOS path directory $pathdir, as it does not\n";
		warn "exist\n";
	    }
	}
329
	print "\"path\" = ", &marshall (join (";", @::DOSpathlist)), "\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
330 331 332 333 334 335
    }
    else {
	# Code status: tested 1.4
	warn "WARNING: Making assumptions for PATH\n";
	warn "Will scan windows directory for executables and generate\n";
	warn "path from that\n";
336
	my $shellcmd = 'find ' . &ToUnix($::windir) . " -iregex '" .
Alexandre Julliard's avatar
Alexandre Julliard committed
337
	    '.*\.\(exe\|bat\|com\|dll\)' . "' -print";
338
	if ($::opt_debug) {
Alexandre Julliard's avatar
Alexandre Julliard committed
339 340
	    print STDERR "DEBUG: autoexec.bat search command:\n $shellcmd\n";
	}
341
	push(@::DOScommand, `$shellcmd`);
342
	if ($::opt_debug && $::opt_debug =~ /autoexec/i) {
343
	    print STDERR "DEBUG: autoexec.bat search results:\n\@DOS::command\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
344
	}
345
	foreach my $command (@::DOScommand) {
Alexandre Julliard's avatar
Alexandre Julliard committed
346
	    $command =~ s%[^/]+$%%;
347
	    $::DOSexecdir{&ToDos($command)}++;
Alexandre Julliard's avatar
Alexandre Julliard committed
348
	}
349
	print "\"path\" = " .
350 351
	    &marshall (join(";",
			    grep(s%\\$%%,
352 353
				 sort {$::DOSexecdir{$b} <=> $::DOSexecdir{$a}}
				 (keys %::DOSexecdir)))) . "\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
354 355
    }

356
    if ($::DOSenv{"temp"} && -d &ToUnix($::DOSenv{"temp"})) {
357
	print "\"temp\" = ", &marshall ($::DOSenv{"temp"}), "\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
358 359
    }
    else {
360 361
        my $TheTemp;

Alexandre Julliard's avatar
Alexandre Julliard committed
362 363 364
        warn "WARNING: Making assumptions for TEMP\n";
	warn "Looking for \\TEMP and then \\TMP on every drive\n";
	# Watch out .. might pick CDROM drive :-)
365 366
	foreach my $DOSdrive (keys %::DOS2Unix) {
	    my $tmp = &ToUnix("$DOSdrive:\\temp");
Alexandre Julliard's avatar
Alexandre Julliard committed
367 368 369 370
	    if (-d $tmp) { $TheTemp = "$DOSdrive:\\temp"; last; }
	    $tmp = &ToUnix("$DOSdrive:\\tmp");
	    if (-d $tmp) { $TheTemp = "$DOSdrive:\\tmp"; last; }
	}
371
	$TheTemp = '/tmp' if (!$TheTemp && -d '/tmp');
Alexandre Julliard's avatar
Alexandre Julliard committed
372 373
	if ($TheTemp) {
	    warn "Using $TheTemp\n";
374
	    print "\"temp\" = ", &marshall ($TheTemp), "\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
375 376 377
	}
	else {
	    warn "Using C:\\\n";
378
	    print "\"temp\" = ", &marshall ("C:\\"), "\n";
Alexandre Julliard's avatar
Alexandre Julliard committed
379 380 381 382 383 384 385 386 387 388 389 390 391
	}
    }
    print "\n";
}

# FNunix = &ToUnix(FNdos);
#   Converts DOS filenames to Unix filenames, leaving Unix filenames
#   untouched.
sub ToUnix {
    my($FNdos) = @_;
    my($FNunix);

    # Initialize tables if necessary.
392
    if (!%::DOS2Unix) { &ReadFSTAB; }
Alexandre Julliard's avatar
Alexandre Julliard committed
393 394 395

    # Determine which type of conversion is necessary
    if ($FNdos =~ /^([A-Z])\:(.*)$/) { # DOS drive specified
396
	$FNunix = $::DOS2MntPoint{$1} . "/$2";
Alexandre Julliard's avatar
Alexandre Julliard committed
397 398
    }
    elsif ($FNdos =~ m%\\%) { # DOS drive not specified, C: is default
399
	$FNunix = $::DOS2MntPoint{"C"} . "/$FNdos";
Alexandre Julliard's avatar
Alexandre Julliard committed
400 401 402 403 404 405 406 407 408 409 410 411 412 413
    }
    else { # Unix filename
	$FNunix = $FNdos;
    }
    1 while ($FNunix =~ s%\\%/%);    # Convert \ to /
    $FNunix =~ tr/A-Z/a-z/;          # Translate to lower case
    1 while ($FNunix =~ s%//%/%);    # Translate double / to /
    return $FNunix;
}

# FNdos = &ToDOS(FNunix)
#   Converts Unix filenames to DOS filenames
sub ToDos {
    my($FNunix) = @_;
414 415 416 417
    my(@MntList) = keys %::MntPoint2DOS;
    my ($TheMntPt, $FNdos);

    foreach my $MntPt (@MntList) { # Scan mount point list to see if path matches
Alexandre Julliard's avatar
Alexandre Julliard committed
418 419 420 421 422 423 424 425 426 427 428
	if ($FNunix =~ /^$MntPt/) {
	    $TheMntPt = $MntPt;
	    last;
	}
    }
    if (!$TheMntPt) {
	Carp("ERROR: $FNunix not found in DOS directories\n");
	exit(1);
    }
    $FNdos = $FNunix;
    $FNdos =~ s/^$TheMntPt//;
429
    $FNdos = $::MntPoint2DOS{$TheMntPt} . ":" . $FNdos;
Alexandre Julliard's avatar
Alexandre Julliard committed
430 431 432 433
    1 while($FNdos =~ s%/%\\%);
    return $FNdos;
}

434 435 436 437 438 439
sub InsertDefaultFile {
    my ($fileName, $tag) = @_;
    my $state = 0;

    if (open(DEFFILE, "$fileName")) {
       while (<DEFFILE>) {
440
	  $state = 0 if ($state == 1 && $_ =~ /^[ \t]*\#/o && index($_, "[/$tag]") >= 0);
441
	  print $_ if ($state == 1);
442
	  $state = 1 if ($state == 0 && $_ =~ /^[ \t]*\#/o && index($_, "[$tag]" ) >= 0);
443 444 445 446 447 448
       }
       close(DEFFILE);
    } else {
       print STDERR "Cannot read $fileName\n";
    }
}
Alexandre Julliard's avatar
Alexandre Julliard committed
449

450 451 452 453 454 455 456
sub marshall {
    my ($s) = @_;
    $s =~ s/\\/\\\\/g;
    return "\"$s\"";
}


Alexandre Julliard's avatar
Alexandre Julliard committed
457
sub StandardStuff {
458 459 460 461 462
    if (!$::opt_inifile) {
	&InsertDefaultFile("./wine.ini", "wineconf");
    } else {
	&InsertDefaultFile($::opt_inifile, "wineconf");
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
}

sub byFileAge {
    -M $a <=> -M $b;
}

sub byDriveOrder {
    my($DeviceA) = $a->[0];
    my($DeviceB) = $b->[0];

    # Primary drives come first, logical drives last
    # DOS User's Guide (version 6) p. 70, IBM version.
    # If both drives are the same type, sort alphabetically
    # This makes drive a come before b, etc.
    # It also makes SCSI drives come before IDE drives;
    # this may or may not be right :-(
    my($Alogical, $Blogical);
    if (substr($DeviceA, 3, 1) >= 5) { $Alogical++; }
    if (substr($DeviceB, 3, 1) >= 5) { $Blogical++; }
    if ($Alogical && !$Blogical) { return -1; }
    elsif ($Blogical && !$Alogical) { return 1; }
    else { return ($DeviceA cmp $DeviceB); }
}

sub byCdOrder {
    my($DeviceA) = $a->[0];
    my($DeviceB) = $b->[0];
    $DeviceA cmp $DeviceB;
}