#!/usr/bin/perl
# Script for creating virtual servers from a skeleton template.
# RedHat GNU Linux version.
# Copyright (c) 1999, 2000, 2001 Idaya Ltd.
#
# This file is part of the Virtual Server Administrator (FreeVSD)
#
# FreeVSD 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, or (at your option)
# any later version.
#
# FreeVSD 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 FreeVSD; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#

# To run this script, you must have previously created a skel with
# vsd-genskel.pl.
#
# This script could be called as a cron job, periodically process
# /tmp/vsd.accounts creating and deleting accounts whenever necessary.
#
use Sys::Hostname;
use IO::File;
use File::Copy;
use VSD;
use VSD::Config;

my $vsdconf = VSD::Config->new( file=>$path{vsdconf} );


# FIX SERIOUSLY........ sort out imports from freevsd.conf, so that at least
#                         it is obvious that stuff comes from there.....!


my $verbose_mode = 0; 
if (@ARGV == 1 && $ARGV[0] eq "-v"){
  $verbose_mode = 1;
}
elsif (@ARGV > 0){
  print "$0: usage error: vsd-vsbatch.pl [-v]\n";
  exit 0;
}
else {
  $verbose_mode = 0;
}



# Added by Ben - root check

$whoami = `whoami`;
chomp($whoami);

if (!($whoami eq "root")) {
   $verbose_mode && print "You're not running as root!  Exiting\n";
   exit 0;
}

# /tmp/vsd.accounts is a temporary file that contains the queue of
# virtual servers that need creating.
unless (-e "/tmp/vsd.accounts") { 
	$verbose_mode && print "No /tmp/vsd.accounts file - Nothing to do!\nExiting\n";
	exit 0;
}

# If this lock file exists then account creation is already in
# progress, don't start another job.
if (-e "/tmp/vsd.accounts.lock") { 
	$verbose_mode && print "/tmp/vsd.accounts.lock exists which suggests I'm already running!\nExiting...\n";
	exit 0; 
}

open (OUT, ">/tmp/vsd.accounts.lock"); close (OUT);
rename ("/tmp/vsd.accounts", "/tmp/vsd.accounts.bak");

# Location of sendmail
$sendmail = "/bin/sendmail" if (-x "/bin/sendmail");
$sendmail = "/usr/libexec/sendmail" if (-x "/usr/libexec/sendmail");
$sendmail = "/usr/sbin/sendmail" if (-x "/usr/sbin/sendmail");
$hostname = hostname ();
srand (time ^ $$);

do "$path{freevsdconf}";
require ($site_vs_install) if (defined $site_vs_install);

# Array of characters suitable for an account password.
@chars = ("A".."Z", "a".."z", 0..9);

