#!/bin/sh
exec perl -x $0 $@

#!perl

my @configuration=(
		   [  'install=new|convert',        'new',        'install new database or convert existing' ],
		   [  'workflow=DIR',         '/var/mgd',           'base directory for MidRepository' ],
		   [  'db-host=host',               'localhost',    'host where the databases reside' ],
		   [  'db-admin-user=user',         'root',           'username of the database administrator' ],
		   [  'db-admin-password=password', '',          'password of the database administrator' ],
		   [  'db-user=user',               'midgard',    'username of the midgard database user' ],
		   [  'db-user-password=password',  'midgard',    'password of the midgard database user' ],
		   [  'convert-db=databasename',            'midgardstaging',     'the db you want to convert' ],
		   [  'staging-db=databasename',            'vcstaging',     'staging database name' ],
		   [  'live-db=databasename',            'vclive',     'live database name' ],
		   [  'centralstaging-db=databasename',            'centralstaging',     'centralstaging database name' ],
		   [  'centrallive-db=databasename',            'centrallive',     'centrallive database name' ],
		   [  'meta-db=databasename',            'centralmeta',     'meta database name' ],
		   [  'host=hostname',              'localhost',   'hostname of this machine' ],
		   [  'ip=ipaddress',               '127.0.0.1',            'IP address of this machine' ],
		   [  'staging-port=portnumber',            '8001',          'port number for this server' ],
		   [  'live-port=portnumber',            '80',          'port number for this server' ],
		   [  'centralstaging-port=portnumber',            '8003',          'port number for this server' ],
		   [  'centrallive-port=portnumber',            '8002',          'port number for this server' ],
		   [  'convert-blobdir=DIR',            '/var/www/blobs_staging',     'source BLOBs directory' ],
		   [  'blobroot=DIR',                '/var/www',            'directory in which the different BLOB dirs will be created' ],
		   [  'staging-cachedir=DIR',              '/var/cache/midgard/page/staging ',            'directory where mod-preparser will store generated pages' ],
		   [  'live-cachedir=DIR',              '/var/cache/midgard/page/live',            'directory where mod-preparser will store generated pages' ],
		   [  'centralstaging-cachedir=DIR',              '/var/cache/midgard/page/centralstaging',            'directory where mod-preparser will store generated pages' ],
		   [  'centrallive-cachedir=DIR',              '/var/cache/midgard/page/centrallive',            'directory where mod-preparser will store generated pages' ],
		   [  'apxs=PROGRAM',               '/usr/bin/apxs',            'full path of the apxs binary' ],
		   [  'midgard=DIR',                '/usr',            'installation directory of Midgard' ],
		   [  'apache-user=user',           'www-data',            'username that apache runs as' ],
		   [  'apache-group=group',         'www-data',            'group that apache runs as' ],
		   [  'admin-user',                 'admin',       'name of the default user' ],
		   [  'admin-pass',                 'password',    'password of the default user' ],
		  );

use Getopt::Long;
use Socket;

my %configvalues = ();

&readoptions();
$configvalues{'help'} && exit;

$configvalues{version} = '1.4';
$none = "<none>";

checking('apache-user', sub { (defined getpwnam($configvalues{'apache-user'})) || die "User '$configvalues{'apache-user'}' does not exist\n"; });
checking('apache-group', sub {
	# seems to be a common case
	if ($configvalues{'apache-group'} eq "") { $configvalues{'apache-group'} = $configvalues{'apache-user'}; }
	(defined getgrnam($configvalues{'apache-group'})) || die "Group '$configvalues{'apache-group'}' does not exist\n";
});


checking('db-host', sub { defined gethostbyname($configvalues{'db-host'}) || die "$configvalues{'db-host'} does not resolve\n"; });
checking('db-admin-user', sub { $configvalues{'db-admin-user'} || die "db-admin-user is empty\n"; });
checking('db-user', sub { $configvalues{'db-user'} || die "db-user is empty\n"; });
checking('host', sub { defined gethostbyname($configvalues{host}) || die "$configvalues{host} does not resolve\n"; });

