mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 12:54:13 +00:00
9a910dd3e5
Change the way functions are called and their declaration order so perl can check the prototypes.
492 lines
15 KiB
Perl
Executable file
492 lines
15 KiB
Perl
Executable file
#!/usr/bin/perl -w
|
|
|
|
# This program generates wine.conf files on STDOUT.
|
|
# 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:
|
|
#
|
|
# This program examines the contents of the DOS filesystems and
|
|
# attempts to generate a sensible wine.conf file. This is output
|
|
# to STDOUT.
|
|
# It reads /etc/fstab to find mounting locations of the hard disk drives
|
|
# 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.
|
|
|
|
# It would make sense to incorporate much of the heuristic code in
|
|
# 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;
|
|
use strict;
|
|
use Carp;
|
|
|
|
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";
|
|
print "-inifile <filename> Path to the wine.ini file (by default './wine.ini')\n";
|
|
# 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);
|
|
}
|
|
|
|
# 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 = shift;
|
|
if (-d "/proc") {
|
|
if (-e "/proc/mounts") {
|
|
open(MOUNTS, "/proc/mounts") ||
|
|
(warn "Cannot open /proc/mounts, although it exists\n" &&
|
|
return -1);
|
|
while(<MOUNTS>) {
|
|
if (/^$Device/) {
|
|
return 1; # Tested 1.4
|
|
}
|
|
}
|
|
return 0; # Tested 1.4
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
sub RegisterDrive($$) {
|
|
my($DOSdrive, $Drive) = @_;
|
|
$::DOS2Unix{$DOSdrive} = $Drive;
|
|
$::Device2DOS{$Drive->[0]} = $DOSdrive;
|
|
$::MntPoint2DOS{$Drive->[1]} = $DOSdrive;
|
|
$::DOS2MntPoint{$DOSdrive} = $Drive->[1];
|
|
$::DOS2Device{$DOSdrive} = $Drive->[0];
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
sub ReadFSTAB() {
|
|
$::opt_f = $::opt_f ? $::opt_f : '/etc/fstab';
|
|
open(FSTAB, $::opt_f) || die "Cannot read $::opt_f\n";
|
|
while(<FSTAB>) {
|
|
next if /^\s*\#/;
|
|
next if /^\s*$/;
|
|
|
|
my ($device, $mntpoint, $type, @rest) = split(' ', $_);
|
|
if ($device !~ m"^/dev/fd") {
|
|
if ($type eq "ntfs") {
|
|
push(@::FatDrives, [$device, $mntpoint, 'win95']);
|
|
}
|
|
elsif ($type eq "msdos" || $type eq "vfat") {
|
|
push(@::FatDrives, [$device, $mntpoint, $type]);
|
|
}
|
|
elsif ($type eq "iso9660" ||
|
|
($mntpoint eq "/cdrom" && ! $type eq 'supermount') ||
|
|
($device eq '/dev/cdrom' && $type eq 'auto') ) {
|
|
push(@::CdromDrives, [$device, $mntpoint, 'win95']);
|
|
}
|
|
elsif ( ($mntpoint eq '/mnt/cdrom' || $mntpoint eq '/cdrom')
|
|
&& $type eq 'supermount') {
|
|
push(@::CdromDrives, ['/dev/cdrom', $mntpoint, 'win95']);
|
|
}
|
|
}
|
|
}
|
|
if (!@::FatDrives) {
|
|
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);
|
|
}
|
|
push(@::UnixDrives, ['', '/tmp', 'hd']);
|
|
push(@::UnixDrives, ['', '${HOME}', 'network']);
|
|
my $MagicDrive = 'C';
|
|
@::FatDrives = sort byDriveOrder @::FatDrives;
|
|
@::CdromDrives = sort byCdOrder @::CdromDrives;
|
|
foreach my $FatDrive (@::FatDrives) {
|
|
print "[Drive $MagicDrive]\n";
|
|
my $MntPoint = $FatDrive->[1];
|
|
my $FileSys = $FatDrive->[2];
|
|
print "\"Path\" = \"$MntPoint\"\n";
|
|
print "\"Type\" = \"hd\"\n";
|
|
print "\"Filesystem\" = \"$FileSys\"\n";
|
|
print "\n";
|
|
RegisterDrive($MagicDrive, $FatDrive);
|
|
if(!IsMounted($FatDrive->[0])) {
|
|
warn "WARNING: DOS Drive $MagicDrive (" . $FatDrive->[0] .
|
|
") is not mounted\n";
|
|
}
|
|
$MagicDrive++;
|
|
}
|
|
foreach my $CdromDrive (@::CdromDrives) {
|
|
print "[Drive $MagicDrive]\n";
|
|
my $Device = $CdromDrive->[0];
|
|
my $MntPoint = $CdromDrive->[1];
|
|
my $FileSys = $CdromDrive->[2];
|
|
print "\"Path\" = \"$MntPoint\"\n";
|
|
print "\"Type\" = \"cdrom\"\n";
|
|
print "\"Device\" = \"$Device\"\n";
|
|
print "\"Filesystem\" = \"$FileSys\"\n";
|
|
print "\n";
|
|
RegisterDrive($MagicDrive, $CdromDrive);
|
|
$MagicDrive++;
|
|
}
|
|
foreach my $UnixDrive (@::UnixDrives) {
|
|
print "[Drive $MagicDrive]\n";
|
|
my $MntPoint = $UnixDrive->[1];
|
|
my $Type = $UnixDrive->[2];
|
|
print "\"Path\" = \"$MntPoint\"\n";
|
|
print "\"Type\" = \"$Type\"\n";
|
|
print "\"Filesystem\" = \"win95\"\n";
|
|
print "\n";
|
|
$MagicDrive++;
|
|
}
|
|
}
|
|
|
|
# FNunix = ToUnix(FNdos);
|
|
# Converts DOS filenames to Unix filenames, leaving Unix filenames
|
|
# untouched.
|
|
sub ToUnix($) {
|
|
my $FNdos = shift;
|
|
my $FNunix;
|
|
|
|
# Initialize tables if necessary.
|
|
if (!%::DOS2Unix) { ReadFSTAB(); }
|
|
|
|
# Determine which type of conversion is necessary
|
|
if ($FNdos =~ /^([A-Z])\:(.*)$/) { # DOS drive specified
|
|
$FNunix = $::DOS2MntPoint{$1} . "/$2";
|
|
}
|
|
elsif ($FNdos =~ m%\\%) { # DOS drive not specified, C: is default
|
|
$FNunix = $::DOS2MntPoint{"C"} . "/$FNdos";
|
|
}
|
|
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 = shift;
|
|
my(@MntList) = keys %::MntPoint2DOS;
|
|
my ($TheMntPt, $FNdos);
|
|
|
|
foreach my $MntPt (@MntList) { # Scan mount point list to see if path matches
|
|
if ($FNunix =~ /^$MntPt/) {
|
|
$TheMntPt = $MntPt;
|
|
last;
|
|
}
|
|
}
|
|
if (!$TheMntPt) {
|
|
Carp("ERROR: $FNunix not found in DOS directories\n");
|
|
exit(1);
|
|
}
|
|
$FNdos = $FNunix;
|
|
$FNdos =~ s/^$TheMntPt//;
|
|
$FNdos = $::MntPoint2DOS{$TheMntPt} . ":" . $FNdos;
|
|
1 while($FNdos =~ s%/%\\%);
|
|
return $FNdos;
|
|
}
|
|
|
|
sub InsertDefaultFile($$) {
|
|
my ($fileName, $tag) = @_;
|
|
my $state = 0;
|
|
|
|
if (open(DEFFILE, "$fileName")) {
|
|
while (<DEFFILE>) {
|
|
$state = 0 if ($state == 1 && $_ =~ /^[ \t]*\#/o && index($_, "[/$tag]") >= 0);
|
|
print $_ if ($state == 1);
|
|
$state = 1 if ($state == 0 && $_ =~ /^[ \t]*\#/o && index($_, "[$tag]" ) >= 0);
|
|
}
|
|
close(DEFFILE);
|
|
} else {
|
|
print STDERR "Cannot read $fileName\n";
|
|
}
|
|
}
|
|
|
|
sub marshall($) {
|
|
my $s = $_[0];
|
|
$s =~ s/\\/\\\\/g;
|
|
return "\"$s\"";
|
|
}
|
|
|
|
sub byFileAge() {
|
|
-M $a <=> -M $b;
|
|
}
|
|
|
|
sub FindWindowsDir() {
|
|
my($MagicDrive) = 'C';
|
|
my(@FATD)=@::FatDrives;
|
|
my(@wininis) = ();
|
|
my ($winini);
|
|
my ($ThisDrive);
|
|
|
|
if (!$::opt_windir && !$::opt_fast && !$::opt_thorough) {
|
|
$::opt_thorough++;
|
|
}
|
|
if ($::opt_windir) {
|
|
$winini = ToUnix($::opt_windir);
|
|
if (!-e $winini) {
|
|
die "ERROR: Specified winini file does not exist\n";
|
|
}
|
|
}
|
|
elsif ($::opt_fast) {
|
|
die "-fast code can be implemented\n";
|
|
}
|
|
elsif ($::opt_thorough) {
|
|
if ($::opt_debug) { print STDERR "DEBUG: Num FATD = ", $#FATD+1, "\n"; }
|
|
foreach $ThisDrive (@FATD) {
|
|
my $MntPoint = $ThisDrive->[1];
|
|
push(@wininis, `find $MntPoint -iname win.ini -print`);
|
|
}
|
|
foreach $winini (@wininis) {
|
|
chomp $winini;
|
|
}
|
|
my ($winini_cnt) = $#wininis+1;
|
|
if ($::opt_debug) {
|
|
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";
|
|
}
|
|
$::windir = ToDos(dirname($winini));
|
|
print "[wine]\n";
|
|
print "\"windows\" = ", marshall ($::windir), "\n";
|
|
if ($::opt_sysdir) {
|
|
print "\"system\" = ", marshall ($::opt_sysdir), "\n";
|
|
}
|
|
else {
|
|
print "\"system\" = ", marshall ("$::windir\\SYSTEM"), "\n";
|
|
}
|
|
}
|
|
|
|
sub ReadAutoexecBat() {
|
|
if (!%::DOS2Unix) { ReadFSTAB(); }
|
|
my($DriveC) = $::DOS2MntPoint{"C"};
|
|
$DriveC =~ s%/$%%;
|
|
my($path);
|
|
if ($::opt_debug) {
|
|
print STDERR "DEBUG: Looking for $DriveC/autoexec.bat\n"; }
|
|
if (-e "$DriveC/autoexec.bat") {
|
|
# Tested 1.4
|
|
open(AUTOEXEC, "$DriveC/autoexec.bat") ||
|
|
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+)%/) {
|
|
my $matchname = $1;
|
|
my $subname = $1;
|
|
$subname =~ tr/A-Z/a-z/;
|
|
if (($::opt_debug) && ($::opt_debug =~ /path/i)) {
|
|
print STDERR "DEBUG: Found $matchname as $subname\n";
|
|
print STDERR "DEBUG: Old varvalue:\n$varvalue\n";
|
|
print STDERR "DEBUG: Old subname value:\n" .
|
|
$::DOSenv{$subname} . "\n";
|
|
}
|
|
if ($::DOSenv{$subname}) {
|
|
$varvalue =~ s/\%$matchname\%/$::DOSenv{$subname}/;
|
|
}
|
|
else {
|
|
warn "DOS environment variable $subname not\n";
|
|
warn "defined in autoexec.bat. (Reading config.sys\n";
|
|
warn "is not implemented.) Using null value\n";
|
|
$varvalue =~ s/%$matchname%//;
|
|
}
|
|
if (($::opt_debug) && ($::opt_debug =~ /path/i)) {
|
|
print STDERR "DEBUG: New varvalue:\n$varvalue\n";
|
|
}
|
|
}
|
|
if ($::opt_debug) {
|
|
print STDERR "DEBUG: $varname = $varvalue\n";
|
|
}
|
|
$::DOSenv{$varname} = $varvalue;
|
|
}
|
|
}
|
|
close(AUTOEXEC);
|
|
}
|
|
else {
|
|
# Tested 1.4
|
|
warn "WARNING: C:\\AUTOEXEC.BAT was not found.\n";
|
|
}
|
|
|
|
if ($::DOSenv{"path"}) {
|
|
my @pathdirs = split(/\s*;\s*/, $::DOSenv{"path"});
|
|
if (($::opt_debug) && ($::opt_debug =~ /path/i)) {
|
|
print STDERR "DEBUG (path): @pathdirs\n";
|
|
}
|
|
foreach my $pathdir (@pathdirs) {
|
|
if (-d ToUnix($pathdir)) {
|
|
if ($::DOSpathdir{$pathdir}++) {
|
|
warn "Ignoring duplicate DOS path entry $pathdir\n";
|
|
}
|
|
else {
|
|
if (($::opt_debug) && ($::opt_debug =~ /path/i)) {
|
|
print STDERR "DEBUG (path): Found $pathdir\n";
|
|
}
|
|
push(@::DOSpathlist, $pathdir);
|
|
}
|
|
}
|
|
else {
|
|
warn "Ignoring DOS path directory $pathdir, as it does not\n";
|
|
warn "exist\n";
|
|
}
|
|
}
|
|
print "\"path\" = ", marshall (join (";", @::DOSpathlist)), "\n";
|
|
}
|
|
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";
|
|
my $shellcmd = 'find ' . ToUnix($::windir) . " -iregex '" .
|
|
'.*\.\(exe\|bat\|com\|dll\)' . "' -print";
|
|
if ($::opt_debug) {
|
|
print STDERR "DEBUG: autoexec.bat search command:\n $shellcmd\n";
|
|
}
|
|
push(@::DOScommand, `$shellcmd`);
|
|
if ($::opt_debug && $::opt_debug =~ /autoexec/i) {
|
|
print STDERR "DEBUG: autoexec.bat search results:\n\@DOS::command\n";
|
|
}
|
|
foreach my $command (@::DOScommand) {
|
|
$command =~ s%[^/]+$%%;
|
|
$::DOSexecdir{ToDos($command)}++;
|
|
}
|
|
print "\"path\" = " .
|
|
marshall (join(";",
|
|
grep(s%\\$%%,
|
|
sort {$::DOSexecdir{$b} <=> $::DOSexecdir{$a}}
|
|
(keys %::DOSexecdir)))) . "\n";
|
|
}
|
|
|
|
if ($::DOSenv{"temp"} && -d ToUnix($::DOSenv{"temp"})) {
|
|
print "\"temp\" = ", marshall ($::DOSenv{"temp"}), "\n";
|
|
}
|
|
else {
|
|
my $TheTemp;
|
|
|
|
warn "WARNING: Making assumptions for TEMP\n";
|
|
warn "Looking for \\TEMP and then \\TMP on every drive\n";
|
|
# Watch out .. might pick CDROM drive :-)
|
|
foreach my $DOSdrive (keys %::DOS2Unix) {
|
|
my $tmp = ToUnix("$DOSdrive:\\temp");
|
|
if (-d $tmp) { $TheTemp = "$DOSdrive:\\temp"; last; }
|
|
$tmp = ToUnix("$DOSdrive:\\tmp");
|
|
if (-d $tmp) { $TheTemp = "$DOSdrive:\\tmp"; last; }
|
|
}
|
|
$TheTemp = '/tmp' if (!$TheTemp && -d '/tmp');
|
|
if ($TheTemp) {
|
|
warn "Using $TheTemp\n";
|
|
print "\"temp\" = ", marshall ($TheTemp), "\n";
|
|
}
|
|
else {
|
|
warn "Using C:\\\n";
|
|
print "\"temp\" = ", marshall ("C:\\"), "\n";
|
|
}
|
|
}
|
|
print "\n";
|
|
}
|
|
|
|
sub StandardStuff() {
|
|
if (!$::opt_inifile) {
|
|
InsertDefaultFile("./wine.ini", "wineconf");
|
|
} else {
|
|
InsertDefaultFile($::opt_inifile, "wineconf");
|
|
}
|
|
}
|
|
|
|
### Main
|
|
|
|
GetOptions('windir=s', 'sysdir=s', 'thorough', 'debug:s', 'inifile=s') || Usage;
|
|
|
|
print "WINE REGISTRY Version 2\n";
|
|
print ";; All keys relative to \\\\Machine\\\\Software\\\\Wine\\\\Wine\\\\Config\n\n";
|
|
ReadFSTAB();
|
|
FindWindowsDir();
|
|
ReadAutoexecBat();
|
|
StandardStuff();
|