#!/usr/bin/perl -w
#    $Id: install.pl,v 1.16 2005/07/07 18:44:56 kevinspicer Exp $
#    install.pl - Install script for MailScanner-MRTG
#    Copyright (C) 2003-5 Kevin Spicer <kevin@kevinspicer.co.uk>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program 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 General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#   Please submit all bug reports, patches etc via the sourceforge project 
#   page at http://sourceforge.net/projects/mailscannermrtg
#
#

use Config;
use File::Copy;
use File::Basename;

my (@args, %options, $key, $value, $ans, %files, $version);

%options= (
		"perl" => "auto",
		"prefix" => "/usr",
		"sbin" => "sbin",
		"mrtgcfg" => "/etc/mrtg",
		"msconf" => "/etc/MailScanner",
		"doc" => "share/doc",
		"www" => "/var/www/html",
		"lib" => "lib",
		"unattended" => "n",
		"uptime" => "auto",
		"usesnmp" => "auto",
		"snmpwalk" => "auto",
		"snmp" => "auto",
		"mrtg" => "auto",
		"editor" => "auto",
		"install" => "y",
		"cron" => "d",
		"crontab" => "/var/spool/cron",
		"wwwconf" => "/etc/httpd/conf",
		"man" => "share/man"
		);

if ($^O eq "solaris") {$options{"crontab"} = "/var/spool/cron/crontabs"};

# Check we are in the correct directory by looking for the presence of this
# script...
if (! -e "./install.pl")
{
	die "ERROR: You must cd to the directory containing this script before running it\n";
}

				
# Process command line arguments
@args = split(/--/, join('',@ARGV));

if ( defined $args[0] && length $args[0])
{
	print STDERR "Unrecognised argument $args[0]\n";
	Usage();
}

foreach (@args)
{
	($key, $value) = split(/=/, $_, 2);
	# Discard any leading or trailing blank arguments
	if (! defined $key) { next }
	if ($key =~ /^help$/i)
	{
		Usage();
	}
	if (! exists $options{$key})
	{
		print STDERR "Unrecognised argument --$key\n";
		Usage();
	}
	if (($key eq 'usesnmp' || $key eq 'unattended' || $key eq 'install') && $value !~ /^[yn]$/i)
	{
		print STDERR "$key must be y or n\n";
		Usage();
	}
	if ($key eq 'snmp' && $value !~ /^(ucd)|(net)$/i)
	{
		print STDERR "$key must be ucd or net\n";
		Usage();
	}
	if ($key eq 'cron' && $value !~ /^(d)|(s)|(r)$/i)
	{
		print STDERR "$key must be d, s or r\n";
		Usage();
	}
	$options{$key}=$value;
}


# Now check we have all the prerequisites....
#
# First perl modules...
foreach ("Exporter", "FileHandle", "Fcntl")
{
  eval "use $_;";
  if ($@)
	{
		die "$@\n\nERROR: Required perl module $_ missing, aborting installation.\n\n";
	}
}

# Find location of perl binary
if ($options{'perl'} eq "auto")
{
	if ($Config{'installusrbinperl'}) { $options{'perl'}="/usr/bin" }
	else { $options{'perl'}=$Config{'installbin'} }
}

# Now the ancillary programs...
# Make some sensible additions to the PATH
$ENV{'PATH'}=$ENV{'PATH'} . "/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin";

# uptime
if ($options{'uptime'} eq "auto")
{
  $options{'uptime'} = `which uptime`;
  if ($?)
  {
	  # which command failed
		die "ERROR: Unable to autodetect location of uptime command.\nPlease use the --uptime=/path/to/uptime command line option\n\n";
	}
	chomp ($options{'uptime'});
}
	
# mrtg
if ($options{'mrtg'} eq "auto")
{
  $options{'mrtg'} = `which mrtg`;
  if ($?)
  {
	  # which command failed
		die "ERROR: Unable to autodetect location of mrtg command.\nPlease use the --mrtg=/path/to/mrtg command line option\n\n";
	}
	chomp ($options{'mrtg'});
}