checking('staging-port', sub { ($configvalues{'staging-port'} =~ /^[0-9]+$/) || die "staging-port invalid\n"; });
checking('live-port', sub { ($configvalues{'live-port'} =~ /^[0-9]+$/) || die "live-port invalid\n"; });
checking('centralstaging-port', sub { ($configvalues{'centralstaging-port'} =~ /^[0-9]+$/) || die "centralstaging-port invalid\n" });
checking('centrallive-port', sub { ($configvalues{'centrallive-port'} =~ /^[0-9]+$/) || die "centrallive-port invalid\n"; });
$configvalues{'listen-port-number'} = "Listen $configvalues{'staging-port'}\nListen $configvalues{'live-port'}\nListen $configvalues{'centralstaging-port'}\nListen $configvalues{'centrallive-port'}";

if ($configvalues{install} eq 'convert') {
   checking('convert-db', sub { $configvalues{'convert-db'} || die "convert-db is empty\n"; });
}
checking('staging-db', sub { $configvalues{'staging-db'} || die "staging-db is empty\n"; });
checking('live-db', sub { $configvalues{'live-db'} || die "live-db is empty\n"; });
checking('centralstaging-db', sub { $configvalues{'centralstaging-db'} || die "centralstaging-db is empty\n"; });
checking('centrallive-db', sub { $configvalues{'centrallive-db'} || die "centrallive-db is empty\n"; });
checking('admin-user', sub { $configvalues{'admin-user'} || die "admin-user is empty\n"; });
checking('admin-pass', sub { $configvalues{'admin-pass'} || die "admin-pass is empty\n"; });

if ($configvalues{'admin-pass'} !~ /\*\*/) {
  $configvalues{'admin-pass-wo-asterisk'} = $configvalues{'admin-pass'};
  $configvalues{'admin-pass'} = "**" .  $configvalues{'admin-pass'};
} else {
  $configvalues{'admin-pass-wo-asterisk'} = substr($configvalues{'admin-pass'}, 2);
}
    
foreach('staging', 'live', 'centralstaging', 'centrallive') {
  $configvalues{$_ . '-blobdir'} = $configvalues{blobroot} . '/blobs_' . $configvalues{$_ . '-db'};
}

if ($configvalues{ip} eq '') {
   my $tmp = inet_aton($configvalues{host});
   if (defined $tmp) { $configvalues{ip} = inet_ntoa($tmp); }
}
checking('ip', sub { ($configvalues{ip} =~ /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/) || die "ip '$configvalues{ip}' is invalid\n" });

checking('midgard', sub {
   $location = '';
   foreach ('/usr', '/usr/local', $configvalues{midgard}) {
      if (-e "$_/share/midgard") { $location = $_; }
   }
   $location || die "Cannot find installation location of midgard\n";
   $configvalues{midgard} = $location;
});
$configvalues{'midgard-data'} = "$configvalues{midgard}/share/midgard";
$configvalues{'midgard-bin'} = "$configvalues{midgard}/bin";

checking('apxs', sub {
   if (!$configvalues{apxs}) {
      foreach (split(/:/, $ENV{PATH})) {
         if (-e "$_/apxs") { $configvalues{apxs} = "$_/apxs"; }
      }
   }
   -e $configvalues{apxs} || die "Cannot find apxs\n";

   my $libexecdir=`$configvalues{apxs} -q LIBEXECDIR`;
   chomp $libexecdir;

   if ($libexecdir eq '') {
      print "Your apxs seems to be broken (CFG_LIBEXECDIR not defined)\nAssuming CFG_LIBEXECDIR to /etc/httpd/modules\n";
      $libexecdir = "/etc/httpd/modules";
   }
   my $sysconfdir=`$configvalues{apxs} -q SYSCONFDIR`;
   chomp $sysconfdir;

   if ($sysconfdir eq '') {
      print "Your apxs seems to be broken (SYSCONFDIR not defined)\nAssuming SYSCONFDIR to /etc/httpd/conf\n";
      $libexecdir = "/etc/httpd/conf";
   }

   my $httpd=`$configvalues{apxs} -q SBINDIR` . '/' . `$configvalues{apxs} -q TARGET`;
   chomp $httpd;

   if ($httpd eq '') {
      print "Your apxs seems to be broken (SBINDIR + TARGET not defined)\nAssuming executable to /usr/sbin/httpd\n";
      $httpd = "/usr/sbin/httpd";
   }


   $configvalues{'sysconfdir'} = $sysconfdir;
   $configvalues{'httpd'} = $httpd;
   $configvalues{'rootfile-php3'} = "$libexecdir/midgard-root.php3";
   $configvalues{'rootfile-php4'} = "$libexecdir/midgard-root.php";
});

$configvalues{'php3-comment'} = "# ";
$configvalues{'php4-comment'} = "";
$configvalues{'php-command-prefix'} = "php_value ";

