#!/usr/bin/perl
###########################################################################
#
# $Id: rpmproc,v 1.10 2001/11/25 20:26:34 vdanen Exp $
# copyright (c) 2000 Vincent Danen <vdanen@mandrakesoft.com>
# copyright (c) 2001 Vincent Danen <vdanen@mandrakesoft.com> and
#                    Guillaume Rousse <rousse@ccr.jussieu.fr>
# 
#
# USAGE:
#
#   flags:
#       -c|--config	use an alternate config file
#   actions:
#       -h|--help	display help message and stop
#       -d|--dump	dump configuration and stop
#       -a|--arch	process i386/i586/i686 RPMs
#       -n|--noarch	process noarch RPMs
#       -l|--local	upload to local RPMs dir
#       -r|--remote	upload to remote RPMs dir
#       -m|--mail	announce changelog to mailing list
#
###########################################################################
#
# rpmproc 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.
#
# rpmproc 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 rpmproc; see the file COPYING.  If not, write to the
# Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
###########################################################################

use Mail::Sendmail;
use Net::FTP;
use Net::SCP;
use Net::SSH qw(ssh);
use File::Path;
use File::Copy;
use File::Basename;
use Getopt::Long;

# Set Global Variables

$VERSION  = "1.10";
$DATE     = "Nov 25, 2001";
$MAIN_CONF = "/etc/rpmproc.conf";
$HOME_CONF = $ENV{HOME} . "/.rpmprocrc";

# Force US locales to avoid date localization when invoking rpm
$ENV{LC_ALL}=C;

# get command line arguments
GetOptions(
  "c|config=s" => \$config,
  "h|help" => \$help,
  "d|dump" => \$dump,
  "a|arch" => \$arch,
  "n|noarch" => \$noarch,
  "l|local" => \$local,
  "r|remote" => \$remote,
  "m|mail" => \$mail
);

# parse each config file
if (-e $MAIN_CONF) {
  &parse_conf($MAIN_CONF);
}
if (-e $HOME_CONF) {
  &parse_conf($HOME_CONF);
}
if ($config) {
  &parse_conf($config);
}

# init values from configuration
&init();

# let's go...
if ($dump) {
  &dump();
}
if ($help) {
  &help();
}
foreach $rpm (@ARGV) {
  if ($arch) {
    &arch($rpm);
  }
  if ($noarch) {
    &noarch($rpm);
  }
  if ($local) {
    &local($rpm);
  }
  if ($remote) {
    &remote($rpm);
  }
  if ($mail) {
    &mail($rpm);
  }
}

# sub routines

sub msgid {
  @currtime = localtime(time());
  @from = split(/\@/,$MAIL_FROM);
  return "<" . $currtime[5] . $currtime[4] . $currtime[3] . $currtime[2] . $currtime[1] . $currtime[0] . "\@" . $from[1] . ">\n";
}

sub init {
  # get hash of package types
  %PATTERNS = (
    source => "\.src\.rpm",
    binary => "\.((i\d86)|(noarch))\.rpm",
    all    => "\.rpm",
    noarch => "\.noarch\.rpm",
    i386   => "\.i386\.rpm",
    i486   => "\.i486\.rpm",
    i586   => "\.i586\.rpm",
    i686   => "\.i686\.rpm"
  );
  # get array of arch types
  @build_arch = split(/\,/,$BUILD_ARCH);
  $archnum = @build_arch;
  $count = 0;
  @TYPE = ("SRPMS", "RPMS/noarch");
  while ($count <= ($archnum -1)) {
    @TYPE = (@TYPE, "RPMS/$build_arch[$count]");
    $count++;
  }
}