# SNMP
if ($options{'snmpwalk'} eq "auto" && $options{'usesnmp'} !~ /^n/i)
{
  $options{'snmpwalk'} = `which snmpwalk`;
  if ($?)
  {
	  # which command failed, disable SNMP if usesnmp is set to auto
		if ($options{'usesnmp'} eq 'auto')
		{
			$options{'usesnmp'}='n';
		} else {
		  die "ERROR: Unable to autodetect location of snmpwalk command.\nPlease use the --snmpwalk=/path/to/snmp command line option\nOr disable SNMP with --usesnmp=no\n\n";
		}
	} else {
		chomp($options{'snmpwalk'});
		$options{'usesnmp'}='y';
	}
}

# Detect snmp version
if ($options{'snmp'} eq "auto" && $options{'usesnmp'} !~ /^n/i)
{
	$options{'snmp'}=`$options{'snmpwalk'} -V 2>&1`;
  if ($?)
  {
	  # snmpwalk command failed
		die "ERROR: Problem executing snmpwalk -V\nTry setting the path to the snmpwalk command using --snmpwalk=/path/to/snmpwalk\nOr set the smnp version using --snmp=ucd/net\n";
	}
	$options{'snmp'}=lc(substr($options{'snmp'},0,3));
	if ($options{'snmp'} !~ /^(ucd)|(net)$/)
	{
		# Couldn't auto detect snmp version
		die "ERROR: Failed to autodetect SNMP version.\nPlease ensure that you are running net-snmp or ucd-snmp.\nSkip autodetection by setting --snmp=ucd/net\n"
	}
}

# Decide on which editor to use
if ($options{'editor'} eq "auto")
{
	if (defined $ENV{'EDITOR'})
	{
		$options{'editor'}=$ENV{'EDITOR'};
	} else {
    $options{'editor'} = `which vi`;
    if ($?)
    {
  	  # which command failed
  		die "ERROR: Unable to autodetect location of vi editor.\nPlease use the --editor=/path/to/editor command line option\n\n";
  	}
  	chomp ($options{'editor'});
	}
}

# Check cron settings
if ($options{'cron'} =~ /^d/i)
{
	unless (-e "/etc/cron.d") { die "ERROR: /etc/cron.d does not exist\nAborting...\n"}
	unless (-d "/etc/cron.d") { die "ERROR: /etc/cron.d is not a directory\nAborting...\n"}
} elsif ($options{'cron'} =~ /^s/i)
{
	unless (-e "/etc/crontab") { die "ERROR: /etc/crontab does not exist\nAborting...\n"}
	unless (-f "/etc/crontab") { die "ERROR: /etc/crontab is not a file\nAborting...\n"}
} else {
	unless (-e $options{'crontab'}) { die "ERROR: $options{'crontab'} does not exist\nAborting...\n"}
	unless (-d $options{'crontab'}) { die "ERROR: $options{'crontab'} is not a directory\nAborting...\n"}
}

# Check wwwconf settings
unless (-e $options{'wwwconf'}) { die "ERROR: $options{'wwwconf'} does not exist\nAborting...\n"}
unless (-d $options{'wwwconf'}) { die "ERROR: $options{'wwwconf'} is not a directory\nAborting...\n"}
unless (-e "$options{'wwwconf'}/httpd.conf") { die "ERROR: $options{'wwwconf'}/httpd.conf does not exist\nAborting...\n"}