open (JOB, "/tmp/vsd.accounts.bak");
while (<JOB>) {
  chomp;
  my ($action, $vs, $param, $vs_ip) = split (/ /, $_);
  if ($action eq "create") {

    $verbose_mode && print "Starting create job for $vs...\n";

    my $fqdn = $param;
#    ($vsconf, $aliasip) = vsd_map_read ("$path{vsdconf}", $vs);
    my $partition_mnt = $vsdconf->getval(
					 'Partition',
					 ($vsdconf->getval( 'VirtualServer', "$vs", 'Partition' )),
					 'Mount'
					);
    my $skelname = $vsdconf->getval (
                                      'VirtualServer', 
                                      "$vs",
                                      'Skel'
                                     );

    if (! -d $partition_mnt) {
      printf ("Couldn't process %s: mount point `%s' does not exist\n", $name, $partition_mnt);
    } else {
      # Create a random password for the account
      $password = join ("", @chars[map {rand @chars} (1..8)]);

      $mntpoint = $partition_mnt;
      $skelroot = $mntpoint."/skel/".$skelname; # Used in all sub-procs
      $vsdir = $mntpoint."/vs/".$vs; # Used in all sub-procs

      if (! -d $skelroot) {
	printf ("Skel root `%s' does not exist\n", $skelroot);
      } else {
	make_vs ();
	site_make_vs ($vsdconf) if (defined $site_vs_install);
	config_vs ($vsdconf, $fqdn, $vs);
	site_config_vs ($vsdconf, $fqdn, $vs) if (defined $site_vs_install);

	if ($send_mail eq "YES") {
          $verbose_mode && print "Sending mail ($mail_template) to $mail_addr...\n";
	  email ($vsdconf, $fqdn, $password, $mail_template, $vs);
	}
      }
    }
    $verbose_mode && print "Finished create job for $vs.\n";
  }
  if ($action eq "delete") {
    $verbose_mode && print "Starting delete job for $vs...\n";

    if (! -d "$param") {
      printf ("Couldn't delete %s: mount point '%s' does not exist\n", $vs, $param);
    } else {
      $verbose_mode && print "Removing $param/vs/$vs...\n";
      `rm -r -f $param/vs/$vs`;
      # Remove iptables if it is configure and exists
      my $chkconfig = `chkconfig --list`;
      if ( -e "/sbin/iptables" && 
           $chkconfig =~ /ipchains .*2:off.*3:off.*4:off.*5:off.*/ &&
           $chkconfig =~ /iptables .*2:on.*3:on.*4:on.*5:on.*/ ){
        $verbose_mode && print "Removing iptables routing to VS IP...\n";
        `/sbin/iptables -D PREROUTING -t nat -p tcp -d $vs_ip --dport 80 -j DNAT --to-destination $vs_ip:8080`;
        `/sbin/iptables -D PREROUTING -t nat -p udp -d $vs_ip --dport 80 -j DNAT --to-destination $vs_ip:8080`;
        `/sbin/iptables -D PREROUTING -t nat -p tcp -d $vs_ip --dport 443 -j DNAT --to-destination $vs_ip:8443`;
        `/sbin/iptables -D PREROUTING -t nat -p udp -d $vs_ip --dport 443 -j DNAT --to-destination $vs_ip:8443`;
        `/etc/rc.d/init.d/iptables save`;
      }
    }
    $verbose_mode && print "Finished delete job for $vs.\n";
  }

################################################################################
# VSD Domain creation is interactive, not batched for now...
#
#  if ($action eq "domaincreate") {
#    my $domainname = $param;
#    my $partition_mnt = $vsdconf->getval(
#                                         'Partition',
#                                         ($vsdconf->getval( 'VirtualServer', "$vs", 'Partition' )),
#                                         'Mount'
#                                        );
#    my $vsdir = $partition_mnt."/vs/".$vs;
#
#    # set up random password for user called $domainname:
#    $rdm_passwd = join ("", @chars[map {rand @chars} (1..8)]);
#
#    if ( ! -d "$vsdir") {
#      printf ("Could not configure managed domain '%s': hosting server '%s' does not exist\n",
#               $domainname, $vs);
#    }
#    else {
#      # print "Adding configuration for $domainname\n";
#      config_domain ($vsdconf, $domainname, $vsdir, $rdm_passwd);
#    }
#    
#    if ($send_mail eq "YES") {
#        email ($vsdconf, $domainname, $passwd, $mail_template, $vs);
#    }
# 
#  }
#  if ($action eq "domaindelete") {
#    my $domainname = $param;
#    my $partition_mnt = $vsdconf->getval(
#                                         'Partition',
#                                         ($vsdconf->getval( 'VirtualServer', "$vs", 'Partition' )),
#                                         'Mount'
#                                        );
#    if ((! defined ($partition_mnt)) || (! -d "$partition_mnt/vs/$vs")) {
#      printf ("Could not remove managed domain '%s': hosting server does not exist\n");
#    }
#    else {
#      # printf ("Removing configuration files for '%s'\n", $domainname);
#      my $vsdir = $partition_mnt."/vs/".$vs;
#      remove_domain ($vsdconf, $domainname, $vsdir);
#    }
#  }
################################################################################
}
close (JOB);
unlink ("/tmp/vsd.accounts.bak");
unlink ("/tmp/vsd.accounts.lock");

$verbose_mode && print "Finished.  Exiting...\n";

exit 0;


