#!/usr/bin/perl
use strict;
my $version = "3.0.5";

=head1 NAME

	toaster_setup.pl - Everything you need to build a mail toaster except a computer

=head1 SYNOPSIS

	To build a great mail system, install FreeBSD 4.8 (or latest stable), download
	this script and then follow the directions on the toaster page (see URL below).

=head1 DESCRIPTION

=cut

##
# Personal Preferences - alter these if you know what you're doing
#                        (beginners should leave them alone).
##
# -------------------------------------------------------------------------------------

my $src       = "/usr/local/src";            # where we want to store our sources
my $qmaildir  = "/var/qmail";                # where qmail is installed
my $supervise = "$qmaildir/supervise";       # where supervised control files live
my $vpopdir   = "/usr/local/vpopmail";       # where vpopmail is installed
my $confdir   = "/usr/local/etc";            # where config files are stored
my $service   = "/service";                  # the control directory for svscan
# -------------------------------------------------------------------------------------
#  $service is where you store symlinks to your services for easy managability. I
#  like mine in /service. It's the default location and it makes it very convenient to 
#  restart a supervised program like dnscache (svc -t /service/dnscache).
my $httpdir   = "/usr/local/www";
my $dl_site   = "http://matt.simerson.net";
# -------------------------------------------------------------------------------------
#  The download site automatically grabs the tarballs from djb's web site. If you don't 
#  like that, download them yourself and place them in $src.
# -------------------------------------------------------------------------------------
my $toaster   = "$dl_site/computing/mail/toaster";
my $osrel     = "4-stable";                  # set this to FreeBSD's latest release
my $pk_site   = "ftp://ftp.freebsd.org";     # which server to get packages from
my $pk_url    = "$pk_site/pub/FreeBSD/ports/i386/packages-$osrel/Latest/";


######################################################################
#            Do not modify anything below this line                  #
######################################################################

use File::Copy;
use File::Path;
use Getopt::Long;
use MATT::Utility;
use MATT::FreeBSD;

$| = 1;
my $user = (getpwuid ($<))[0];
if ( $user ne "root") { die "Thou shalt have root to proceed!\n"; };

my %options = (
	'action=s'    => \my $action,
	'secti=s'     => \my $section,
	'host=s'      => \my $host,
	'user=s'      => \my $postmaster,
	'debug=s'     => \my $debug
);
GetOptions (%options);

if ( !$action  ) { $action = "install"; };
if ( !$section ) { die "usage: $0 -s pre -v\n"; };

my $tar      = FindTheBin("tar");
my $grep     = FindTheBin("grep");
my $pkg_info = FindTheBin("pkg_info");

if    ( $section eq "pre"        ) { InstallToasterDependencies();           } 
elsif ( $section eq "qmail"      ) { InstallQmail("qmail-1.03");             } 
elsif ( $section eq "ucspi"      ) { InstallUCSPI();                         } 
elsif ( $section eq "courier"    ) { InstallCourier("courier-imap-1.7.0");   } 
#elsif ( $section eq "courier"    ) { InstallCourier("courier-imap-2.0.0");   } 
elsif ( $section eq "ezmlm"      ) { InstallEzmlm();                         } 
elsif ( $section eq "apache"     ) { InstallApache($section);                } 
elsif ( $section eq "apache1"    ) { InstallApache($section);                } 
elsif ( $section eq "apache2"    ) { InstallApache($section);                } 
elsif ( $section eq "mysql"      ) { InstallMysql();                         } 
elsif ( $section eq "mysqltool"  ) { InstallMysqlTool("MysqlTool-0.94");     } 
elsif ( $section eq "vpopmail"   ) { InstallVpopmail("vpopmail-5.3.20");     }
elsif ( $section eq "vpeconfig"  ) { ConfigVpopmailEtc("$vpopdir/etc");      }
elsif ( $section eq "qmailadmin" ) { InstallQmailadmin("qmailadmin-1.0.21"); } 
elsif ( $section eq "sqwebmail"  ) { InstallSqwebmail("sqwebmail-3.5.0");    } 
elsif ( $section eq "squirrelmail"){ InstallSquirrelmail();                  } 
elsif ( $section eq "supervise"  ) { InstallSupervise();                     }
elsif ( $section eq "socklog"    ) { InstallSocklog();                       }
elsif ( $section eq "filter"     ) { InstallFilter();                        }
elsif ( $section eq "clamav"     ) { InstallClamAV();                        }
elsif ( $section eq "maillogs"   ) { InstallMailLogs();                      }
elsif ( $section eq "test"       ) { ConfigureSuperviseFile("smtp");  };

print "\n$0 script execution complete.\n";

exit 1;

##
# Helper Subroutines
##

sub InstallApache
{
	my ($ver) = @_;

	use MATT::Apache;
	
	if    ( lc($ver) eq "apache" or lc($ver) eq "apache1" ) { InstallApache1($src); } 
	elsif ( lc($ver) eq "apache2") { InstallApache2();     };
};