if ($options{'unattended'} !~ /^[Yy]/)
{
  # Print a summary of options...
  print STDERR "\n\nAbout to prepare MailScanner-MRTG using the following options...\n\n";
  print STDERR "For list of command line options run...   ";
  print STDERR "perl install.pl -help\n\n";
  print STDERR "Location of perl:             $options{'perl'}\n";
  print STDERR "Installation Prefix:          $options{'prefix'}\n";
  print STDERR "Program Location:             \${prefix}/$options{'sbin'}\n";
  print STDERR "Libraries Location:           \${prefix}/$options{'lib'}\n";
  print STDERR "Documentation Location:       \${prefix}/$options{'doc'}\n";
  print STDERR "Man pages Location:           \${prefix}/$options{'man'}\n";
  print STDERR "MRTG Config directory:        $options{'mrtgcfg'}\n";
  print STDERR "MailScanner Config directory: $options{'msconf'}\n";
  print STDERR "WWW root:                     $options{'www'}\n";
  print STDERR "Apache configuration dir:     $options{'wwwconf'}\n";
  print STDERR "Location of mrtg:             $options{'mrtg'}\n";
  print STDERR "Location of uptime:           $options{'uptime'}\n";
  print STDERR "Use SNMP:                     $options{'usesnmp'}\n";
  if ($options{'usesnmp'} =~ /^y/i)
  {
    print STDERR "Location of snmpwalk:         $options{'snmpwalk'}\n";
    print STDERR "SNMP version:                 $options{'snmp'}\n";
  }
	if ($options{'cron'} eq "d") {print STDERR "Cron job in cron.d:           /etc/cron.d\n" }
	elsif ($options{'cron'} eq "s") {print STDERR "Cron job in system crontab:   /etc/crontab\n" }
	else {
		print STDERR "Cron job in root user crontab\n";
    print STDERR "Location of root's crontab:   $options{'crontab'}\n";
	}

  if ($options{'install'} =~ /^y/i)
  {
    print STDERR "\nMailScanner-MRTG will be prepared and installed.\n\n";
	} else {
    print STDERR "\nMailScanner-MRTG will be prepared but not installed.\n\n";
	}
	

  print STDERR "Continue with installation? [y/N]: ";
	$ans=<STDIN>;
	if ($ans !~ /^[Yy]/)
	{
		die "\n\nOperation cancelled by user, aborting installation.\n\n";
	}
}

# Now we modify several files
#
modifyMSMRTGFile();
modifyIncludeFile();
modifyConfFile();
modifyCfgFile();
modifyCrondFile();


if ($options{'unattended'} !~ /^[Yy]/)
{
	# Give the user an opportunity to edit the config file

  print STDERR "\n\nBefore continuing with the installation you should review the settings in the\nconfiguration file.\n\nWhen you hit return the configuration file will be opened in your editor.";
	$ans=<STDIN>;
	system($options{'editor'}, "./mailscanner-mrtg.conf");
}
		

# Finished preparing, exit here if we don't want to install
if ($options{'install'} =~ /^n/i)
{
  if ($options{'unattended'} !~ /^[Yy]/)
  {
	  print STDERR "MailScanner-MRTG is now prepared for installation\n";
	}
	exit(0);
}

# Check we are being run as root...
if ($> != 0)
{
	die "ERROR: You must be root to install this program\n";
}

# Remove any old docs
`rm -rf /$options{'prefix'}/$options{'doc'}/mailscanner-mrtg-*`;

# Create the manpage
`pod2man ./mailscanner-mrtg | gzip > ./mailscanner-mrtg.8.gz`;

copy ("./web/htaccess","./web/.htaccess");

# Sort out each of the files to install
# This is a hash, filename as key array as value...
# [ file_location, install_to, UID, GID, mode, parent_dir_UID, parent_dir_GID, parent_dir_mode, backup ]
# The parent dir settings are only applied if the directory is created.
# backup is 1 or 0, indicating whether an existing file with the same name
# should be saved with a .old extenstion