sub parse_conf {
  $conf = shift;

  # read from configuration file
  unless (open(CONF, $conf)) {
    die ("Can't open configuration file $conf.\n");
  }
  
  while ($line = <CONF>) {
    chop($line);
    if ($line ne "") {
      if ($line =~ /^\#/) {
        #this is a comment so ignore it
      } else {
        @inline = split(/=/,$line);
        if ($inline[0] =~ /^ROOT_RPM$/i) {
          $ROOT_RPM = $inline[1];
	} elsif ($inline[0] =~ /^VERBOSE$/i) {
  	  $VERBOSE = $inline[1];
        } elsif ($inline[0] =~ /^BUILD_ARCH$/i) {
          $BUILD_ARCH = $inline[1];
        } elsif ($inline[0] =~ /^BUILD_CLEANFILES$/i) {
          $BUILD_CLEANFILES = $inline[1];
	} elsif ($inline[0] =~ /^BUILD_CLEANSOURCES$/i) {
          $BUILD_CLEANSOURCES = $inline[1];
        } elsif ($inline[0] =~ /^BUILD_PGP$/i) {
          $BUILD_PGP = $inline[1];
        } elsif ($inline[0] =~ /^BUILD_RPMLINT$/i) {
          $BUILD_RPMLINT = $inline[1];
        } elsif ($inline[0] =~ /^BUILD_RPMTARGET$/i) {
          $BUILD_RPMTARGET = $inline[1];
          if ($BUILD_RPMTARGET == 1) {
            $target_string = " ";
          } else {
            $target_string = "=";
          }
        } elsif ($inline[0] =~ /^LOCAL_BASEDIR$/i) {
          $LOCAL_BASEDIR = $inline[1];
        } elsif ($inline[0] =~ /^LOCAL_NAMEDIR$/i) {
          $LOCAL_NAMEDIR = $inline[1];
        } elsif ($inline[0] =~ /^LOCAL_SUBDIR$/i) {
          $LOCAL_SUBDIR = $inline[1];
        } elsif ($inline[0] =~ /^LOCAL_UMASK$/i) {
          $LOCAL_UMASK = $inline[1];
	} elsif ($inline[0] =~ /^LOCAL_GROUP$/i) {
          $LOCAL_GROUP = $inline[1];
        } elsif ($inline[0] =~ /^LOCAL_TYPE$/i) {
          $LOCAL_TYPE = $inline[1];
        } elsif ($inline[0] =~ /^LOCAL_CLEAN$/i) {
          $LOCAL_CLEAN = $inline[1];
        } elsif ($inline[0] =~ /^LOCAL_MD5SUM$/i) {
          $LOCAL_MD5SUM = $inline[1];
	} elsif ($inline[0] =~ /^REMOTE_AGENT$/i) {
          $REMOTE_AGENT = $inline[1];
	} elsif ($inline[0] =~ /^REMOTE_HOST$/i) {
          $REMOTE_HOST = $inline[1];
	} elsif ($inline[0] =~ /^REMOTE_USER$/i) {
          $REMOTE_USER = $inline[1];
	} elsif ($inline[0] =~ /^REMOTE_PASSWORD$/i) {
          $REMOTE_PASSWORD = $inline[1];
	} elsif ($inline[0] =~ /^REMOTE_BASEDIR$/i) {
          $REMOTE_BASEDIR = $inline[1];
        } elsif ($inline[0] =~ /^REMOTE_NAMEDIR$/i) {
          $REMOTE_NAMEDIR = $inline[1];
        } elsif ($inline[0] =~ /^REMOTE_SUBDIR$/i) {
          $REMOTE_SUBDIR = $inline[1];
        } elsif ($inline[0] =~ /^REMOTE_UMASK$/i) {
          $REMOTE_UMASK = $inline[1];
	} elsif ($inline[0] =~ /^REMOTE_GROUP$/i) {
          $REMOTE_GROUP = $inline[1];
        } elsif ($inline[0] =~ /^REMOTE_TYPE$/i) {
          $REMOTE_TYPE = $inline[1];
        } elsif ($inline[0] =~ /^REMOTE_CLEAN$/i) {
          $REMOTE_CLEAN = $inline[1];
        } elsif ($inline[0] =~ /^MAIL_SMTP$/i) {
          $MAIL_SMTP = $inline[1];
        } elsif ($inline[0] =~ /^MAIL_LIST$/i) {
          $MAIL_LIST = $inline[1];
        } elsif ($inline[0] =~ /^MAIL_FROM$/i) {
          $MAIL_FROM = $inline[1];
        } elsif ($inline[0] =~ /^MAIL_TRAILER$/i) {
          $MAIL_TRAILER = $inline[1];
        } elsif ($inline[0] =~ /^MAIL_HEADER$/i) {
  	  $MAIL_HEADER = $inline[1];
        }
      }
    }
  }
  close(CONF);
}