sub InstallVpopmail 
{
	my ($package)  = @_;
	my ($ans, $ddom, $ddb, $cflags, $my_write);

	my $site       = "http://www.inter7.com/devel";

	use MATT::Passwd;
	InstallGroup  ("vchkpw", "89");
	InstallUser   ("vpopmail", "", $vpopdir);

	ConfigVpopmailEtc("$vpopdir/etc");

	my $conf_args = "--enable-mysql=y ";
	$conf_args    = $conf_args . " --enable-rebuild-tcpserver-file=n";
	$conf_args    = $conf_args . " --enable-defaultquota=100000000S,10000C";
	$conf_args    = $conf_args . " --enable-roaming-users=y";

	CdSrcDir("$src/mail");

	if ( !-e "$package.tar.gz" ) {
		FetchFile("$site/$package.tar.gz");
	};

	if ( -d $package )
	{
		my $r = SourceWarning($package, 1);
		if (! $r) { die "sorry, I can't continue.\n"; };
	};
	SysCmd( "$tar -xzf $package.tar.gz");

	$ans = YesOrNo("Do you want password learning? (y) ");
	if ($ans) 
	{
		$conf_args    = $conf_args . " --enable-learn-passwords=y";
	};

	$ans = YesOrNo("Do you want logging enabled? (y) ");
	if ($ans) 
	{
		my $a2 = YesOrNo("Do you want verbose logging? (y) ");
		if ($a2) 
		{
			$conf_args    = $conf_args . " --enable-logging=v";
		} else {
			$conf_args    = $conf_args . " --enable-logging=p";
		};
	} else {
		$conf_args    = $conf_args . " --enable-logging=p";
	};

	$ans = YesOrNo("Do you want to use a default domain? ");
	if ($ans) 
	{
		my $ddom = GetAnswer("your default domain");
		$conf_args = $conf_args . " --enable-default-domain=$ddom";
	};

	print "\t\t CAUTION!!  CAUTION!!

The system users account is NOT comptible with qmail-smtpd-chkusr.
If you selected that option in the qmail build, you should not answer
yes here. If you are unsure, select (n).
";
	$ans = YesOrNo("Do system users (/etc/passwd) get mail? (n) ");
	if ($ans) { $conf_args  = $conf_args . " --enable-passwd"; };
 	
	$ans = YesOrNo("Do you use valias processing? (n) ");
	if ($ans) { $conf_args  = $conf_args . " --enable-valias=y"; };
 	
	$ans = YesOrNo("Do you want mysql logging? (n) ");
	if ($ans) { $conf_args  = $conf_args . " --enable-mysql-logging=y"; };

	$ans = YesOrNo("Do you want qmail extensions? (n) ");
	if ($ans) { $conf_args  = $conf_args . " --enable-qmail-ext=y"; };

	print "Qmailadmin supports limits via a .qmailadmin-limits file. It can\n";
	print "also get these limits from a MySQL table. ";
	$ans = YesOrNo("Do you want mysql limits? (n) ");
	if ($ans) { $conf_args  = $conf_args . " --enable-mysql-limits=y"; };

	my $mysql_repl = YesOrNo("Do you want mysql replication enabled? (n) ");
	if ($mysql_repl) 
	{
		$conf_args = $conf_args . " --enable-mysql-replication=y";
		if ($ddom) { $ddb = "db.$ddom"; } else { $ddb = "db"; };
		$my_write = GetAnswer("your MySQL master servers hostname", $ddb);
	};

	my $my_read = GetAnswer("your MySQL read server hostname", "localhost");
	my $my_user = GetAnswer("your MySQL user name", "vpopmail");
	my $my_pass = GetAnswer("your MySQL password");

	$ans = YesOrNo("Do you want vpopmail's domain quotas? (n) ");
	if ($ans) { $conf_args  = $conf_args . " --enable-domainquotas=y"; };

	chdir($package);
	SetupVmysql($mysql_repl, $my_write, $my_read, $my_user, $my_pass);
	print "running configure with $conf_args\n\n";
	SysCmd( "./configure $conf_args");
	SysCmd( "make");
	SysCmd( "make install-strip");
	SysCmd( "cp vlimits.h $vpopdir/include/");
};

sub SetupVmysql 
{
	my ($mysql_repl, $my_write, $my_read, $my_user, $my_pass) = @_;

	copy("vmysql.h", "vmysql.h.orig");
	my @lines = ReadFile("vmysql.h");

	foreach my $line (@lines) {
		chomp $line;
		if      ( $line =~ /^#define MYSQL_UPDATE_SERVER/ ) {
			if ($mysql_repl) {
				$line = "#define MYSQL_UPDATE_SERVER \"$my_write\"";
			} else {
				$line = "#define MYSQL_UPDATE_SERVER \"$my_read\"";
			};
		} elsif ( $line =~ /^#define MYSQL_UPDATE_USER/ ) {
			$line = "#define MYSQL_UPDATE_USER   \"$my_user\"";
		} elsif ( $line =~ /^#define MYSQL_UPDATE_PASSWD/ ) {
			$line = "#define MYSQL_UPDATE_PASSWD \"$my_pass\"";
		} elsif ( $line =~ /^#define MYSQL_READ_SERVER/ ) {
			$line = "#define MYSQL_READ_SERVER   \"$my_read\"";
		} elsif ( $line =~ /^#define MYSQL_READ_USER/ ) {
			$line = "#define MYSQL_READ_USER     \"$my_user\"";
		} elsif ( $line =~ /^#define MYSQL_READ_PASSWD/ ) {
			$line = "#define MYSQL_READ_PASSWD   \"$my_pass\"";
		};
	};
	WriteFile("vmysql.h", @lines);
};

sub InstallSquirrelmail 
{
	InstallPort("squirrelmail", "mail");
};

sub InstallMailLogs 
{
	my $log = "/var/log/mail";
	my $uid = getpwnam("qmaill");
	my $gid = getgrnam("qnofiles");

	CreateSuperviseDirs();

	InstallQmailControl("send");
	InstallQmailControl("smtp");
	InstallQmailControl("pop3");

	if ( !-d $log ) 
	{ 
		print "InstallMailLogs: creating $log\n";
		mkdir($log, 0755) or die "couldn't create $log: $!";
		chown($uid, $gid, $log) or die;
	};

	foreach my $prot ( qw/ send smtp pop3 / )
	{
		if ( ! -d "$log/$prot" ) {
			print "InstallMailLogs: creating $log/$prot\n";
			mkdir("$log/$prot", 0755) or die "couldn't create: $!";
		} else {
			print "InstallMailLogs: $log/$prot exists\n";
		};
		chown($uid, $gid, "$log/$prot") or die;
	};
};