%files = (
	"mailscanner-mrtg" => [ ".", "/$options{'prefix'}/$options{'sbin'}", 0, 0, "755", 0, 0, "755", 0 ],
	"mailscanner-mrtg.cfg" => [ ".", "/$options{'mrtgcfg'}", 0, 0, "644", 0, 0, "755", 1],
	"mailscanner-mrtg.conf" => [ ".", "/$options{'msconf'}", 0, 0, "644", 0, 0, "755", 1],
	"mailscanner-mrtg.thresholds" => [ ".", "/$options{'msconf'}", 0, 0, "644", 0, 0, "755", 1],
	"mailscanner-mrtg.8.gz" => [ ".", "/$options{'prefix'}/$options{'man'}/man8", 0, 0, "644", 0, 0, "755", 1],
	"BUGS" => [ "./docs", "/$options{'prefix'}/$options{'doc'}/mailscanner-mrtg-$version", 0, 0, "644", 0, 0, "755", 0],
	"CHANGELOG" => [ "./docs", "/$options{'prefix'}/$options{'doc'}/mailscanner-mrtg-$version", 0, 0, "644", 0, 0, "755", 0],
	"COPYING" => [ "./docs", "/$options{'prefix'}/$options{'doc'}/mailscanner-mrtg-$version", 0, 0, "644", 0, 0, "755", 0],
	"INSTALL-TARGZ" => [ "./docs", "/$options{'prefix'}/$options{'doc'}/mailscanner-mrtg-$version", 0, 0, "644", 0, 0, "755", 0],
	"README" => [ "./docs", "/$options{'prefix'}/$options{'doc'}/mailscanner-mrtg-$version", 0, 0, "644", 0, 0, "755", 0],
	"README.SNMP" => [ "./docs", "/$options{'prefix'}/$options{'doc'}/mailscanner-mrtg-$version", 0, 0, "644", 0, 0, "755", 0],
	"TODO" => [ "./docs", "/$options{'prefix'}/$options{'doc'}/mailscanner-mrtg-$version", 0, 0, "644", 0, 0, "755", 0],
	"index.html" => [ "./web", "/$options{'www'}/mailscanner-mrtg", 0, 0, "755", 0, 0, "755", 0],
	".htaccess" => [ "./web", "/$options{'www'}/mailscanner-mrtg", 0, 0, "644", 0, 0, "755", 0],
	"mailscanner-mrtg.jpg" => [ "./web", "/$options{'www'}/mailscanner-mrtg", 0, 0, "644", 0, 0, "755", 0],
	"Config.pm" => [ "./lib/MSMRTG", "/$options{'prefix'}/$options{'lib'}/MailScanner-MRTG/MSMRTG", 0, 0, "644", 0, 0, "755", 0],
	"Data.pm" => [ "./lib/MSMRTG", "/$options{'prefix'}/$options{'lib'}/MailScanner-MRTG/MSMRTG", 0, 0, "644", 0, 0, "755", 0],
	"Log.pm" => [ "./lib/MSMRTG", "/$options{'prefix'}/$options{'lib'}/MailScanner-MRTG/MSMRTG", 0, 0, "644", 0, 0, "755", 0],
	"State.pm" => [ "./lib/MSMRTG", "/$options{'prefix'}/$options{'lib'}/MailScanner-MRTG/MSMRTG", 0, 0, "644", 0, 0, "755", 0],
	"Scale.pm" => [ "./lib/MSMRTG", "/$options{'prefix'}/$options{'lib'}/MailScanner-MRTG/MSMRTG", 0, 0, "644", 0, 0, "755", 0],
	"Alarm.pm" => [ "./lib/MSMRTG", "/$options{'prefix'}/$options{'lib'}/MailScanner-MRTG/MSMRTG", 0, 0, "644", 0, 0, "755", 0],
	"Debug.pm" => [ "./lib/MSMRTG", "/$options{'prefix'}/$options{'lib'}/MailScanner-MRTG/MSMRTG", 0, 0, "644", 0, 0, "755", 0]
	);

foreach (keys %files) {
	installFile($_);
}

# We also need to create some directories for mrtg...

foreach (qw(cpu inqueue iptrafficnew loadavg mail mailbytes mailscanner memory outqueue rootusage sendmail spam spoolusage tmpfsusage virus quarantine spamratio virusratio batchsize speed))
{
  if (-e $options{'www'} . "/mailscanner-mrtg/" . $_ )
	{
    if (-d $options{'www'} . "/mailscanner-mrtg/" . $_ ) { next }
	  else { die "ERROR: $options{'www'}/mailscanner-mrtg/$_ is not a directory.\nAborting...\n"}
	}

	CreateDir($options{'www'} . "/mailscanner-mrtg/" . $_ , 0, 0, "755");
}

if ($options{'unattended'} !~ /^[Yy]/)
{
	print STDERR "Please wait whilst initialising MailScanner-MRTG\n";
}

`$options{'prefix'}/$options{'sbin'}/mailscanner-mrtg --notimeout cpu > /dev/null 2>&1`;
`$options{'mrtg'} $options{'mrtgcfg'}/mailscanner-mrtg.cfg > /dev/null 2>&1`;
`$options{'mrtg'} $options{'mrtgcfg'}/mailscanner-mrtg.cfg > /dev/null 2>&1`;
`$options{'mrtg'} $options{'mrtgcfg'}/mailscanner-mrtg.cfg > /dev/null 2>&1`;

# Deal with crontab
InstallCrontab();

# Deal with httpd.conf
AddHttpdConfig();

