#!/usr/bin/perl
# -*- Mode: cperl -*-
#
# Rewritten by Jrme Martin <jerome.f.martin@free.fr>
#
# Some additions by Danny Tholen <obiwan@mailmij.org>
#
# Copyright (C) 2002 by Chmouel Boudjnah <chmouel@mandrakesoft.com>,
# MandrakeSoft
# Redistribution of this file is permitted under the terms of the GNU
# Public License (GPL)

use strict;


# rcc: s/wine.reg/config/
my $config = shift || '/etc/wine/config';
my $fstab = '/etc/fstab';
my $autofs = '/etc/auto.master';
my $fattype = 'vfat|ntfs';
my $windir = 'windows';
my $windrive = 'C:\\';
my $winmpoint = '/var/lib/wine';
my @fat;
my @iso;


sub change_config {
    local *F, *O;
    my $gotc;
    my $gotwine;
    my $gotdrive;
    my $gotversion;
    my $output = `mktemp /tmp/.wine.XXXXXX`;chop($output);
    my $drive;
    my $parsed = 0;
    my $homedrive = "H";
    my $tmpdrive = "Z";
    open O, ">$output"; select O;
    open F, $config;
    while (<F>) {
	$gotc++ if /^\[Drive\s*C\]/;
	$gotdrive++ if /^\[Drive\s*D\]/;
	$gotwine++ if (/^\[wine\]/);
	$gotversion++ if (/^\[Version\]/);
	
	if ($gotc and /^\"Path\"\s*=\s*\"([^\"]+)\"/) {
	    my $w = $1;
	    my $f;
	     
	    #check for boot.ini and msdos.sys
	    foreach $f (@fat)
	    {
	        if (!$parsed) {
		    $parsed = parse_winfiles("$f/msdos.sys", "WinDir");
	            $parsed = $parsed + parse_winfiles("$f/boot.ini", "default");            
	        }
	     if ($parsed && check_dir($f, $windir) ) { delete $fat[$f]; }
	     
             }
	    
	     s|$1|$winmpoint|;
	     
	     print; undef $gotc; next;
	}
	elsif ($gotwine) {
	    
	    if (/^\"Windows\"/) {
	        print "\"Windows\" = \"" . "$windrive\\" . $windir . "\"\n";
	    }
	    elsif (/^\"System\"/) {
		print "\"System\" = \"" . "$windrive\\" . "$windir\\\\system" . "\"\n";
	    }
	    elsif (/^\"Temp\"/) {
		print "\"Temp\" = \"" . "$tmpdrive:\\\\" . "\"\n";
	    }
	    elsif (/^\"Path\"/) {
		print "\"Path\" = \"" . "$windrive\\" . "$windir;" . "$windrive\\" . "$windir\\\\system;" . "$homedrive:\\\\;" . "$tmpdrive:\\\\" . "\"\n";
	    }
	    elsif (/^\"Profile\"/) {
		print "\"Profile\" = \"" . "$windrive\\" . "$windir\\\\Profiles\\\\Administrator" . "\"\n";
		
            } 
	    elsif (/^\[Version\]/) {
	        undef $drive;undef $gotwine; print "[Version]\n";
            }
	    else {
		print;
	    }
	    next;

	}
	elsif ($gotdrive)
	{
	    $drive = "D";
	    my $f;
	    foreach $f (@fat)
	      {
		# hmm: seems that delete doesn't remove the element:      
		if (!$f) {next;}
		print "[Drive $drive]\n";
		print "\"Path\" = \"" . $f . "\"\n";
		print "\"Type\" = \"hd\"\n";
		#$f =~ s|.*/(\w+)/?|$1|;
		print "\"Label\" = \"$f\"\n";
		print "\"Filesystem\" = \"win95\"\n\n";
		$drive++;
	      }

	    foreach $f (@iso)
	      {
		print "[Drive $drive]\n";
		print "\"Path\" = \"" . $f->[0] . "\"\n";
		print "\"Type\" = \"cdrom\"\n";
		print "\"Label\" = \"CD-Rom\"\n";
		print "\"Filesystem\" = \"win95\"\n";
		print "; make sure that device is correct and has proper permissions !\n";
		print "\"Device\" = \"" . $f->[1] . "\"\n\n";
		$drive++;
	      }

	    print "[Drive $drive]\n";
	    print "\"Path\" = \"\${HOME}\"\n";
	    print "\"Type\" = \"network\"\n";
	    print "\"Label\" = \"Home\"\n";
	    print "\"Filesystem\" = \"win95\"\n\n";
            $homedrive = $drive ;
	    $drive++;
	    
	    print "[Drive $drive]\n";
	    print "\"Path\" = \"/tmp/winetmp-\${USER}\"\n";
	    print "\"Type\" = \"hd\"\n";
	    print "\"Label\" = \"Tmp Drive\"\n";
	    print "\"Filesystem\" = \"win95\"\n\n";
	    $tmpdrive = $drive ;
	    
	    undef $gotdrive;
	    next;
	}
	elsif ($drive)
	{
	    next;
	}
	else 
	{
	    print; next;
	}
	print;
      }
    close F;
    close O;
    system("cp -f $config $config.bak");
    system("mv $output $config");
}
sub parse_fstab {
    local *F;
    open F, $fstab;
    while (<F>) {
	@_ = split ' ';
	next if ($_[0] =~ /^#/);
	if ($_[2] =~ /$fattype/)
	  {
	   push @fat, $_[1] if ( -d $_[1]);
	  }
	elsif ($_[0] =~ /\/mnt\/cdrom\d?/)
	  {
	   push @iso, [ $_[1], $1 ] if ($_[3] =~ /dev=([\w\/]+)/);
	  }
    }
    close F;
    return;
}
sub parse_autofs {
    local *F;
    my ($f, $d) = (shift, shift);
    open F, $f;
    while (<F>) {
	@_ = split ' ';
	next if ($_[0] =~ /^#/);
	if ($_[1] =~ /-fstype=$fattype/)
	  {
	    push @fat, "$d/$_[0]" if ( -d $_[0]);
	  }
	elsif ($_[0] =~ /^\//)
	  {
	    parse_autofs ($_[1], $_[0]);
	  }
    }
    close F;
    return;
}
# Danny:
# The Win NT,2k, and XP machines have a boot.ini file,
# which specifies the windows direcotry like:
# default=multi(0)disk(0)rdisk(0)partition(1)\WINNT
#
# NOTE1: I cannot test on nt/2k/xp, so feedback on strange windows machines welcome.
# NOTE2: perhaps the partition stuff can be used to guess the $winmpoint
#
# The win95/98 series have a msdos.sys file,
# which specifies the windows direcotry like:
# WinDir=C:\WINDOWS
sub parse_winfiles {
   local *F;
   my $winfile = shift;
   my $filekey = shift;
   my ($a, $key, $val);
   
   if ( -r $winfile ) { 
       open F, $winfile;
       my @file = <F>;
       foreach $a (@file)
           {	    
	       ($key,$val) = split(/=/,$a);
               if ($key eq $filekey)
	       {
		  ($key, $windir)= split(/\\/,$val);
		  $windir = lc($windir);
		  #Capitalize first letter (fat drives seem to have capitalized
		  #dirs. Do not know how to case insens. check existance of dir.
		  $windir =~ s/\b(\w)/\U$1/g ;
		  #I would like to use chomp/chop, but it doesn't work?
		  #perhaps because its a windoze file.
		  $windir = substr($windir, 0, length($windir)-2);
		  
		  # if the length of the key is 2, is is a drive letter
		  # if not it is boot.ini partition stuff.
		  my $len = length($key);
		  if ( $len = 2) {
			  $windrive = "$key\\";
		  }
	       
		  close F;
		  return 1;
	        }
	  }
    close F;
    return 0;
    }
}

# Danny: Check if the windows dir really exist on any partition.
sub check_dir {
    my $mpoint = shift;
    my $dir = shift;
    if ( -d "$mpoint/$dir")
      {
	$winmpoint = $mpoint;
     
	return 1;
      }
    return 0;
}

parse_fstab();
parse_autofs($autofs);
change_config();