sub InstallQmailControl 
{
	my ($serv)  = @_;
	my $run_f   = "$supervise/$serv/log/run";

	if ( !-s $run_f ) 
	{
		print "InstallQmailControl: creating file $run_f\n";
		open(RUN, ">$run_f") or die "couldn't open for write: $!";
		print RUN "#!/bin/sh\n";
		print RUN "PATH=/var/qmail/bin:/usr/local/bin:/usr/bin:/bin\n";
		print RUN "export PATH\n";

		if ($serv eq "smtp") {
			print RUN "exec setuidgid qmaill multilog t !./smtplog s100000 /var/log/mail/smtp\n";
		} elsif ( $serv eq "send") {
			print RUN "exec setuidgid qmaill multilog t !./sendlog s100000 /var/log/mail/send\n";
		} elsif ( $serv eq "pop3") {
			print RUN "exec setuidgid qmaill multilog t !./pop3log s100000 /var/log/mail/pop3\n";
		};
		close RUN;
		chmod(0755, $run_f);
	} else {
		print "InstallQmailControl: $run_f already exists.\n";
	};
};

sub InstallSocklog 
{
	my $log = "/var/log/mail";
	my $uid = getpwnam("bin");
	my $gid = getgrnam("bin");

	InstallPort("socklog", "sysutils");
	InstallSocklogQmailControl("send");
	InstallSocklogQmailControl("smtp");
	InstallSocklogQmailControl("pop3");

	if ( !-d $log ) 
	{ 
		mkdir($log, 0755) or die "couldn't create $log: $!";
		chown($uid, $gid, $log) or die;
	};

	foreach my $prot ( qw/ send smtp pop3 / )
	{
		mkdir("$log/$prot", 0755) or die "couldn't create: $!";
		chown($uid, $gid, "$log/$prot") or die;
	};
};

sub InstallSocklogQmailControl 
{
	my ($serv)  = @_;
	my $run_f   = "$supervise/$serv/log/run";

	if ( !-s $run_f ) 
	{
		open(RUN, ">$run_f") or die "couldn't open for write: $!";
		print RUN "#!/bin/sh\n";
		print RUN "LOGDIR=/var/log/mail\n";
		print RUN "LOGSERVERIP=192.168.0.8\n";
		print RUN "PORT=10116\n";
		print RUN "PATH=/var/qmail/bin:/usr/local/bin:/usr/bin:/bin\n";
		print RUN "export PATH\n";
		print RUN "exec setuidgid bin multilog t s4096 n20 \\\n";
		print RUN "  !\"tryto -pv tcpclient -v \$LOGSERVERIP \$PORT sh -c 'cat >&7'\" \\\n";
		print RUN "  \${LOGDIR}/$serv\n";
		close RUN;
	};
};

sub InstallFilter 
{
	InstallPort ("maildrop",             "mail"      );
	InstallPort ("procmail",             "mail"      );
	InstallPort ("p5-Time-HiRes",        "devel"     );
	InstallPort ("tnef",                 "converters");
	InstallPort ("unzip",                "archivers" );
	InstallPort ("p5-Mail-SpamAssassin", "mail"      );
	InstallClamAV();
	InstallQmailScanner();
	InstallMaildropFiles();
};

sub InstallMaildropFiles
{
	my $filterfile = "/usr/local/etc/mail/mailfilter";

	if ( ! -e $filterfile ) 
	{
		FetchFile("$toaster/etc/mailfilter-site");
		move("mailfilter-site", $filterfile);
		chmod(0600, $filterfile);
		my $uid = getpwnam("vpopmail");
		my $gid = getgrnam("vchkpw");
		chown($uid, $gid, $filterfile) or die;
	};

	my $imap = "/usr/local/sbin/subscribeIMAP.sh";
	if ( ! -e $imap )
	{
		FetchFile("$toaster/etc/subscribeIMAP.sh");
		move("subscribeIMAP.sh", $imap);
		chmod(0555, $imap);
	};
};

sub ConfigSpamAssassin
{
	print	"Visit http://www.yrex.com/spam/spamconfig.php ";
};

sub ConfigQmailScanner
{
	# We want qmailscanner to process emails so we add and ENV to the SMTP server:
	print "To enable qmaail-scanner, add this to your $service/smtp/run file:
\n
QMAILQUEUE=\"/var/qmail/bin/qmail-scanner-queue.pl\"
 export QMAILQUEUE\n\n
";

};

sub InstallQmailScanner
{
	my $package    = "qmail-scanner-1.16";
	my $site       = "http://download.sourceforge.net/qmail-scanner";
	#my $site       = "http://aleron.dl.sourceforge.net/sourceforge/qmail-scanner/";

	if ( -e "/var/qmail/bin/qmail-scanner-queue.pl") {
		print "QmailScanner is already Installed!\n";
		return;
	};

	CdSrcDir("$src/mail/filter");

	if ( ! -e "$package.tgz" ) 
	{
		FetchFile("$site/$package.tgz");
	};

	if ( -d $package )
	{
		my $r = SourceWarning($package, 1);
		if (! $r) { die "sorry, I can't continue.\n"; };
	};

	SysCmd("$tar -xzf $package.tgz");
	chdir($package);

	my $confcmd = "./configure ";

	my $user = GetAnswer("What username will receive postmaster mail?");
	my $dom  = GetAnswer("What domain will receive postmaster mail?");

	my $confcmd = $confcmd . " --admin $user --domain $dom ";

	my $clam = YesOrNo("Do you want ClamAV enabled?");
	my $spam = YesOrNo("Do you want SpamAssassin enabled?");
	my $verb = YesOrNo("Do you want SA verbose logging (n)?");

	if ( $clam && $spam && $verb ) {
		$confcmd = $confcmd . "--scanners verbose_spamassassin,clamscan ";
	} elsif ( $clam && $spam ) {
		$confcmd = $confcmd . "--scanners fast_spamassassin,clamscan ";
	} elsif ( $clam ) {
		$confcmd = $confcmd . "--scanners clamscan ";
	} elsif ( $spam ) {
		$confcmd = $confcmd . "--scanners fast_spamassassin ";
	} else {
		die "No scanners?";
	};

	print "OK, running qmail-scanner configure to test options.\n";
	SysCmd( $confcmd );

	my $ans = YesOrNo("OK, ready to install it now?");
	if ($ans) { SysCmd( $confcmd . "--install" ); };

	ConfigQmailScanner();
};