sub destination_dir {
  $rpm = shift;
  $basedir = shift or ".";
  $namedir = shift or "0";
  $subdir = shift;

  $dir = $basedir;
  if ($namedir == 1) {
    $dir .= "/" . $rpm;
  }
  if ($subdir) {
    $dir .= "/" . $subdir;
  }
 
  return $dir;
}

sub rpm_list {
  $rpm = shift;
  $type = shift or "all";

  $pattern = "^(lib)?$rpm([0-9\.]*)?-.*$PATTERNS{$type}\$";
  foreach $T (@TYPE) {
    opendir(DIR, "$ROOT_RPM/$T") or die "Can't open $ROOT_RPM/$T";
    while ($file = readdir(DIR)) {
        if ($file =~ /$pattern/) {
	  push (@rpms, "$ROOT_RPM/$T/$file");
        }
      }
    closedir(DIR);
  }

  return @rpms;
}

sub rpmlint {
  $file = shift;
  if (-e "/usr/bin/rpmlint") {
    if (-e $file) {
      print "\nChecking $file with rpmlint...\n\n";
      system("rpmlint $file");
    } else {
      print "\nFile $file doesn't exist!  Aborting!\n\n";
      exit(1);
    }
  } else {
    print "\n/usr/bin/rpmlint doesn't exist!  Are you sure rpmlint is installed?\n\n";
    exit(1);
  }
}

# main routines

