#! /usr/local/bin/perl

$| = 1;
use LWP::Simple;

##############################################################
# licensed under LGPL
# coded by Lars Gohlke
# reachable under http://www.lars-gohlke.de.vu
# contact http://www.lars-gohlke.de.vu/hp/?id=contact
##############################################################
# Germany 2005/06/06
# this script is based on http://iedb.org/svn/svn-install.txt
#
# Step by step automatic installation of
#	- subversion
#	- apache
#	- BerkelyDB
#
# download + installation is automated
#
# ***********************************************************
# history
#	2005/06/06
#		* initial release
#
##############################################################

my %_DIRS	=(
	"APACHE_STD"	=> "/usr/local/apache2/",
	"DB_STD"		=> "/usr/local/BerkeleyDB.4.3"
);

my %_CONF	= (
	"APACHE"=>{
		"file"	=>	"httpd-2.0.54.tar.bz2",
		"url"	=>	"http://ftp.uni-erlangen.de/pub/mirrors/apache/httpd/",
		"configure_opts"	=>	[
			"--enable-dav=shared",
			"--with-gdbm=no",
			"--enable-mod_deflate=shared",
      		"--enable-so",
			"--with-berkeley-db=".$_DIRS{'DB_STD'},
			"--with-dbm=db4"
			]
	},
	"DB" =>{
		"file"	=> "db-4.3.28.NC.tar.gz",
		"url"	=> "http://downloads.sleepycat.com/",
		"libs"	=> "/usr/local/BerkeleyDB.4.3/lib"
	},
	"STATUS" =>{
		"max_line_length"	=> 80,
		"text_length"		=> 0,
		"steps_to_end"		=> 26
	},
	"SVN" => {
		"file"	=>	"subversion-1.2.0.tar.bz2",
		"url"	=>	"http://subversion.tigris.org/downloads/",
		"configure_opts"	=>	[
			"--with-apxs=".$_DIRS{'APACHE_STD'}."bin/apxs",
			"--with-apr=".$_DIRS{'APACHE_STD'},
			"--enable-mod_deflate=shared",
      		"--with-apr-util=".$_DIRS{'APACHE_STD'},
			"--with-berkeley-db=".$_DIRS{'DB_STD'}
			]
	},
	"log_file"	=> " 1>>svn_install.log 2>>svn_install.log"
);

### ADDON ###
my %APACHE_adjust = (
	# these dirs will be renamed to dir_orig
	# and replaced by an link to following
	"cgi-bin"	=> "/srv/svn/apache_cgi-bin",
	"conf"		=> "/srv/svn/apache_conf",
	"htdocs"	=> "/srv/svn/apache_htdocs"
);

# Schritt 3
&get_superuser();
# zur Überprüfung (1)
&check_urls(1);
# Schritt  2 (2)
&download_svn(2);
# Schritt  4 (3)
&extract_svn(3);
# Schritt  5 (4)
&autogen_svn(4);
# Schritt 7 (5)
&download_db(5);
# Schritt 8-19 (6-11)
&install_db(6);
# Schritt 20
&download_apache(12);
# Schritt 21
&extract_apache(13);
# Schritt 22-28
&install_apache(14);
# Schritt 29-36
&install_svn(19);
# deleting dirs
&delete_dirs(24);

# if you know what you're doing uncomment this line
#&apache_adjust_install();

print "\n"x2,"so nun bitte ab Punkt 40 selber weitermachen","\n";
print "( go on creating repository and so on )\n";

print "\n"x2,"Bitte bei einem Upgrade nicht vergessen, den ServerRoot anzupassen","\n";
print "( don't forget to replace ServerRoot with correct one after you upgraded \n";


#*****************************************************************************
sub apache_adjust_install{
	# for all paths to fit
	foreach my $_dir (keys %APACHE_adjust){

		if (-e $_DIRS{'APACHE_STD'}.$_dir ){
			# go on, unless link exists
			unless (-l $_DIRS{'APACHE_STD'}.$_dir){
				rename( $_DIRS{'APACHE_STD'}.$_dir, $_DIRS{'APACHE_STD'}.$_dir."_orig" );

				if ( -e $APACHE_adjust{$_dir} ){
					print $APACHE_adjust{$_dir}," exists \n";
				}
				if ( symlink( $APACHE_adjust{$_dir} , $_DIRS{'APACHE_STD'}.$_dir ) ){
					print "link ok\n";
				}
				else{
					print "link failed\n";
				}
			}
		}
		else{
			print "ERROR : \"",$_DIRS{'APACHE_STD'}.$_dir,"\" do not existing \n";
			die;
		}
	}
}