if (! -e "/etc/init.d/httpd" || ! -x "/etc/init.d/httpd" )
{
	print STDERR "\n##########################################################################\n";
	print STDERR "# Unable to automatically restart httpd - please manually restart Apache #\n";
	print STDERR "##########################################################################\n";
} else {
	`/etc/init.d/httpd restart`
}

if ($options{'unattended'} !~ /^[Yy]/)
{
	print STDERR "Installation completed sucessfully\n";
}


exit(0);

########################
# FUNCTIONS START HERE #
########################

sub Usage
{
	print STDERR "Usage is....\n\n\tperl install.pl OPTIONS\n\nWhere OPTIONS are any of the following...\n\n";
	print STDERR "  Option           Description                                 Default\n";
	print STDERR "  --perl=/path     Absolute path directory containing perl     Autodetected\n";
	print STDERR "  --prefix=/path   Install prefix. default                     /usr\n";
	print STDERR "  --sbin=path      Relative path to install program            sbin\n";
	print STDERR "  --lib=path       Relative path to install libraries          lib\n";
	print STDERR "  --doc=path       Relative path to install documentation      doc\n";
	print STDERR "  --mrtgcfg=/path  Absolute path to mrtg cfg directory         /etc/mrtg\n";
	print STDERR "  --msconf=/path   Absolute path to MailScanner cfg directory. /etc/MailScanner\n";
	print STDERR "  --www=/path      Absolute path to www root.                  /var/www/html\n";
	print STDERR "  --unattended=y/n Install in non-interactive mode             n\n";
	print STDERR "  --mrtg=/path     Absolute path to the mrtg command           Autodetected\n";
	print STDERR "  --uptime=/path   Absolute path to the uptime command         Autodetected\n";
	print STDERR "  --usesnmp=y/n    Whether to use SNMP                         Autodetected\n";
	print STDERR "  --snmpwalk=/path Absolute path to the snmpwalk command       Autodetected\n";
	print STDERR "  --snmp=ucd/net   Whether to use ucd-snmp or net-snmp         Autodetected\n";
	print STDERR "  --editor=/path   Your favourite text editor                  \$EDITOR (or vi)\n";
	print STDERR "  --install=y/n    Whether to install (or just prepare)        y\n";
	print STDERR "  --cron=d/s/r     Install in /etc/cron.d (d) /etc/crontab (s)\n";
	print STDERR "                     or root's crontab (r)                     d\n";
	if ($^O eq "solaris") {
	  print STDERR "  --crontab=/path  Path to crontab directory (if 'r' above)    /var/spool/cron/crontabs\n";
	} else {
	  print STDERR "  --crontab=/path  Path to crontab directory (if 'r' above)    /var/spool/cron\n";
	}
	print STDERR "  --wwwconf=/path  Path to Apache conf directory               /etc/httpd/conf\n";
	print STDERR "  --man=/path      Relative path to Man pages directory        /share/man\n";
	print STDERR "\n";
	exit(1);
}