sub remote {
  $name = shift;
  print "Uploading $name to $REMOTE_HOST...\n";

  # determine exact destination dir
  $dir = &destination_dir($name, $REMOTE_BASEDIR, $REMOTE_NAMEDIR, $REMOTE_SUBDIR);

  # determine rpm list
  @rpms = &rpm_list($rpm, $REMOTE_TYPE);

  if ($REMOTE_AGENT eq "ftp") {
    # connection
    ($VERBOSE == 1) && print "Connection to $REMOTE_HOST\n";
    $ftp = Net::FTP->new($REMOTE_HOST) or die "Can't connect to $REMOTE_HOST: $@\n";
    $ftp->login($REMOTE_USER, $REMOTE_PASSWORD) or die "Can't login\n";
    $ftp->binary() or die "Can't set binary mode\n";

    # directory check
    if ($ftp->cwd($dir)) {
      if ($REMOTE_CLEAN == 1) {
	@files = $ftp->ls(".");
	$pattern = "^(lib)?$rpm([0-9\.]*)?-.*$PATTERNS{all}\$";
	foreach $file (@files) {
	  if ($file =~ /$pattern/) {
	    ($VERBOSE == 1) && print "Deleting file $file\n";
	    $ftp->delete($file) or warn "Can't delete file $file\n";
	  }
	}
      }
    } else {
      ($VERBOSE == 1) && print "Creating directory $dir\n";
      $ftp->mkdir($dir, 1) or die "Can't create directory $dir\n";
      $ftp->cwd($dir) or die "Can't go in newly created $dir\n";
    }

    # files transfer
    foreach $rpm (@rpms) {
      ($VERBOSE == 1) && print "Transfering rpm " . basename($rpm) . "\n";
      $ftp->put($rpm) or die "Can't transfer rpm $rpm\n";
    }

    # quit
    $ftp->quit() or warn "Couldn't quit gracefuly\n";
  } elsif ($REMOTE_AGENT eq "scp") {
    # transfer script creation
    $script = "transfer.sh";
    open(SCRIPT, "> $script") or die "Can't create script $script: $!";
    print SCRIPT "#/bin/sh\n";
    print SCRIPT "# script generated by rpmproc\n";
    print SCRIPT "\n";
    print SCRIPT "umask $REMOTE_UMASK\n";
    print SCRIPT "dir=$dir\n";
    print SCRIPT "rpms=\"";
    foreach $rpm (@rpms) {
      print SCRIPT basename($rpm) . " ";
    }
    print SCRIPT "\"\n";
    print SCRIPT "\n";
    print SCRIPT "if [ ! -d \$dir ]; then\n";
    print SCRIPT "    mkdir -p \$dir\n";
    if ($REMOTE_GROUP) {
        print SCRIPT "    chgrp $REMOTE_GROUP \$dir\n";
    }
    if ($REMOTE_CLEAN == 1) {
        print SCRIPT "else\n";
        print SCRIPT "    rm -f \$dir/*$rpm*.rpm\n";
    }
    print SCRIPT "fi\n";
    print SCRIPT "\n";
    print SCRIPT "for rpm in \$rpms; do\n";
    print SCRIPT "    touch \$dir/\$rpm\n";
    print SCRIPT "    cp -f \$rpm \$dir\n";
    print SCRIPT "    rm -f \$rpm\n";
    if ($REMOTE_GROUP) {
        print SCRIPT "    chgrp $REMOTE_GROUP \$dir/\$rpm\n";
    }
    print SCRIPT "done\n";
    print SCRIPT "\n";
    print SCRIPT "rm -f \$0\n";
    close(SCRIPT);
    # connection
    ($VERBOSE == 1) && print "Connection to $REMOTE_HOST\n";
    $scp = Net::SCP->new($REMOTE_HOST, $REMOTE_USER) or die "Can't connect to $REMOTE_HOST: $@\n";
    # files transfer
    foreach $rpm (@rpms) {
      ($VERBOSE == 1) && print "Transfering rpm " . basename($rpm) . "\n";
      $scp->put($rpm) or die "Can't transfer rpm $rpm: $scp->{errstr}\n";
    }
    ($VERBOSE == 1) && print "Transfering script $script\n";
    $scp->put($script) or die "Can't transfer script $script: $scp->{errstr}\n";
    # remote script execution
    ($VERBOSE == 1) && print "Executing script $script\n";
    # Altough working correctly, this keeps returning an infamous ssh error message, so i disabled the error sequence here
    # ssh("$REMOTE_USER\@$REMOTE_HOST", "sh $script") or die "Can't execute script $script: $!\n";
    ssh("$REMOTE_USER\@$REMOTE_HOST", "sh $script");
    # cleanup
    unlink $script or die "Can't delete script $file\n";
  } else {
    print "Configuration error.  Invalid value for Delivery Agent.  Please fix.\n\n";
    exit(1);
  }
}