# email <vsconf> <fqdn> <admin-password> <template>
sub email {
  my ($fqdn, $ipaddr, $vs, $pw, $email, $tmpl);

  $vsdconf = $_[0];
  $fqdn = $_[1];
  $pw = $_[2];
  $email = $mail_addr;
  $tmpl = $_[3];
  $vs = $_[4];

  # FIX get $ip at top .. ?
  my $ip = $vsdconf->getval( 'VirtualServer', $vs, 'IP' );

  open (TMPL, "< $tmpl")
    or warn "cannot open $tmpl: $!\n";
  open (SMAIL, "|$sendmail -oi -t")
    or die "cannot open a pipe to $sendmail: $!";
  printf (SMAIL "From: vsd@%s (Virtual Server Administrator)\n", $hostname);
  printf (SMAIL "To: %s\n", $email);
  while (<TMPL>) {
    s/\#VS\#/$vs/;
    s/\#HOSTNAME\#/$fqdn/;
    s/\#IPADDRESS\#/$ip/;
    s/\#PASSWORD\#/$pw/;
    printf SMAIL "%s", $_;
  }
  close (SMAIL);
  close (TMPL);
}

# make_vs <vsconf>
sub make_vs {
  my (@nam1, @nam2, $x, $y, $vs);

#  $vsconf = $_[0];

# FIX don't use globals, eg $mntpoint $vsdir ......

  mkdir ("$mntpoint/vs", 0755) unless (-d "$mntpoint/vs");
  mkdir ("$vsdir", 0755) unless (-d "$vsdir");

  # Files are copied as hard links except /etc
  system ("cp -al $skelroot/* $vsdir");
  system ("rm -r -f $vsdir/etc $vsdir/home/httpd");
  system ("cp -a $skelroot/etc $vsdir");
  system ("cp -a $skelroot/home/httpd $vsdir/home");

  # Create some additional directories
  @dirs = ("etc/vsd", "etc/cron.d", "dev", "root", "var", 
	   "home/ftp", "home/ftp/incoming");
  foreach $file (@dirs) {
      mkdir ("$vsdir/$file", 0755);
  }
  
  mkdir ("$vsdir/etc/vsd", 0755);

  # Softlink /var/tmp to /tmp
  symlink ("../tmp", "$vsdir/var/tmp");
  
  # Set the timezone. Er. Shouldn't be blighty specific.
  symlink ("../usr/share/zoneinfo/Europe/London", "$vsdir/etc/localtime");

  # Create the tty devices
  @nam1 = ("p".."z", "a".."e");
  @nam2 = (0..9, "a".."f");
  for ($x = 0; $x <= 15; $x++) {
      for ($y = 0; $y <= 15; $y++) {
	  $minor = ($x * 16) + $y;
	  system ("mknod", "-m", "0620", "$vsdir/dev/pty$nam1[$x]$nam2[$y]",
		  "c", "2", "$minor") unless ( -c "$vsdir/dev/pty$nam1[$x]$nam2[$y]" ) ;
	  system ("mknod", "-m", "0620", "$vsdir/dev/tty$nam1[$x]$nam2[$y]",
		  "c", "3", "$minor")  unless ( -c "$vsdir/dev/tty$nam1[$x]$nam2[$y]" ); 
          chmod ( "0620", "$vsdir/dev/pty$nam1[$x]$nam2[$y]", "$vsdir/dev/tty$nam1[$x]$nam2[$y]" );
      }
  }
  
  # Make other useful devices
  system ("mknod", "-m", "0666", "$vsdir/dev/zero", "c", "1", "5") unless ( -c "$vsdir/dev/zero" );
  unlink ("$vsdir/dev/null");
  system ("mknod", "-m", "0666", "$vsdir/dev/null", "c", "1", "3");
  system ("mknod", "-m", "0666", "$vsdir/dev/random", "c", "1", "8")  unless ( -c "$vsdir/dev/random");
  system ("mknod", "-m", "0666", "$vsdir/dev/urandom", "c", "1", "9")  unless ( -c "$vsdir/dev/urandom" );
  system ("mknod", "-m", "0666", "$vsdir/dev/tty", "c", "5", "0")  unless ( -c "$vsdir/dev/tty" );
  mkdir ("$vsdir/dev/fd", 0755);
  symlink ("../var/run/log", "$vsdir/dev/log"); # For syslogd
}
          