sub delete_dirs{
	my $_step = $_[0];
	foreach my $_SECTION("SVN","APACHE","DB"){
		my %_SECTION = %{$_CONF{ $_SECTION }};
		(my $_dir = $_SECTION{"file"}) =~ s/\.tar\.(bz2|gz)$//i;

		&progress($_step++);
		&status("deleting $_dir","wait");
		system("rm -rf $_dir");
		&status("","ok");
	}
}

#*****************************************************************************
sub install_svn{
	my $_step = $_[0];
	my $_SECTION = "SVN";

	my $_sub = "install_".$_SECTION;
	my %_SECTION = %{$_CONF{ $_SECTION }};

	(my $_dir = $_SECTION{"file"}) =~ s/\.tar\.(bz2|gz)$//i;
	chdir($_dir) || die "[func: $_sub] $^E \n";
		# alte Bibliotheken löschen

		&progress($_step);
		&status("delete old libs");
		system("rm -rf /usr/local/lib/lib{svn,neon}*");

		my $_configure_opts = join(' ',@{$_SECTION{"configure_opts"}});
		&_make(($_step+1), $_SECTION, "./configure ".$_configure_opts);
		&_make(($_step+2), $_SECTION, "make");
		&_make(($_step+3), $_SECTION, "make install");
		&_make(($_step+4), $_SECTION, "make clean");

	chdir("..");# in basedir


	my $_cmd_output = `cat /etc/group | grep svn`;
	unless( length($_cmd_output) > 0 ){
		&progress( $_step+5);
		&status("add  $_SECTION");
		system("groupadd -r svn");
	}

	$_cmd_output = `cat /etc/passwd | grep svn`;
	unless( length($_cmd_output) > 0 ){
		&progress( $_step+6);
		&status("add user $_SECTION");
		system("useradd -r -g svn svn");
	}
}

#*****************************************************************************
sub _make{
	my ($_step, $_section, $_cmd) = @_;

	&progress($_step);
	&status("$_cmd $_section","wait");
	system($_cmd." ".$_CONF{"log_file"});
	&status("","ok");
}


#*****************************************************************************
sub install_apache{
	my $_step = $_[0];
	my $_SECTION = "APACHE";

	my $_sub = "install_".$_SECTION;
	my %_SECTION = %{$_CONF{ $_SECTION }};

	(my $_dir = $_SECTION{"file"}) =~ s/\.tar\.(bz2|gz)$//i;
	chdir($_dir) || die "[func: $_sub] $^E \n";

		&_make( $_step, $_SECTION, "./buildconf");

		my $_configure_opts = join(' ',@{$_SECTION{"configure_opts"}});
		&_make(($_step+1), $_SECTION, "./configure ".$_configure_opts);
		&_make(($_step+2), $_SECTION, "make");
		&_make(($_step+3), $_SECTION, "make install");
		&_make(($_step+4), $_SECTION, "make clean");

	chdir("..");# in basedir
}

#*****************************************************************************
sub extract_apache{
	&progress($_[0]);
	&extract_pack("APACHE");
}

#*****************************************************************************
sub extract_pack{
	my %_SECTION = %{$_CONF{ $_[0] }};

	my $_file_and_log = $_SECTION{"file"}." ".$_CONF{"log_file"};
	&status("unpack + decompress ".$_SECTION{"file"},"wait");
	if 		( $_SECTION{"file"} =~ /\.tar\.bz2$/i)	{ `tar -xjf $_file_and_log`;}
	elsif	( $_SECTION{"file"} =~ /\.tar\.gz$/i)	{ `tar -xzf $_file_and_log`;}
	else	{ die "\n Filetyp unknown ".$_SECTION{"file"}."\n";}
	&status("","ok");
}

#*****************************************************************************
sub download_apache{
	&progress($_[0]);
	&download_pack("APACHE");
}