sub local {
  $name = shift;
  print "Uploading $name localy...\n";

  # force umask
  umask oct($LOCAL_UMASK);

  # get new gid if needed
  if ($LOCAL_GROUP) {
    $gid = getgrnam($LOCAL_GROUP) or die "No such group: $LOCAL_GROUP\n";
  }

  # determine exact destination dir
  $dir = &destination_dir($name, $LOCAL_BASEDIR, $LOCAL_NAMEDIR, $LOCAL_SUBDIR);

  # determine rpm list
  @rpms = &rpm_list($name, $LOCAL_TYPE);
  
  # directory check
  if (-d $dir) {
    if ($LOCAL_CLEAN == 1) {
      $pattern = "^(lib)?$rpm([0-9\.]*)?-.*$PATTERNS{all}\$";
      opendir(DIR, $dir) or die "Can't open directory $dir\n";
      while ($file = readdir(DIR)) {
        if ($file =~ /$pattern/) {
	($VERBOSE == 1) && print "Deleting file $file\n";
	unlink "$dir/$file" or die "Can't delete file $file\n";
        }
      }
      closedir(DIR);
    }
  } else {
    ($VERBOSE == 1) && print "Creating directory $dir\n";
    mkpath($dir) or die  "Cant' create directory $dir\n";
    if ($gid) {
      ($VERBOSE == 1) && print "Changing $dir group to $LOCAL_GROUP\n";
      chown -1, $gid, $dir or die "Can't change dir group to $LOCAL_GROUP\n" ;
    }
  }
  
  # files transfer
  foreach $rpm (@rpms) {
    ($VERBOSE == 1) && print "Transfering rpm " . basename($rpm) . "\n";
    copy($rpm, $dir) or die "Can't transfer rpm " . basename($rpm) . "\n";
    if ($gid) {
      $transfered_rpm = $dir . "/" . basename($rpm);
      ($VERBOSE == 1) && print "Changing $transfered_rpm group to $LOCAL_GROUP\n";
      chown -1, $gid, $transfered_rpm or die "Can't change $transfered_rpm group to $LOCAL_GROUP\n" ;
    }
  }

  # add MD5SUM if needed
  if ($LOCAL_MD5SUM == 1) {
    ($VERBOSE == 1) && print "Creating md5sum file\n";
    system("rm -f $dir/md5sum; (cd $dir; md5sum * > md5sum)");
  }
}

sub mail {
  $name = shift;
  print "Announcing $name changelog to $MAIL_LIST.\n";

  # find src rpm
  $rpm = (&rpm_list($name, "source"))[0];

  @changelog = split(/\*/,`rpm -qp --changelog $rpm`);
  $maintain = `rpm -qp --queryformat '%{PACKAGER}' $rpm`;
  $description = `rpm -qpi $rpm`;
  ($name, $version, $release) = split(/ /,`rpm -qp --queryformat '%{NAME} %{VERSION} %{RELEASE}' $rpm`);

  if (@changelog) {

    if ($MAIL_SMTP) {
      $msgid = &msgid();
      $Mail::Sendmail::mailcfg{mime} = 0;
      %mail = (
	       smtp         => $MAIL_SMTP,
	       To           => $MAIL_LIST,
	       From         => $MAIL_FROM,
	       'Reply-To'   => $MAIL_FROM,
               'Message-ID' => $msgid,
               'X-Mailer'   => "rpmproc $VERSION",
	      );
      $mail{"Subject: "} = "[RPM] $name-$version-$release";
      $mail{"Message: "} .= $MAIL_HEADER . "\n\n";
      $mail{"Message: "} .= "-------\n$description\n-------\n\n";
      if (@changelog) {
	$mail{"Message: "} .= "$changelog[1]";
      } else {
	$mail{"Message: "} .= "Nothing =( ......\n";
      }
      $mail{"Message: "} .= "-- \n$MAIL_TRAILER\n";
      sendmail(%mail) or die $Mail::Sendmail::error;
    } else {
      print "Configuration error.  Invalid value for MAIL_SMTP.  Please fix.\n\n";
      exit(1);
    }
  } else {
    print "Body of the message is empty.  Not mailing.  Non-existant RPM?\n\n";
    exit(1);
  }
}