# config_vs <vsconf> <fqdn>
sub config_vs {
  my ($c, $fh, $childpid);

# FIX get rid og globals eg. $vsdir ....

  # are we running on rh 6.2 or 7.1?
  my $release_version = 0;
  if (-e "/etc/redhat-release")
    {
      open (OUT, "/etc/redhat-release");
      while (<OUT>)
        {
           if ($_ =~ /.* 6\.. .*/)
             {
               $release_version = rh6;
               $verbose_mode && print "Redhat 6.x configuration\n";
             }
           elsif ($_ =~ /.* 7\.. .*/)
             {
               $release_version = rh7;
               $verbose_mode && print "Redhat 7.x configuration\n";
             }
           else
             {
               undef $release_version;
               $verbose_mode && print "Generic OS configuration\n";
             }
        }
    }
          

#  $vsconf = $_[0];
  my ($vsdconf, $fqdn, $vs) = @_;

  my $startuid = $vsdconf->getval( 'VirtualServer', $vs, 'StartUID' );
  my $enduid = $startuid + ( $vsdconf->getval( 'VirtualServer', $vs, 'Users' )) - 1 ;

  my $ip = $vsdconf->getval( 'VirtualServer', $vs, 'IP' );

  my $pns = $vsdconf->getval( 'VirtualServer', $vs, 'PrimaryNS' );
  my $sns = $vsdconf->getval( 'VirtualServer', $vs, 'SecondaryNS' );

  $pns = defined $pns ? $pns : '';
  $sns = defined $sns ? $sns : '';

  my $vs_quota = $vsdconf->getval( 'VirtualServer', $vs, 'Quota' );

  # Create /etc/vsd/quota
  open (OUT, ">$vsdir/etc/vsd/quota");
  printf (OUT "%d\n", $vs_quota);
  close (OUT);

  # This file is used by the uname system call
  open (OUT, ">$vsdir/etc/FQDN");
  printf OUT "%s %s\n", $fqdn, $vs;
  close (OUT);

  # Create /etc/hosts
  open (OUT, ">$vsdir/etc/hosts");
  printf OUT "%s %s localhost\n", $ip, $fqdn;
  close (OUT);

  # Create /etc/resolv.conf
  open (OUT, ">$vsdir/etc/resolv.conf");
  printf OUT "domain %s\n", $fqdn;
  printf OUT "nameserver %s\n", $pns;
  printf OUT "nameserver %s\n", $sns;
  close (OUT);

  # Create /etc/issue.net
  open (OUT, ">$vsdir/etc/issue.net");
  printf OUT "Server %s\n", $fqdn;
  close (OUT);

  # Create /etc/sendmail.cw
  open (OUT, ">$vsdir/etc/sendmail.cw");
  printf OUT "# sendmail.cw - include all aliases for your machine here\n";
  printf OUT "%s\n", $fqdn;
  close (OUT);

  rename ("$vsdir/etc/login.defs", "$vsdir/tmp/login.defs");
  open (IN, "$vsdir/tmp/login.defs");
  open (OUT, ">$vsdir/etc/login.defs");
  while (<IN>) {
    $_ =~ s/\#UID_MIN\#/$startuid/;
    $_ =~ s/\#UID_MAX\#/$enduid/;
    $_ =~ s/\#GID_MIN\#/$startuid/;
    $_ =~ s/\#GID_MAX\#/$enduid/;
    printf OUT "%s", $_;
  }
  close (OUT);
  close (IN);
  unlink ("$vsdir/tmp/login.defs");

  # Test for iptables 
  my $chkconfig = `chkconfig --list`;
  if ( -e "/sbin/iptables" &&
       $chkconfig =~ /ipchains .*2:off.*3:off.*4:off.*5:off.*/ &&
       $chkconfig =~ /iptables .*2:on.*3:on.*4:on.*5:on.*/ ) {
    # if it exists, remove vsdredirect commands from etc/rc
    rename ("$vsdir/etc/rc", "$vsdir/tmp/rc");
    open (IN, "$vsdir/tmp/rc");
    open (OUT, ">$vsdir/etc/rc");
    while (<IN>) {
      $_ =~ s/vsdredirect/# vsdredirect replaced by iptables rules on hosting server:/;
      printf OUT "%s", $_;
    }
    close (OUT);
    close (IN);
    system ("chmod", "755", "$vsdir/etc/rc");
    unlink ("$vsdir/tmp/rc");

    # Configure iptables rules for virtual server
    `/sbin/iptables -A PREROUTING -t nat -p tcp -d $ip --dport 80 -j DNAT --to-destination $ip:8080`;
    `/sbin/iptables -A PREROUTING -t nat -p udp -d $ip --dport 80 -j DNAT --to-destination $ip:8080`;
    `/sbin/iptables -A PREROUTING -t nat -p tcp -d $ip --dport 443 -j DNAT --to-destination $ip:8443`;
    `/sbin/iptables -A PREROUTING -t nat -p udp -d $ip --dport 443 -j DNAT --to-destination $ip:8443`;
    `/etc/rc.d/init.d/iptables save`;
  }

  if (! defined($childpid = fork ())) {
      die "cannot fork: $!";
  } elsif ($childpid == 0) {
    # child
    my ($gid_admin, $gid_mail, $gid_web, $gid_ftp);
    my ($uid_admin, $uid_web, $uid_ftp);
    chroot ($vsdir);
    chdir ("/");
    $uid_admin = $gid_admin = $startuid;
    $uid_mail = $gid_mail = $startuid + 1;
    $uid_web = $gid_web = $startuid + 2;
    $uid_ftp = $gid_ftp = $startuid + 3;
    
    system ("/usr/sbin/groupadd", "admin", "-g", "$gid_admin");
    system ("/usr/sbin/groupadd", "mail", "-g", "$gid_mail");
    system ("/usr/sbin/groupadd", "web", "-g", "$gid_web");
    system ("/usr/sbin/groupadd", "ftp", "-g", "$gid_ftp");

    system ("/usr/sbin/useradd", "-c", "administrator", "-d", "/root",
	    "-u", "$uid_admin", "-g", "admin", "-G", "web", "-M",
	    "-n", "-s", "/bin/bash", "admin");
    chown $uid_admin, $gid_admin, "/home";

    system ("/usr/sbin/useradd", "-c", "mail", "-d", "/var/spool/mail",
	    "-u", "$uid_mail", "-g", "mail", "-M", "-n",
	    "-s", "/bin/bash", "mail");

    system ("/usr/sbin/useradd", "-c", "webserver", "-d", "/home/web",
	    "-u", "$uid_web", "-g", "web", "-G", "admin", "-M", "-n",
	    "-s", "/bin/bash", "web");
    mkdir ("/home/web", 0755);
    chown $uid_web, $uid_web, "/home/web";
    mkdir ("/home/web/log", 0755);
    chown $uid_web, $uid_web, "/home/web/log";

    system ("/usr/sbin/useradd", "-c", "ftpserver", "-d", "/home/ftp",
	    "-u", "$uid_ftp", "-g", "ftp", "-M", "-n",
	    "-s", "/bin/bash", "ftp");

    @admin_files = ("/home/httpd", "/home/ftp", "/home/ftp/incoming", "/tmp", "/root");
    chown $uid_admin, $gid_admin, @admin_files;
    system ("chown", "-R", "root.root", "/etc");

    # Create subdirectories of /var
    @subdir = ("catman", "lib", "lib/texmf", "lib/texmf/fonts",
	       "lib/texmf/texfonts", "local", "lock", "lock/subsys",
	       "log", "preserve", "spool", "spool/at",
	       "spool/cron", "mail", "spool/mail", "spool/mqueue");
    foreach (@subdir) {
       mkdir ("/var/$_", 0755);
    }

    # Make var/run. 'tis a special case:
    if ($release_version eq "rh7")
      {
        mkdir ("/var/run", 0777);
        chmod (01777, "/var/run");
      }
    elsif ($release_version eq "rh6")
      {
        mkdir ("/var/run", 0775);
      }
    else 
      {
        mkdir ("/var/run", 0755);
      }

    # Create subdirectories pf /usr/local
    mkdir ("/usr/local", 0755);
    chown $uid_admin, $gid_admin, "/usr/local";
    @subdir = ("bin", "doc", "etc", "games", "include", "info", "lib",
	       "man", "sbin", "src", "man/man1", "man/man2", "man/man3",
	       "man/man4", "man/man5", "man/man6", "man/man7", "man/man8",
	       "man/mann");
    foreach (@subdir) {
	mkdir ("/usr/local/$_", 0755);
	chown $uid_admin, $gid_admin, "/usr/local/$_";
    }

    chmod (01777, "/tmp");
    chmod (0755, "/etc");
    chmod (0755, "/etc/mail");
    chmod (0755, "/etc/vsd");
    chmod (0775, "/var/lock");
    chmod (0755, "/var/spool/at");
    chmod (0775, "/var/catman");
    chmod (0775, "/var/spool/mail");
    chmod (0755, "/var/log");

    # Set the ownership of the /var/spool/mqueue for the different sendmail versions.
    if ($release_version eq "rh7")
      {
        #`chown root.admin /var/spool/mqueue`;
        chown "root", $uid_admin, "/var/spool/mqueue";
        $verbose_mode && print "chown-ing /var/spool/mqueue for sendmail 8.11\n";
      }
    else 
      {
        chown $uid_admin, $gid_admin, "/var/spool/mqueue";
      }

    # Certain directories cannot be written to by admin
    #`chown -R root.man /var/catman`;
    #`chown -R root.uucp /var/lock`;
    #`chown -R daemon.admin /var/spool/at`;

    # Certain directories need to be written to by admin
    `chown admin.admin /etc/mail`;
    `chown admin.admin /var/run`;
    `chown admin.admin /var/lib`;
    `chown admin.admin /var/log`;
    `chown admin.admin /var/mail`;
    `chown admin.admin /var/spool/mail`;
    `chown admin.admin /var/spool/at`;

    # Create the dynamic library cache.
    system ("/sbin/ldconfig");
    
    # Fix file permissions of certain /etc files.
    foreach $file ("login.defs", "vsd/priv", "vsd/quota", "sendmail.cw", "sendmail.ct",
		   "crontab", "sendmail.cf",
		   "httpd/conf/httpd.conf", "pam.d/*", "aliases", "aliases.db") {
	chmod (0644, "/etc/$file");
    }

    # Fixup file permissions to stop sendmail complaining.
    chmod (0666, "/etc/mail/ip_allow");

    # Ensure that the aliases.db file exists before chown it
    if ($release_version eq "rh6")
      {
        `touch /etc/aliases.db`;
        chown $uid_admin, $gid_admin, "/etc/aliases.db";
        $verbose_mode && print "creating dummy alias.db\n";
      }

    # Certain files in /etc should be owned by the admin user
    @admin_files = ("/etc/aliases", "/etc/at.deny", "/etc/bashrc",
		    "/etc/hosts",
		    "/etc/issue.net", "/etc/logrotate.conf",
		    "/etc/lynx.cfg", "/etc/ld.so.conf",
		    "/etc/ld.so.cache", "/etc/resolv.conf",
		    "/etc/proftpd.conf", "/etc/sendmail.cw",
		    "/etc/rc.conf", "/etc/rc.local",
		    "/etc/procmailrc", "/etc/procmailrcs");
    push (@admin_files, glob ("/etc/httpd/*"));
    push (@admin_files, glob ("/etc/mail/*"));
    push (@admin_files, glob ("/etc/procmailrcs/*"));
    push (@admin_files, glob ("/etc/logrotate.d/*"));
    chown $uid_admin, $gid_admin, @admin_files;

    # Generate /etc/aliases.db.
    `/usr/bin/newaliases 2>/dev/null`;

    # Set the password here for the admin user.
    system ("/usr/bin/passwd", "-u", "admin", "-p", $password);

    if ( $vs_quota != 0) {
      # Set quotas for the users. Purely arbitary.
      system ("setquota", "admin", "10M");
      system ("setquota", "web", "4M");
      system ("setquota", "mail", "1M");
      system ("setquota", "ftp", "4K");
    }
  
    exit 0;
  } else {
    waitpid ($childpid, 0);
  }
}