sub InstallClamAV
{
	use MATT::Passwd;

	InstallGroup("clamav");
	InstallUser ("clamav");
	InstallPort ("clamav",               "security"  );

	my $uid = getpwnam("clamav");
	my $gid = getgrnam("clamav");
	chown($uid, $gid, "/usr/local/share/clamav") or die;
	chown($uid, $gid, "/usr/local/share/clamav/viruses.db") or die;
	chown($uid, $gid, "/usr/local/share/clamav/viruses.db2") or die;

	my $run_f   = "$confdir/rc.d/clamav.sh";

	if ( !-s $run_f ) 
	{
		print "Creating $confdir/rc.d/clamav.sh startup file.\n";
		open(RUN, ">$run_f") or die "couldn't open for write: $!";

		print RUN <<EORUN
#!/bin/sh

case "\$1" in
    start)
        /usr/local/bin/freshclam -d -c 2 -l /var/log/freshclam.log
        echo -n ' freshclam'
        ;;

    stop)
        /usr/bin/killall freshclam > /dev/null 2>&1
        echo -n ' freshclam'
        ;;

    *)
        echo ""
        echo "Usage: `basename \$0` { start | stop }"
        echo ""
        exit 64
        ;;
esac
EORUN
;
		chmod(0755, "$confdir/rc.d/clamav.sh");
	};

	my $logfile = "/var/log/freshclam.log";
	if ( !-e $logfile )
	{
		SysCmd("touch $logfile");
		chmod(0644, $logfile);
		chown($uid, $gid, $logfile);
	};

	my $freshclam = FindTheBin("freshclam");
	SysCmd("$freshclam --verbose");
};

sub InstallToasterDependencies 
{
	InstallPackage("ispell");
	InstallPackage("gdbm");
	InstallPackage("setquota");
	InstallPackage("autoconf");
	InstallPackage("automake");
	InstallPackage("expect");
	InstallPackage("gnupg");
	InstallPackage("maildrop");
	InstallPackage("mysql-client");
	InstallPort   ("autorespond",   "mail");
	InstallPort   ("qmail",         "mail");
	InstallPort   ("qmailanalog",   "mail");
	InstallPort   ("daemontools",   "sysutils");
	InstallPackage("openldap2");
	InstallPort   ("openldap2",     "net", "openldap21");
	InstallPort   ("p5-Compress-Zlib", "archivers");
	InstallPort   ("p5-Crypt-PasswdMD5", "security");
};

sub InstallCourier 
{
	my ($package)  = @_;
	my $site       = "http://download.sourceforge.net/courier";

	CdSrcDir("$src/mail");

	if ( ! -e "$package.tar" ) 
	{
		FetchFile("$site/$package.tar.bz2");
	};

	if ( -d $package )
	{
		my $r = SourceWarning($package, 1);
		if (! $r) { die "sorry, I can't continue.\n"; };
	};

	SysCmd("bunzip2 $package.tar.bz2");
	SysCmd("$tar -xf $package.tar");
	chdir($package);
	$ENV{"HAVE_OPEN_SMTP_RELAY"} = 1;
	SysCmd( "./configure --prefix=/usr/local --exec-prefix=/usr/local --without-authldap --without-authshadow --with-authvchkpw --without-authcram --sysconfdir=/usr/local/etc/courier-imap --datadir=/usr/local/share/courier-imap --libexecdir=/usr/local/libexec/courier-imap --enable-workarounds-for-imap-client-bugs --disable-root-check --without-authdaemon");

	SysCmd( "make");
	SysCmd( "make install");
	ConfigCourier();
};

sub SourceWarning 
{
	my ($package, $clean) = @_;
	print "\n$package sources are already present, indicating that you've already\n";
	print "installed $package. If you want to reinstall it, remove the existing\n";
	print "sources (rm -r $src/mail/$package) and re-run this script\n\n";

	if ($clean) {
		my $answer = YesOrNo("\n\tWould you like me to remove the sources for you? ");
		if ($answer) {
			print "Deleting $package...";
			rmtree $package;
			print "done.\n";
			return 1;
		} else {
			return 0;
		};
	};
};

sub InstallSqwebmail 
{
	my ($package)  = @_;
	my $site     = "http://download.sourceforge.net/courier";
	my $cgi      = "$httpdir/cgi-bin";

	CdSrcDir("$src/mail");

	if ( -d "$package" )
	{
		my $r = SourceWarning($package, 1);
		if (! $r) { die "sorry, I can't continue.\n"; };
	};

	if ($package = "sqwebmail-3.5.0") {
		if ( !-e "$package.tar" ) {
			FetchFile("$site/$package.tar.bz2");
			SysCmd("bunzip2  $package.tar.bz2");
		};
		SysCmd("$tar -xf $package.tar");
	} else {
		if ( !-e "$package.tar.gz" ) {
			FetchFile("$site/$package.tar.gz");
		};
		SysCmd("$tar -xzf $package.tar.gz");
	};

	chdir($package);

	my $datadir;
	if  ( -d "$httpdir/data/mail") 
	{
		$datadir = "$httpdir/data/mail";
	} else {
		$datadir = "$httpdir/data";
	};

	my $mime = "";

	if ( -e "/usr/local/etc/apache2/mime.types" ) {
		$mime = "--enable-mimetypes=/usr/local/etc/apache2/mime.types";
	} elsif ( -e "/usr/local/etc/apache/mime.types" ) {
		$mime = "--enable-mimetypes=/usr/local/etc/apache/mime.types";
	};
		
	SysCmd( "./configure --with-cachedir=/var/run/sqwebmail --enable-webpass=vpopmail --with-module=authvchkpw --enable-https --enable-logincache --enable-imagedir=$datadir/webmail --without-authdaemon $mime");
	SysCmd( "make configure-check");
	SysCmd( "make check");
	SysCmd( "make");

	my $share = "/usr/local/share/sqwebmail";
	if (-d $share) {
		SysCmd( "make install-exec");
		print "\n\nWARNING: I have only installed the $package binaries, thus\n";
		print "preserving any custom settings you might have in $share.\n";
		print "If you wish to do a full install, overwriting any customizations\n";
		print "you might have, then do this:\n\n";
		print "\tcd $src/mail/$package; make install\n";
	} else {
		SysCmd( "make install");
		chmod(0755, $share);
		chmod(0755, "$datadir/sqwebmail");
		copy("$share/ldapaddressbook.dist", "$share/ldapaddressbook") or die "copy failed: $!";
	};

	my $var = "/var/run/sqwebmail";
	if (!-e $var) {
		my $uid = getpwnam("bin");
		my $gid = getgrnam("bin");
		mkdir($var, 0755);
		chown($uid, $gid, $var);
	};
};