sub noarch {
  $name = shift;
  $opwd=`pwd`;
  chdir ("$ROOT_RPM/SPECS");
  if (!-e $name . ".spec") {
    print "specfile $name.spec doesn't exist.  Aborting.\n\n";
    exit(1);
  }
  if ($BUILD_CLEANFILES == 1) {			# clean old RPMs
    foreach $rpm (rpm_list($name, "all")) {
      ($VERBOSE == 1) && print "Deleting file $rpm\n";
      unlink $rpm or die "Can't delete file $rpm\n";
    }
  }
  $targets = join($target_string,"--target","noarch");
  if ($BUILD_PGP == 1) {			# build with PGP/GPG signing
    system("rpm -bb --sign $targets $name.spec");
  } else {		# build without PGP/GPG signing
    system("rpm -bb $targets $name.spec");
  }
  # clean source and specs if requested, do this by rebuilding srpm
  if ($BUILD_CLEANSOURCES == 1) {
    print "Building source and cleaning .spec file and source files...\n";
    if ($BUILD_PGP == 1) {
      system("rpm -bs --sign --rmspec --rmsource $name.spec");
    } else {
      system("rpm -bs --rmspec --rmsource $name.spec");
    }
  } else {
    print "Building source...\n";
    if ($BUILD_PGP == 1) {
      system("rpm -bs --sign $name.spec");
    } else {
      system("rpm -bs $name.spec");
    }
  }

  if ($BUILD_RPMLINT == 1) {
    $pattern = "^$name-.*rpm\$";
    opendir(DIR, "$ROOT_RPM/RPMS/noarch") || break;
    while ($file = readdir(DIR)) {
      if ($file =~ /$pattern/) {
        &rpmlint("$ROOT_RPM/RPMS/noarch/$file");
      }
    }
  }
  chdir ("$opwd");
}