# config_domain <vsdconf> <domainname> <vsdir> <password>
sub config_domain {

  my ($vsdconf, $domainname, $vsdir, $rdm_passwd) = @_;
  my $childpid;

  if (! defined ($childpid = fork ())) {
    die "cannot fork: $!";
  } elsif ($childpid == 0) {
    # We are the child, safe to chroot into virtual server
    chroot ($vsdir);
    chdir ("/");

    # Add the domain to the hosting servers mailertable:
    open (OUT, ">>/etc/mail/mailertable") or warn "error: unable to open the mailertable: $!";
    printf (OUT "%s    procmail:/etc/procmailrcs/virtual/%s/.procmailrc\n", $domainname, $domainname);
    close (OUT);
    system ("chown", "admin.admin", "/etc/mail/mailertable");

    # Regenerate the mailertable map
    `su - admin -c '/usr/sbin/makemap hash /etc/mail/mailertable.db < /etc/mail/mailertable'`;
    system ("chown", "admin.admin", "/etc/mail/mailertable.db");

    # create the virtualised procmailrcs directory:
    if ( ! -d "/etc/procmailrcs") {
      mkdir ("/etc/procmailrcs", 0755) or warn "error: unable to make /etc/procmailrcs directory: $!";
      system ("chown", "admin.admin", "/etc/procmailrcs");
    }
    if ( ! -d "/etc/procmailrcs/virtual") {
      mkdir ("/etc/procmailrcs/virtual", 0755) or warn "error: unable to make /etc/procmailrcs/virtual: $!";
      system ("chown", "admin.admin", "/etc/procmailrcs/virtual");
    }
    mkdir ("/etc/procmailrcs/virtual/$domainname", 0755) or warn "error: unable to make /etc/procmailrcs/virtual/$domainname: $!";
    system ("chown", "admin.admin", "/etc/procmailrcs/virtual/$domainname");

    # create the .procmailrc file:
    open (OUT, ">/etc/procmailrcs/virtual/$domainname/.procmailrc") or warn "error: unable to open $domainname/.procmailrc";
    printf (OUT "DOMAIN = %s\n", $domainname);
    printf (OUT "MAILDIR = /var/spool/virtual/\$DOMAIN\n\n");
    printf (OUT "SENDER = \$1\n");
    printf (OUT "RECIPT = \$2\n\n");
    printf (OUT ":0: # _vuser admin\n");
    printf (OUT "{\n");
    printf (OUT "  :0: # _fwd admin\n");
    printf (OUT "  | formail -ds >> \$MAILDIR/admin\n");
    printf (OUT "}\n");
    close (OUT);
    system ("chown", "mail.mail", "/etc/procmailrcs/virtual/$domainname/.procmailrc");

    # create the /var/spool directories
    if ( ! -d "/var/spool/virtual") {
        mkdir ("/var/spool/virtual", 0755);
        system ("chown", "admin.admin", "/var/spool/virtual");
    }
    mkdir ("/var/spool/virtual/$domainname", 0755);
    system ("chown", "mail.mail", "/var/spool/virtual/$domainname");

    # create the virtualised passwd directory:
    if ( ! -d "/etc/virtual") {
      mkdir ("/etc/virtual", 0755) or warn "error: unable to make /etc/virtual directory: $!";
      system ("chown", "admin.admin", "/etc/virtual");
    }
    mkdir ("/etc/virtual/$domainname", 0755) or warn "error: unable to make /etc/virtual/$domainname: $!";
    system ("chown", "admin.admin", "/etc/virtual/$domainname");

    # Create a passwd file for the virtual pop account, and populate with user $domainname:
    my $name = "admin";
    open (OUT, ">/etc/virtual/$domainname/passwd");
    my @salt_chars         = ('a'..'z','A'..'Z','0'..'9');
    my $salt               = $salt_chars[rand(62)] . $salt_chars[rand(62)];
    $passwd = crypt ($rdm_passwd, $salt);
    printf (OUT "$name:$passwd\n");
    close (OUT);
    exit 0;
  } else {
    waitpid ($childpid, 0);
  }
}