#*****************************************************************************
sub download_pack{
	my %_SECTION = %{$_CONF{ $_[0] }};
	my $_exists = (-e $_SECTION{"file"} ) ? "ok" : "no";

	&status("checking if \"".$_SECTION{"file"}."\" exists",$_exists);
	if ( $_exists eq "no" ){
		&status("downloading ".$_SECTION{"file"});
		system("wget ". $_SECTION{"url"} . $_SECTION{"file"});
	}
}

#*****************************************************************************
sub install_db{
	my $_step = $_[0];
	&progress($_step);
	my $_SECTION = "DB";

	my $_sub = "install_".$_SECTION;
	my %_SECTION = %{$_CONF{ $_SECTION }};
	&extract_pack( $_SECTION );

	(my $_dir = $_SECTION{"file"}) =~ s/\.tar\.(bz2|gz)$//i;
	chdir($_dir) || die "[func: $_sub] $^E \n";

	# Wechsle in das build_unix Verzeichnis

	chdir("build_unix") || die "[func: $_sub] $^E \n";

		&_make(($_step+1), $_SECTION, "./configure ".$_configure_opts);
		&_make(($_step+2), $_SECTION, "make");
		&_make(($_step+3), $_SECTION, "make install");
		&_make(($_step+4), $_SECTION, "make clean");

	chdir("..");# in das DB-Dir
	chdir("..");# in basedir

	&progress($_step+5);
	&status("installing DB libs","wait");
	my $_DB_libs = $_SECTION{"libs"};
	my $_cmd_fgrep = `fgrep $_DB_libs /etc/ld.so.conf`;
	chomp($_cmd_fgrep);
	unless( $_cmd_fgrep eq $_DB_libs){
		system("echo $_DB_libs >> /etc/ld.so.conf");
		system("ldconfig");
	}
	&status("","ok");
}

#*****************************************************************************
sub download_db{
	&progress($_[0]);
	&download_pack("DB");
}
#*****************************************************************************
sub autogen_svn{
	&progress($_[0]);
	my $_sub = "autogen_svn";
	(my $_svn_dir = $_CONF{"SVN"}{"file"}) =~ s/\.tar\.(bz2|gz)$//i;
	chdir($_svn_dir) || die "[func: $_sub] $^E \n";
		&status("running \"autogen.sh\" in \"$_svn_dir\"");
		if (-e "apr-util/xml/expat/autom4te.cache"){
			system("rm -r apr-util/xml/expat/autom4te.cache");
		}
		system("./autogen.sh ".$_CONF{"log_file"});
	chdir("..");
}

#*****************************************************************************
sub get_superuser{
	(`id` =~ /uid\=([\d]+)/);
	my $_id = $1;
	if ( $_id > 0){
		&status("change to ROOT and restart Script");
		system("su ");
		exit;
	}
}

#*****************************************************************************
sub extract_svn{
	&progress($_[0]);
	&extract_pack("SVN");
}

#*****************************************************************************
sub check_urls{
	&progress($_[0]);
	print "\n";

	while (($_section,$_vals) = each(%_CONF)){

		if ( exists($_vals->{"url"}) && exists($_vals->{"file"}) ){
			my $_url 	= $_vals->{"url"}.$_vals->{"file"};

			&status("checking url ( ".$_vals->{"file"}." )","wait");

			my $_list = head($_url);

			if ( $_list > 0) {
				&status("","ok");
			}
			else {
				&status("","failed");
				die "please check url: \"$_url\" \n";
			}
		}
	}
}
#*****************************************************************************
sub download_svn{
	&progress($_[0]);
	&download_pack("SVN");
}

#*****************************************************************************
sub progress{
	printf("step %02d/%02d ",$_[0],$_CONF{"STATUS"}{"steps_to_end"});
}

#*****************************************************************************
sub status{
	my ($_text, $_status) = @_;

	my $_length_text 	= ($_CONF{"STATUS"}{"text_length"} > 0) ? $_CONF{"STATUS"}{"text_length"} : length($_text);
	my $_length_status	= length($_status);

	my $_space = $_CONF{"STATUS"}{"max_line_length"} - ( $_length_text + $_length_status);

	print $_text;

	if ( $_status eq "wait" ){
		$_CONF{"STATUS"}{"text_length"} = $_length_text;
	}
	else{
		$_CONF{"STATUS"}{"text_length"} = 0;
		print " "x$_space,$_status."\n";
	}
}