sub arch {
  $name = shift;
  $opwd=`pwd`;
  chdir ("$ROOT_RPM/SPECS");
  if (!-e $name . ".spec") {
    print "specfile $name.spec doesn't exist.  Aborting.\n\n";
    exit(1);
  } 
  if ($BUILD_CLEANFILES == 1) {			# clean old RPMs
    foreach $rpm (rpm_list($name, "all")) {
      ($VERBOSE == 1) && print "Deleting file $rpm\n";
      unlink $rpm or die "Can't delete file $rpm\n";
    }
  }
  if ($BUILD_PGP == 1) {			# build with PGP/GPG signing
    $count = 0;
    foreach $T (@TYPE) {
      @target = split(/\//,$T);
      if ($target[1] ne "noarch" && $target[1] ne "") {
        $targets = join($target_string,"--target",$target[1]);
        system("rpm -bb --sign $targets $name.spec");
      }
    }
  } else {		# build without PGP/GPG signing
    $count = 0;
    foreach $T (@TYPE) {
      @target = split(/\//,$T);
      if ($target[1] ne "noarch" && $target[1] ne "") {
        $targets = join($target_string,"--target",$target[1]);
        system("rpm -bb $targets $name.spec");
      }
    }
  }
  # clean source and specs if requested, do this by rebuilding srpm
  if ($BUILD_CLEANSOURCES == 1) {
    print "Building source and cleaning .spec file and source files...\n";
    if ($BUILD_PGP == 1) {
      system("rpm -bs --sign --rmspec --rmsource $name.spec");
    } else {
      system("rpm -bs --rmspec --rmsource $name.spec");
    }
  } else {
    print "Building source...\n";
    if ($BUILD_PGP == 1) {
      system("rpm -bs --sign $name.spec");
    } else {
      system("rpm -bs $name.spec");
    }
  }

  if ($BUILD_RPMLINT == 1) {
    $pattern = "^$name-.*rpm\$";
    opendir(DIR, "$ROOT_RPM/$TYPE[2]") || break;
    while ($file = readdir(DIR)) {
      if ($file =~ /$pattern/) {
        &rpmlint("$ROOT_RPM/$TYPE[2]/$file");
      }
    }
  }
  chdir("$opwd");
}

sub help {
  print "\nrpmproc v$VERSION    $DATE\n\n";
  print "usage: rpmproc [flags] [actions] [packages]\n\n";
  print "  flags are:\n";
  print "    [-c|--config <file>] uses <file> as an additional config file\n\n";
  print "  actions are:\n";
  print "    [-h|--help]          display this help message and stop\n";
  print "    [-d|--dump]          dump configuration information and stop\n";
  print "    [-a|--arch]          build arch-independant files\n";
  print "    [-n|--noarch]        build noarch files\n";
  print "    [-l|--local]         upload to local RPMs dir\n";
  print "    [-r|--remote]        upload to remote RPMs dir\n";
  print "    [-m|--mail]          announce changelog to mailing list\n\n";
  print "  packages is the list of packages to process\n\n";
  exit(0);
}

sub dump {
  print "\nrpmproc v$VERSION    $DATE\n\n";
  print "Configuration dump for debugging purposes\n\n";
  print "  General configuration:\n";
  print "    Root RPM directory: $ROOT_RPM\n";
  print "    Be verbose:         " . (($VERBOSE == 1) ? "yes" : "no") . "\n";
  print "\n";
  print "  Build Configuration:\n";
  print "    Use PGP/GnuPG:      " . (($BUILD_PGP == 1) ? "yes" : "no") . "\n";
  print "    Clean files:        " . (($BUILD_CLEANFILES == 1) ? "yes" : "no") . "\n";
  print "    Clean sources:      " . (($BUILD_CLEANSOURCES == 1) ? "yes" : "no") . "\n";
  print "    Use rpmlint:        " . (($BUILD_RPMLINT == 1) ? "yes" : "no") . "\n";
  print "    Target RPM:         " . (($BUILD_RPMTARGET == 1) ? ">=4.0.3" : "<4.0.3") . "\n";
  print "    Build for archs:    ";
  foreach $T (@TYPE) {
    @target = split(/\//,$T);
    if ($target[0] eq "RPMS") {
      print "$target[1] ";
    }
  }
  print "\n";
  print "\n";
  print "  Local upload configuration:\n";
  print "    Base directory:     $LOCAL_BASEDIR\n";
  print "    Use name directory: " . (($LOCAL_NAMEDIR == 1) ? "yes" : "no") . "\n";
  print "    Sub directory:      $LOCAL_SUBDIR\n";
  print "    Clean files:        " . (($LOCAL_CLEAN == 1) ? "yes" : "no") . "\n";
  print "    Umask:              $LOCAL_UMASK\n";
  print "    Group:              $LOCAL_GROUP\n";
  print "    Type:               $LOCAL_TYPE\n";
  print "    Use md5sum:         " . (($LOCAL_MD5SUM == 1) ? "yes" : "no") . "\n";
  print "\n";
  print "  Remote upload configuration:\n";
  print "    Remote agent:       " . ((($REMOTE_AGENT eq "ftp") || ($REMOTE_AGENT eq "scp")) ? $REMOTE_AGENT : "error") . "\n";
  print "    Remote host:        $REMOTE_HOST\n";
  print "    Remote user:        $REMOTE_USER\n";
  print "    Remote password:    $REMOTE_PASSWORD\n";
  print "    Base directory:     $REMOTE_BASEDIR\n";
  print "    Use name directory: " . (($REMOTE_NAMEDIR == 1) ? "yes" : "no") . "\n";
  print "    Sub directory:      $REMOTE_SUBDIR\n";
  print "    Clean files:        " . (($REMOTE_CLEAN == 1) ? "yes" : "no") . "\n";
  print "    Umask:              $REMOTE_UMASK\n";
  print "    Group:              $REMOTE_GROUP\n";
  print "    Type:               $REMOTE_TYPE\n";
  print "\n";
  print "  Changelog configuration:\n";
  print "    SMTP server:        $MAIL_SMTP\n";
  print "    Destinations list:  $MAIL_LIST\n";
  print "    Email is from:      $MAIL_FROM\n";
  print "    Email header:\n     $MAIL_HEADER\n";
  print "    Email trailer:\n    $MAIL_TRAILER\n";
  exit(0);
}