sub modifyMSMRTGFile
{
	my $perlbin;
	my $libdir;
	my $conffile;
	OpenFiles("mailscanner-mrtg");
	
	$perlbin="/$options{'perl'}/perl";
	$perlbin=~s#/+#/#g;
	$libdir="/$options{'prefix'}/$options{'lib'}/MailScanner-MRTG";
	$libdir=~s#/+#/#g;
	$conffile="/$options{'msconf'}/mailscanner-mrtg.conf";
	$conffile=~s#/+#/#g;
	$thresfile="/$options{'msconf'}/mailscanner-mrtg.thresholds";
	$thresfile=~s#/+#/#g;

	while (<OLD>)
	{
		if (/^#!\/.*\/perl -w$/) { print NEW "#!$perlbin -w\n" }
		elsif (/^use lib ".*";/) { print NEW "use lib \"$libdir\";\n" }
		elsif (/^\$configfile\s*=\s*".*";/) { print NEW "\$configfile = \"$conffile\";\n" }
		elsif (/^\$thresholdfile\s*=\s*".*";/) { print NEW "\$thresholdfile = \"$thresfile\";\n" }
		elsif (/^\$version\s*=\s*"(.*)";/) { print NEW $_ ; $version=$1 }
		else { print NEW $_ }
	}
	
	CloseAndReplace("mailscanner-mrtg");
	

}
sub modifyIncludeFile
{
	my $wwwdir;

	OpenFiles("mailscanner-mrtg.include");
	
	$wwwdir="/$options{'www'}/mailscanner-mrtg/";
	$wwwdir=~s#/+#/#g;

  while (<OLD>)
	{
		if (/^Alias \/mailscanner-mrtg ".*"/) { print NEW "Alias \/mailscanner-mrtg \"$wwwdir\"\n" }
		else { print NEW $_ }
	}
	CloseAndReplace("mailscanner-mrtg.include");
}
sub modifyConfFile
{
	my $uptime;
	my $statefile;
	my $usesnmp = "no";
	my $snmp = 0;
	my $snmpwalk;

	OpenFiles("mailscanner-mrtg.conf");
	
	$uptime="/$options{'uptime'}";
	$uptime=~s#/+#/#g;
	$statefile="/$options{'www'}/mailscanner-mrtg/state.info";
	$statefile=~s#/+#/#g;
	$wwwroot="/$options{'www'}";
	$wwwroot=~s#/+#/#g;
	if ($options{'usesnmp'} =~ /^y/i) { 
		$usesnmp="yes";
		$snmp=1;
	}
	$snmpwalk="/$options{'snmpwalk'}";
	$snmpwalk=~s#/+#/#g;
	

  while (<OLD>)
	{
		if (/^Uptime Command\s*=/) { print NEW "Uptime Command = $uptime\n" }
		elsif (/^State File\s*=/) { print NEW "State File = $statefile\n" }
		elsif (/^WWW Root\s*=/) { print NEW "WWW Root = $wwwroot\n" }
		elsif (/^Use SNMP\s*=/) { print NEW "Use SNMP = $usesnmp\n" }
		elsif ($snmp && /^SNMP version\s*=/) { print NEW "SNMP version = $options{'snmp'}\n" }
		elsif ($snmp && /^Snmpwalk Binary\s*=/) { print NEW "Snmpwalk Binary = $snmpwalk\n" }
		else { print NEW $_ }
	}
	CloseAndReplace("mailscanner-mrtg.conf");

}
sub modifyCfgFile
{
	my $wwwdir;
	my $mrtg;

	OpenFiles("mailscanner-mrtg.cfg");
	
	$wwwdir="/$options{'www'}/mailscanner-mrtg/";
	$wwwdir=~s#/+#/#g;
	$msmrtg="/$options{'prefix'}/$options{'sbin'}/mailscanner-mrtg";
	$msmrtg=~s#/+#/#g;

  while (<OLD>)
	{
		if (/^Workdir: /) { print NEW "WorkDir: $wwwdir\n" }
		elsif (/^Target\[(\w+)\]: `\S+ (\w+)`/) { print NEW "Target[$1]: `$msmrtg $2`\n" }
		else { print NEW $_ }
	}

	CloseAndReplace("mailscanner-mrtg.cfg");

}
sub modifyCrondFile
{
	my $mrtg;
	my $cfgfile;

	OpenFiles("mailscanner-mrtg.crond");
	
	$mrtg="/$options{'mrtg'}";
	$mrtg=~s#/+#/#g;
	$cfgfile="/$options{'mrtgcfg'}/mailscanner-mrtg.cfg";
	$cfgfile=~s#/+#/#g;

  while (<OLD>)
	{
		if (/0-59\/5 \* \* \* \* root/) { print NEW "0,5,10,15,20,25,30,35,40,45,50,55 * * * * root $mrtg $cfgfile\n" }
		else { print NEW $_ }
	}
	CloseAndReplace("mailscanner-mrtg.crond");

}
sub OpenFiles
{
	open (OLD, "<$_[0]") or die "Can't open $_[0]: $!";
	open (NEW, ">$_[0].new") or die "Can't create $_[0].new: $!";
}
sub CloseAndReplace
{
	close (OLD);
	close (NEW);
	unlink ($_[0]) or die "ERROR: Couldn't remove unmodified $_[0]: $!";
	move ("$_[0].new", $_[0]) or die "ERROR: Couldn't rename modified file $_[0].new: $!";
}
sub installFile
{
	my $file=shift;
	my $copyfrom=$files{$file}[0] . "/" . $file;
	my $copyto=$files{$file}[1] . "/" . $file;

	unless (-e $files{$file}[1]) { CreateDir($files{$file}[1], $files{$file}[5], $files{$file}[6], $files{$file}[7]) }
	unless (-d $files{$file}[1]) { die "ERROR: " . $files{$file}[1] . " is not a directory. Aborting...\n"}

	if (-e $copyto)
	{
		if ($files{$file}[8])
		{
      move($copyto, $copyto . ".new") or die "ERROR: Couldn't backup existing $file:$!\nAborting...\n";
		} else {
      unlink($copyto) or die "ERROR: Couldn't delete existing $file: $!\nAborting...\n";
		}
	}

	copy($copyfrom, $copyto) or die "ERROR: Couldn't copy file $file: $!\nAborting...\n";
	chown($files{$file}[2], $files{$file}[3], $copyto) or die "ERROR: Couldn't chown $file: $!\nAborting...\n";
	chmod(oct $files{$file}[4], $copyto) or die "ERROR: Couldn't chmod $file: $!\nAQborting...\n";
}

sub CreateDir
{
	my $dir=shift;
  my $owner=shift;
	my $group=shift;
	my $mode=shift;

	$parentdir= dirname($dir);

	unless (-e $parentdir) { CreateDir($parentdir, $owner, $group, $mode) }

	unless (-d $parentdir) { die "ERROR: $parentdir is not a directory.\nAborting\n\n" }

	mkdir($dir, oct $mode) or die "ERROR: Problem creating directory $dir: $!\nAborting...\n";
	chown($owner, $group, $dir) or die "ERROR: Couldn't chown $dir: $!\nAborting...\n";
	chmod(oct $mode, $dir) or die "ERROR: Couldn't chmod $dir: $!\nAborting...\n";
	
}

sub InstallCrontab
{
	if ($options{'cron'} =~ /^d/i)
	{
		# Install in the cron.d directory
	  $files{"mailscanner-mrtg.crond"} = [ ".", "/etc/cron.d", 0, 0, "644", 0, 0, "755", 0];
	  installFile("mailscanner-mrtg.crond");
	}
	elsif ($options{'cron'} =~ /^s/i)
	{
		# Add line to the system crontab
		AddCronLine("/etc/crontab", 1);
	}
	else
	{
		# Add line to root crontab
		AddCronLine("$options{'crontab'}/root", 0);
	}
}

sub AddCronLine
{
	# Adds a line to a crontab
	# first argument is the file
	# second argument is whether to include a username (system crontab)
	#
	my $file=shift;
	my $includeuser=shift;
	my ($mrtg, $cfgfile, $line);
	my $found=0;
	
	$mrtg="/$options{'mrtg'}";
	$mrtg=~s#/+#/#g;
	$cfgfile="/$options{'mrtgcfg'}/mailscanner-mrtg.cfg";
	$cfgfile=~s#/+#/#g;

	if ($includeuser==1) { $line="0,5,10,15,20,25,30,35,40,45,50,55 * * * * root $mrtg $cfgfile\n" }
	else { $line="0,5,10,15,20,25,30,35,40,45,50,55 * * * * $mrtg $cfgfile\n" }

	OpenFiles($file);

	while (<OLD>)
	{
		if (/^.*mailscanner-mrtg.cfg/) { 
			print NEW $line;
			$found=1;
		}
		else { print NEW $_ }
	}

	unless ($found) { print NEW $line }

	CloseAndReplace($file);
}
sub AddHttpdConfig
{
	# Installs the httpd include file and adds a line to httpd.conf
	#
	my $found=0;
	my $line="Include $options{'wwwconf'}/mailscanner-mrtg.include\n"; 

	$files{"mailscanner-mrtg.include"} = [ ".", $options{'wwwconf'}, 0, 0, "644", 0, 0, "755", 0];
	installFile("mailscanner-mrtg.include");
	
	OpenFiles("$options{'wwwconf'}/httpd.conf");

	while (<OLD>)
	{
		if (/^Include.*mailscanner-mrtg.include/) { 
			print NEW $line;
			$found=1;
		}
		else { print NEW $_ }
	}

	unless ($found) { print NEW $line }

	CloseAndReplace("$options{'wwwconf'}/httpd.conf");
}


syntax highlighted by Code2HTML, v. 0.9.1