# remove_domain <vsdconf> <domainname> <vsdir> <password>
sub remove_domain {

  my ($vsdconf, $domainname, $vsdir, $rdm_passwd) = @_;
  my $childpid;

  if (! defined ($childpid = fork ())) {
    die "cannot fork: $!";
  } elsif ($childpid == 0) {

    # We are the child so it is safe to chroot:
    chroot ($vsdir);
    chdir ("/");

    rename ("/etc/mail/mailertable", "/tmp/mailertable");
    open (IN, "/tmp/mailertable");
    open (OUT, ">/etc/mail/mailertable");
    while (<IN>) {
      my $line = $_;
      if ($line =~ /$domainname/){
        #printf (OUT "%s\n", $line);
      } else {
        printf (OUT "%s\n", $line);
      }
    }
    close (IN);
    close (OUT);
    unlink ("/tmp/mailertable");

    `su - admin -c '/usr/bin/makemap hash /etc/mail/mailertable.db < /etc/mail/mailertable'`;

    system ("rm", "-r", "-f", "/etc/virtual/$domainname");
    system ("rm", "-r", "-f", "/etc/procmailrcs/virtual/$domainname");
    system ("rm", "-r", "-f", "/var/spool/virtual/$domainname");
    exit 0;
  } else {
    waitpid ($childpid, 0);
  }
}