sub InstallQmailadmin
{
	my ($package)  = @_;
	my ($answer, $helpdir);

	my $patch      = 0;
	#my $patch      = "$package-patch.txt";
	my $cgi        = "$httpdir/cgi-bin";
	my $site       = "http://aleron.dl.sourceforge.net/sourceforge/qmailadmin";
	#my $site       = "http://www.inter7.com/devel";
	my $help       = "qmailadmin-help-1.0.8";

	CdSrcDir("$src/mail");

	if ( !-e "$package.tar.gz" ) 
	{
		FetchFile("$site/$package.tar.gz");
	};

	my $conf_args = " --enable-domain-autofill=Y";

	$answer = YesOrNo("\nDo you want spam options? ");
	if ($answer) { 
		$conf_args = $conf_args . " --enable-modify-spam=Y" .
		" --enable-spam-command=\"| /usr/local/bin/maildrop /usr/local/etc/mail/mailfilter\"";
	};

	$answer = YesOrNo("\nDo you want user quotas to be modifiable? ");
	if ($answer) { $conf_args = $conf_args . " --enable-modify-quota=y"; };

	$answer = YesOrNo("\nShould qmailadmin be installed as root? ");
	if ($answer) { $conf_args = $conf_args . " --enable-vpopuser=root"; };

	if ( -d "$httpdir/cgi-bin.mail") 
	{
		$conf_args = $conf_args . " --enable-cgibindir=$httpdir/cgi-bin.mail";
	} else {
		$conf_args = $conf_args . " --enable-cgibindir=$cgi";
	};

	if ( $patch && !-e $patch ) { FetchFile("$toaster/$patch"); };

	if ( -d "$package" )
	{
		my $r = SourceWarning($package, 1);
		if (! $r) { die "sorry, I can't continue.\n"; };
	};

	SysCmd("$tar -xzf $package.tar.gz");
	chdir($package);
	SysCmd("patch < ../$patch") if ($patch);
	print "running configure with $conf_args\n\n";
	SysCmd("./configure $conf_args");
	SysCmd("make");
	SysCmd("make install-strip");

	$answer = YesOrNo("Would you like help links on the qmailadmin login page? ");
	if ($answer) 
	{
		$conf_args = $conf_args . " --enable-help=y"; 
		if ( -d "$httpdir/data/mail" )
		{
			$helpdir = "$httpdir/data/mail/images/qmailadmin/help";
		} else {
			$helpdir = "$httpdir/data/images/qmailadmin/help";
		};

		if ( -d $helpdir ) 
		{
			print "InstallQmailadmin: help files already installed.\n";
		}
		else
		{
			FetchFile("$site/$help.tar.gz");
			SysCmd( "$tar -xzf $help.tar.gz");
			move("$help", "$helpdir") or warn "FAILED: Couldn't move $help to $helpdir";
		};
	};

};