checking('php', sub { 
	   if (-e "/usr/bin/php") { 
	     $configvalues{php} = "/usr/bin/php"; 
	   } elsif (-e "/usr/bin/php4") { 
	     $configvalues{php} = "/usr/bin/php4"; 
	   } else { 
	     die "Cannot find php commandline interpreter in /usr/bin/php nor /usr/bin/php4\n"; 
	   }
	 }
	);

checking('install', sub { checkvalues($configvalues{install}, 'new', 'convert'); });

$configvalues{'parser'} = "latin1";

open F, ">config.cache";
print F "\%configvalues = (\n";
foreach (@configuration) {
	$key = $$_[0];
	$key =~ s/=.*//;
	print F "\t", '"', quotemeta($key), '" => "',
		quotemeta($configvalues{$key}), '",', "\n";
}
print F ");\n";
close F;

print "Generating install files, please wait...\n";
output('dbinstall', 'midgard-workflow.conf', 'mysql-db.sql', 'mysql-user.sql', 'vcconfig.php', 'midgarddb', 'metadb', 'database-upgrade', 'support.xml', 'clear', 'vcstaging.conf', 'vclive.conf', 'centralstaging.conf', 'centrallive.conf', 'convertdb.conf', 'clients/call-migrate.php', 'clients/everymin.php', 'clients/dump.php');
system "chmod 0700 dbinstall database-upgrade clear";
system "chmod 0660 midgard-workflow.conf mysql-db.sql mysql-user.sql config.cache vcconfig.php midgarddb metadb support.xml  vcstaging.conf vclive.conf centralstaging.conf centrallive.conf convertdb.conf";
system "chmod 0755 clients/*";
system "chown $> dbinstall mysql-db.sql mysql-user.sql config.cache vcconfig.php midgarddb metadb database-upgrade support.xml clear vcstaging.conf vclive.conf centralstaging.conf centrallive.conf convertdb.conf";


########################## UTILS ################################################

sub readoptions
{
	if (-f './config.cache') {
		print STDERR "Loading config.cache...\n";
		eval `cat ./config.cache`;
	}

   foreach (@configuration) {
      ($option, $default, $help) = @{$_};
      if (length($option) > $longest) { $longest = length($option); }
      
      $option =~ s/=.*//;
      $options{"with-$option:s"} = \&handle_option;
      if (! defined $configvalues{$option}) {
			$configvalues{$option} = $default;
		}
      $optionhelp{$option} = $help;
   }

   foreach (@configuration) {
      ($option, $default, $help) = @{$_};
      $helptext .= sprintf("--with-%-${longest}s     $help\n", $option);
   }

   GetOptions('verbose' => \$verbose, 'help' => \&help, %options);
}

sub handle_option
{
my ($name, $value) = @_;

   $name =~ s/^with-//;
   if ($value) { $configvalues{$name} = $value; }
}

sub help
{
   $configvalues{'help'} = 'yes';
   die $helptext;
}

sub checkvalues
{
my $answer = shift;
my @valid = @_;
my $o, $h;

   foreach (@valid) {
      ($answer eq $_) && return;
   }

   if ($answer) { print "unexpected answer '$answer'.\n"; }
   else { print "this option requires a value.\n"; }
   print "Valid options are: ", join(', ', @valid), "\n";
   exit(1);
}

sub checking
{
my ($option, $sub) = @_;

   print STDERR "Checking for $optionhelp{$option}... ";
   &$sub();
   print $configvalues{$option}, "\n";
}

sub showoptions
{
my ($option, $default, $help);

   foreach (@configuration) {
      ($option, $default, $help) = @{$_};
      $option =~ s/=.*//;
      print "$option => $configvalues{$option}\n";
   }
}

sub output
{
my @files = @_;
my %replace;
my ($key, $value);
my $line;

   while (($key, $value) = each(%configvalues)) {
      $key =~ s/-/_/g;
      $key = uc $key;

      $value =~ s/([$\\"])/\\$1/g;

      $replace{$key} = $value;
      $verbose && print "Replacing \@$key\@ with '$value'\n";
   }

   foreach (@files) {
      open I, "<$_.in";
      open O, ">$_";
      while ($line = <I>) {
         foreach (keys %replace) {
            $line =~ s/\@$_\@/$replace{$_}/g;
         }
         print O $line;
      }
      close I;
      close O;
   }
} 