sub InstallMysql
{

	my $ans = GetAnswer("You have several choices for installing Mysql:

   1. Install ? version from FreeBSD package.

	This will (very quickly) install whichever version of MySQL was released
	 with the version of FreeBSD you are running. This quite often is not 
	what you want.

	2. Install Mysql 3.23.x, which is the latest MySQL in the 3.x branch.

	3. Install Mysql 4.0.x, which is the latest MySQL in the 4.x branch.

	4. Install Mysql 4.1.x, which is currently alpha quality. Not recommended.
");

	if ($ans == 1) 
	{
		InstallPackage("mysql-server", "databases");
		InstallPackage("mysql-client", "databases");
	} 
	elsif ($ans == 2) 
	{
		InstallPort("mysql323-server", "databases", "mysql323-server", "mysql-server-3");
		InstallPort("mysql323-client", "databases", "mysql323-client", "mysql-client-3");
	} 
	elsif ($ans == 3) 
	{
		InstallPort("mysql40-server", "databases", "mysql40-server", "mysql-server-4.0");
		InstallPort("mysql40-client", "databases", "mysql40-client", "mysql-client-4.0");
	} 
	elsif ($ans == 4) 
	{
		InstallPort("mysql41-server", "databases", "mysql41-server", "mysql-server-4.1");
		InstallPort("mysql41-client", "databases", "mysql41-client", "mysql-client-4.1");
	};

	InstallPort("p5-DBI",            "databases");
	InstallPort("p5-DBD-mysql",      "databases");

#  This would be great to install but until it recognizes a previously
#  installed mod_perl2, we can't use it via ports. :(
#	InstallPort("p5-Apache-DBI",     "www");

}

sub InstallUCSPI
{
	my $package = "ucspi-tcp-0.88";
	my $patch   = "$package-mysql2+rss.patch";
	my $site    = "http://cr.yp.to/ucspi-tcp";

	CdSrcDir("$src/mail");

	if ( !-e "$package.tar.gz" ) { FetchFile("$site/$package.tar.gz"); };
	if ( !-e "$patch" )          { FetchFile("$toaster/$patch"); };

	if ( -d "$package" ) 
	{
		my $r = SourceWarning($package, 1);
		if (! $r) { die "sorry, I can't continue.\n"; };
	};

	SysCmd("$tar -xzf $package.tar.gz");
	chdir($package);
	SysCmd( "patch -p1 < ../$patch");
	SysCmd( "make");
	SysCmd( "make setup check");
};

sub InstallEzmlm 
{
	my $r = InstallPort("ezmlm-idx", "mail");

	if ($r) 
	{
		chdir("$confdir/ezmlm");
		copy("ezmlmglrc.sample",  "ezmlmglrc" ) or die "copy failed: $!";
		copy("ezmlmrc.sample",    "ezmlmrc"   ) or die "copy failed: $!";
		copy("ezmlmsubrc.sample", "ezmlmsubrc") or die "copy failed: $!";
	};
};

sub ConfigCourier 
{
	chdir("$confdir/courier-imap");

	copy("pop3d.cnf.dist", "pop3d.cnf" ) if ( ! -e "pop3d.cnf" );
	copy("pop3d.dist",     "pop3d"     ) if ( ! -e "pop3d"     );
	copy("pop3d-ssl.dist", "pop3d-ssl" ) if ( ! -e "pop3d-ssl" );
	copy("imapd.cnf.dist", "imapd.cnf" ) if ( ! -e "imapd.cnf" );
	copy("imapd.dist",     "imapd"     ) if ( ! -e "imapd"     );
	copy("imapd-ssl.dist", "imapd-ssl" ) if ( ! -e "imapd-ssl" );
	copy("quotawarnmsg.example", "quotawarnmsg") if (!-e "quotawarnmsg");

	if ( ! -e "$confdir/rc.d/imapd.sh" ) 
	{
		my $libe = "/usr/local/libexec/courier-imap";
		copy("$libe/imapd.rc",     "$confdir/rc.d/imapd.sh");
		chmod(00755, "$confdir/rc.d/imapd.sh");
		copy("$libe/pop3d.rc",     "$confdir/rc.d/pop3d.sh");
		chmod(00755, "$confdir/rc.d/pop3d.sh");
		copy("$libe/imapd-ssl.rc", "$confdir/rc.d/imapd-ssl.sh");
		chmod(00755, "$confdir/rc.d/imapd-ssl.sh");
		copy("$libe/pop3d-ssl.rc", "$confdir/rc.d/pop3d-ssl.sh");
		chmod(00755, "$confdir/rc.d/pop3d-ssl.sh");
	};

	if ( ! -e "/usr/local/sbin/imap" ) 
	{
		symlink("$confdir/rc.d/imapd.sh",     "/usr/local/sbin/imap");
		symlink("$confdir/rc.d/pop3d.sh",     "/usr/local/sbin/pop3");
		symlink("$confdir/rc.d/imapd-ssl.sh", "/usr/local/sbin/imapssl");
		symlink("$confdir/rc.d/pop3d-ssl.sh", "/usr/local/sbin/pop3ssl");
	};
};

sub ConfigQmail 
{
	my ($host) = @_;
	my $dbhost;
	my $control = "$qmaildir/control";

	if ( !$host ) 
	{
		$host = GetAnswer("the hostname for this mail server");
	};

	if ( !$dbhost ) 
	{
		$dbhost = GetAnswer("the hostname for your database server (localhost)");
	};
	$dbhost = "localhost" if (!$dbhost);

	if ( !$postmaster ) 
	{
		$postmaster = GetAnswer("the email address you use for administrator mail");
	};

	my $password = GetAnswer("the SQL password for user vpopmail");

	if ( !-e "$control/concurrencyremote" ) 
	{
		WriteFile("$control/concurrencyremote", "255");
		chmod(00644, "$control/concurrencyremote");
	};

	if ( !-e "$control/me" ) 
	{
		WriteFile("$control/me", $host);
	};

	if ( !-e "$control/tarpitcount" ) 
	{
		WriteFile("$control/tarpitcount", "50");
	};

	if ( !-e "$control/tarpitdelay" ) 
	{
		WriteFile("$control/tarpitdelay", "5");
	};

	if ( !-e "$qmaildir/alias/.qmail-postmaster" ) 
	{
		WriteFile("$qmaildir/alias/.qmail-postmaster",    "$postmaster\@$host");
	};

	if ( !-e "$qmaildir/alias/.qmail-root" ) 
	{
		WriteFile("$qmaildir/alias/.qmail-root",          "$postmaster\@$host");
	};

	if ( !-e "$qmaildir/alias/.qmail-mailer-daemon" ) 
	{
		WriteFile("$qmaildir/alias/.qmail-mailer-daemon", "$postmaster\@$host");
	};

	if ( !-e "$control/sql" ) 
	{
		my @lines  = "server $dbhost";
		push @lines, "port 3306";
		push @lines, "database vpopmail";
		push @lines, "table relay";
		push @lines, "user vpopmail";
		push @lines, "pass $password";
		push @lines, "time 1800";

		WriteFile("$control/sql", @lines);

		my $uid = getpwnam("vpopmail");
		my $gid = getgrnam("vchkpw");
		chown( $uid, $gid, "$control/sql"); 
		chown( $uid, $gid, "$control/servercert.pem"); 
	};
};

sub ConfigVpopmailEtc 
{
	my ($vetc) = @_;

	if ( !-d $vpopdir ) 
	{
		mkdir($vpopdir, 0775);
	};

	if ( -d $vetc ) 
	{
		print "$vetc already exists, skipping.\n";
	} else {
		print "creating $vetc\n";
		mkdir($vetc, 0775) or warn "failed to create $vetc: $!\n";
	};

	if ( ! -f "$vetc/tcp.smtp" ) 
	{
		push my @lines, "127.0.0.1:allow,RELAYCLIENT=\"\"";
		my $block = 1;

		my $ans = YesOrNo("Do you need to enable relay access for any netblocks? :");
		if ($ans)
		{
			do
			{
				$block = GetAnswer("the netblock to add (empty to finish)");
				push @lines, "$block:allow,RELAYCLIENT=\"\"" if $block;
			} until (! $block);
		};
		push @lines, ":allow";

		WriteFile("$vetc/tcp.smtp", @lines);
	};
};

sub InstallSupervise 
{
	CreateSuperviseDirs();
	chdir($supervise);

	foreach my $prot ( qw/ smtp send pop3 / )
	{
		if ( !-e "$prot/run") 
		{
			ConfigureSuperviseFile($prot);
			chmod(00751, "$prot/run", "$prot/log/run");
			# WriteFile("$prot/log/down", "");
		};

		if ( ! -e "$prot/log/run")
		{
			my @lines;
			if ($prot eq "send") {
				push @lines, "#!/bin/sh";
				push @lines, "PATH=/var/qmail/bin:/usr/local/bin:/usr/bin:/bin";
				push @lines, "export PATH";
				push @lines, "exec setuidgid qmaill multilog t s1000000 n20 /var/log/mail/send 2>&1";
			};
			WriteFile("$prot/log/run", @lines);
			chmod(00751, "$prot/log/run");
		};
	};

	ConfigureQmailControl();
	ConfigureServices();
};

sub ConfigureSuperviseFile
{
	my $prot = shift;

	my $vpdir = (getpwnam("vpopmail"))[7];
	push my @lines, "#!/bin/sh\n";

	if ($prot eq "smtp" or $prot eq "pop3")
	{
		push @lines, "PATH=/var/qmail/bin:/usr/local/bin:/usr/bin:/bin\n";
		push @lines, "export PATH";
	};

	if ($prot eq "smtp")
	{
		my $qmuid;
		my $ans = YesOrNo("Do you have domains owned by system users other than vpomail?");

		if ($ans) { $qmuid = (getpwnam("root"))[2]; } 
		else      { $qmuid = (getpwnam("vpopmail"))[2]; };

		my $qmgid = getgrnam("qnofiles");
		$qmgid = getgrnam("qmail") if (! $qmgid);

		my $servername = GetAnswer("this mail servers (smtp helo) host name");

		push @lines, "LOCAL=\`head -1 $qmaildir/control/me\`";
		push @lines, "if [ -z \"\$LOCAL\" ]; then";
		push @lines, "\techo LOCAL is unset in";
		push @lines, "\t$qmaildir/supervise/smtp/run";
		push @lines, "\texit 1";
		push @lines, "fi";

		push @lines, "if [ ! -f $qmaildir/control/rcpthosts ]; then";
    	push @lines, "\techo \"No $qmaildir/control/rcpthosts!\"";
    	push @lines, "\techo \"Refusing to start SMTP listener because it'll create an open relay\"";
    	push @lines, "\texit 1";
		push @lines, "fi";

		my $exec = "exec softlimit -m 8000000 tcpserver -S -H -R -c20 -x $vpdir/etc/tcp.smtp.cdb" .
			" -u $qmuid -g $qmgid 0 smtp";
		my $bl = GetDesiredBlacklists();
		$exec = $exec . " $bl qmail-smtpd \"\$LOCAL\" $vpdir/bin/vchkpw /usr/bin/true";
		$exec = $exec . " splogger smtpd";

		push @lines, $exec;
		push @lines, "\n# -H don't look up \$TCPREMOTEHOST";
		push @lines, "# -R don't look up \$TCPREMOTEINFO";
		push @lines, "# -p paranoid, do forward & reverse queries";
		push @lines, "#    (if you use the -p option, consider the -t option).";
		push @lines, "# -S http://matt.simerson.net/computing/mail/qmail/qmail.toaster.open-smtp_writeup.txt";
		push @lines, "# -t timout value for dns lookups (in seconds) - default 26 seconds";
		push @lines, "# -c number of simultaneous connections";
	}
	elsif ($prot eq "send")
	{
		push @lines, "exec /var/qmail/rc";
	}
	elsif ($prot eq "pop3")
	{
		my $servername = GetAnswer("this mail servers (pop3) host name");
		my $exec = "exec tcpserver -R -H -c100 0 pop3 qmail-popup $servername $vpdir/bin/vchkpw qmail-pop3d Maildir splogger pop3";
		push @lines, $exec;
	};
	print "ConfigureSuperviseFile: writing $supervise/$prot/run\n";
	WriteFile("$supervise/$prot/run", @lines);
};

sub GetDesiredBlacklists
{
	my @blacklists = 
		qw/ rbl-plus.mail-abuse.org relays.osirusoft.com
			blackholes.mail-abuse.org relays.mail-abuse.org dialups.mail-abuse.org
			list.dsbl.org sbl.spamhaus.org bl.spamcop.net relays.ordb.org 
   		korea.services.net formmail.relays.monkeys.com proxies.relays.monkeys.com
			cn.rbl.cluecentral.net kr.rbl.cluecentral.net
		/;

	print "\nDNS based blacklists:\n\n\t";
	print join("\n\t", @blacklists); 
	my $ans = YesOrNo("\n\nDo you want to enable any of the listed blacklists? ");

	my $enabled = "";
	if ($ans)
	{
		$enabled = " rblsmtpd";
		foreach my $bl ( @blacklists ) 
		{
			my $ans = YesOrNo("enable $bl ");
			if ($ans)
			{
				$enabled = $enabled . " -r $bl";
			};
		};
	};
	return $enabled;
};

sub ConfigureServices
{
	if ( -e "$confdir/rc.d/services.sh" ) 
	{
		print "ConfigureServices: $confdir/rc.d/services.sh already exists.\n";
	}
	else
	{
		print "ConfigureServices: installing $confdir/rc.d/services.sh...\n";
		FetchFile("$toaster/services.txt");
		move("services.txt", "$confdir/rc.d/services.sh") or die "couldn't move: $!";
		chmod(00751, "$confdir/rc.d/services.sh");
		print "done.\n";
	};

	my $sym = "/usr/local/sbin/services";
	if ( -e $sym ) 
	{
		print "ConfigureServices: $sym already exists.\n";
	}
	else
	{
		print "ConfigureServices: adding $sym\n";
		symlink("$confdir/rc.d/services.sh", "/usr/local/sbin/services");
	};

	if ( -d $service ) 
	{
		print "ConfigureServices: $service already exists.\n";
	} else {
		print "creating $service...";
		mkdir($service, 0775) or die "couldn't create $service\n";
		print "done.\n";
	};

	foreach my $prot ("smtp", "send")
	{
		if ( -e "$service/$prot" ) 
		{
			print "ConfigureServices: $service/$prot already exists.\n";
		}
		else
		{
			print "ConfigureServices: creating symlink from $supervise/$prot to $service/$prot\n";
			symlink("$supervise/$prot", "$service/$prot") or die "couldn't symlink: $!";
		};
	};
}

sub ConfigureQmailControl
{
	if ( -e "$qmaildir/rc" ) 
	{
		print "ConfigureQmailControl: $qmaildir/rc already exists.\n";
	}
	else 
	{
		push my @lines, "#!/bin/sh\n";

		# This uses splogger to send logging through syslog
		push @lines, "exec env - PATH=\"/var/qmail/bin:\$PATH\" qmail-start ./Maildir/ splogger qmail";

		# This sends the output to multilog as directed in log/run
		#push @lines, "exec env - PATH=\"/var/qmail/bin:\$PATH\" qmail-start ./Maildir/";

		WriteFile("$qmaildir/rc", @lines);
		chmod(00751, "$qmaildir/rc");
	};

	if ( -e "$confdir/rc.d/qmail.sh" ) 
	{
		unlink("$confdir/rc.d/qmail.sh") 
			or die "couldn't delete $confdir/rc.d/qmail.sh: $!";;
	};

	my $qmailctl  = "/usr/local/sbin/qmail";
	if ( -e $qmailctl ) 
	{
		print "ConfigureQmailControl: $qmailctl already exists.\n";
	}
	else 
	{
		FetchFile("$toaster/qmail.txt");
		move("qmail.txt", $qmailctl) or die "couldn't move: $!";
		chmod(00751, $qmailctl);
		SysCmd("$qmailctl cdb");
	};
};

sub CreateSuperviseDirs
{
	if ( -d $supervise ) 
	{
		print "CreateSuperviseDirs: $supervise already exists.\n";
	} else {
		mkdir($supervise, 0775) or die "failed to create $supervise: $!\n";
	};

	chdir($supervise);

	foreach my $prot ( qw/ smtp send pop3 / )
	{
		if ( -d $prot )
		{
			print "CreateSuperviseDirs: $supervise/$prot already exists\n";
		}
		else
		{
			mkdir($prot, 0775) or die "failed to create $supervise/$prot: $!\n";
			mkdir("$prot/log", 0775) or die "failed to create $supervise/$prot/log: $!\n";
			SysCmd("chmod +t $prot");
		};
	};
};

sub InstallQmail 
{
	my ($package) = @_;
	my $patch;

	CdSrcDir("$src/mail");

	if ( -e $package ) 
	{
		my $r = SourceWarning($package, 1);
		if (! $r) { die "sorry, I can't continue.\n"; };
	};

	print "\nCheckUser support causes the qmail-smtpd daemon to verify that
a user exists locally before accepting the message, during the SMTP conversation.
This prevents your mail server from accepting messages to email addresses that
don't exist in vpopmail. It is not compatible with system user mailboxes. \n\n";

	my $chkusr = YesOrNo("Do you want qmail-smtpd-chkusr support enabled?");
	if ($chkusr) {
		$patch = "$package-toaster-2.4.patch";
	} else {
		$patch = "$package-toaster-2.3.patch";
	};
	my $site  = "http://cr.yp.to/software";

	if ( !-e "$package.tar.gz" ) 
	{
		if ( -e "/usr/ports/distfiles/$package.tar.gz" ) 
		{
			copy("/usr/ports/distfiles/$package.tar.gz", "./$package.tar.gz");  
		} else {
			FetchFile("$site/$package.tar.gz");
		};
	};

	if ( !-e $patch ) 
	{
		FetchFile("$toaster/$patch");
	};

	SysCmd( "$tar -xzf $package.tar.gz");
	chdir("$src/mail/$package");
	SysCmd( "patch -p1 < ../$patch");
	SysCmd( "echo \"$qmaildir\" > conf-qmail");
	SysCmd( "make setup");
	#SysCmd( "make cert");

	if ($chkusr) {
		my $uid = getpwnam("vpopmail");
		my $gid = getgrnam("qnofiles");
		chown($uid, $gid, "$qmaildir/bin/qmail-smtpd") 
			or warn "chown $qmaildir/bin/qmail-smtpd failed: $!\n";
		SysCmd("chmod 6555 $qmaildir/bin/qmail-smtpd");
	};

	if ( !-e "/usr/share/skel/Maildir" ) 
	{
		SysCmd( "$qmaildir/bin/maildirmake /usr/share/skel/Maildir");
	};

	ConfigQmail($host);
};

sub FetchFile 
{
	my ($url) = @_;

	my $fetch = FindTheBin("fetch");
	SysCmd("$fetch $url");
};

__END__


=head1 AUTHOR

	Matt Simerson

=head1 BUGS

	None known. Report any to matt@cadillac.net.

=head1 TODO

	Check if daemons are running before installs.
	Add checks to pkg_add so that if pkg_add -r fails, install from ports
	Turn entire process into a ./install_it_all script
	Add -s dnscache section to install a DNS stub resolver

=head1 SEE ALSO

	http://matt.simerson.net/computing/mail/toaster/
	http://matt.simerson.net/computing/mail/toaster/faq.shtml
	http://matt.simerson.net/computing/mail/toaster/changelog.shtml

=head1 COPYRIGHT

	Copyright 2001 - 2003, Matt Simerson. All Right Reserved.

=cut
