=head1 SYNOPSIS
-gatekeeper.pl -B<z> I<zone> [-B<d> I<debuglevel>]
+gatekeeper.pl [-B<c> I<config>] [-B<z> I<zone>] [-B<d> I<level>]
-gatekeeper.pl --B<zone> I<zone> [--B<debug> I<debuglevel>]
+gatekeeper.pl [--B<conf> I<config>] [--B<zone> I<zone>] [--B<debug> I<level>]
gatekeeper.pl --B<version>
Show version information and exit.
+=item B<--conf> I<file>
+
+=item B<--config> I<file>
+
+=item B<--configfile> I<file>
+
+Specify alternate configuration file. Default is C<gatekeeper.conf> in the
+same directory as this tool.
+
=item B<--zone>
Specify the zone to process. The "zone" selects a configuration subset for
my $want_help = '';
my $want_version = '';
+ my $ConfigFile = File::Spec->catfile($FindBin::Bin, 'gatekeeper.conf');
my $GPGV_Bin = '/usr/bin/gpgv';
my $LSOF_Bin = '/usr/bin/lsof';
my $TSTAMPCHECK = 1;
my $TestingMode = 0;
+ my $CheckConfigurationParse = 0;
GetOptions('help' => \$want_help,
'version' => \$want_version,
+ 'configfile|config|conf|c=s' => \$ConfigFile,
'zone|z|s=s' => \$ZONE,
'with-gpgv=s' => \$GPGV_Bin,
'with-lsof=s' => \$LSOF_Bin,
'nomail=i' => \$NOMAIL,
'debug|d=i' => \$DEBUG,
'testing-this-script' => \$TestingMode,
+ 'check-config-parse' => \$CheckConfigurationParse,
) or pod2usage(-verbose => 0, -exitval => 2);
constant->import(ZONE => $ZONE);
constant->import(GPGV_BIN => $GPGV_Bin);
constant->import(LSOF_BIN => $LSOF_Bin);
}
+
+ # Read the configuration file.
+ unless ($want_help || $want_version) {
+ # --help and --version should work even without a configuration file
+
+ if ($TestingMode) { # use hardwired test configuration
+ # Again, the test environment is trusted, but we still run in taint mode.
+ $ENV{TEST_BASE_DIR} =~ m/^([[:graph:] ]+$)/ && -d $1
+ or die "gatekeeper: test mode: TEST_BASE_DIR not valid";
+ my $base = $1; # untainted
+
+ our $email_blacklist = File::Spec->catfile($base, 'email.blacklist');
+ our $maintainers_bypkg = File::Spec->catfile($base, 'm.bypkg');
+
+ our $Public_Upload_Archive_Inbox = 'ftp-upload-report@gnu.org';
+ our $Internal_Report_Inbox = 'ftp-upload-script@gnu.org';
+
+ our $zone_tag = 'ftp';
+ our $Log_Tag = 'Test';
+
+ our $package_config_base =File::Spec->catdir($base, 'packages');
+ our $package_state_base = $base;
+ our $serials_path = File::Spec->catfile($base, 'serial.txt');
+
+ our $Inbox_dir = File::Spec->catdir($base, 'inbox');
+ our $Scratch_dir = File::Spec->catdir($base, 'scratch');
+ our $Stage_dir = File::Spec->catdir($base, 'stage');
+ our $Public_dir = File::Spec->catdir($base, 'pub');
+ our $Archive_dir = File::Spec->catdir($base, 'archive');
+ } else { # load configuration from file
+ my @zonelist = ();
+ my %ZoneConfig = ();
+ my %EmailConfig = ();
+
+ open my $config, '<', $ConfigFile
+ or die "gatekeeper: read config $ConfigFile: $!\n";
+
+ my $interesting = $ZONE ? undef : \%ZoneConfig;
+ while (<$config>) {
+ chomp;
+ next if m/^$/ || m/^\s*#/; # skip blank lines and comments
+ # collect configured zone names
+ push @zonelist, $1 if m/^\[zone[. ]([-_.[:alnum:]]+)\]/;
+
+ if (m/^\[([-_.[:alnum:]]*)\]/) {
+ # begin section
+ if ($1 eq 'email') { $interesting = \%EmailConfig }
+ elsif ($1 eq 'zone.'.$ZONE) { $interesting = \%ZoneConfig }
+ else { $interesting = undef }
+ } elsif (not defined $interesting) {
+ next
+ } elsif (m/^([-_.[:alnum:]]+)\s*=\s*(.*)$/) {
+ # store configuration option
+ $interesting->{$1} = $2;
+ } else
+ { die "gatekeeper: unrecognized configuration line $.: $_\n" }
+ }
+
+ close $config;
+
+ # Check if zones are configured and/or --zone given.
+ if (@zonelist and $ZONE eq '') {
+ die "gatekeeper: zones configured but --zone parameter not given\n"
+ .join(' ', 'gatekeeper: known zones:', @zonelist)."\n";
+ } elsif ($ZONE and not grep $_ eq $ZONE, @zonelist) {
+ die "gatekeeper: requested zone '$ZONE' not configured\n"
+ .join(' ', 'gatekeeper: known zones:', @zonelist)."\n";
+ }
+
+ our $email_blacklist = $EmailConfig{blacklist};
+ our $maintainers_bypkg = $EmailConfig{maintainermap};
+
+ our $Public_Upload_Archive_Inbox = $EmailConfig{archivebox};
+ our $Internal_Report_Inbox = $EmailConfig{internalbox};
+
+ our $zone_tag = $ZoneConfig{tag} || $ZONE || 'upload';
+ our $Log_Tag = $ZoneConfig{logtag} || ucfirst $ZONE || 'Upload';
+
+ our $package_config_base = $ZoneConfig{pkgconfdir};
+ our $package_state_base = $ZoneConfig{pkgstatedir};
+ our $serials_path;
+ $serials_path= File::Spec->catfile($ZoneConfig{pkgstatedir},
+ $ZoneConfig{serials})
+ if $ZoneConfig{pkgstatedir} && $ZoneConfig{serials};
+
+ our $Inbox_dir = $ZoneConfig{inboxdir};
+ our $Scratch_dir = $ZoneConfig{scratchdir};
+ our $Stage_dir = $ZoneConfig{stagedir};
+ our $Public_dir = $ZoneConfig{publicdir};
+ our $Archive_dir = $ZoneConfig{archivedir};
+ }
+
+ if ($CheckConfigurationParse) {
+ our $email_blacklist; our $maintainers_bypkg;
+ our $Public_Upload_Archive_Inbox; our $Internal_Report_Inbox;
+ our $zone_tag; our $Log_Tag; our $serials_path;
+ our $package_config_base; our $package_state_base;
+ our $Inbox_dir; our $Scratch_dir;
+ our $Stage_dir; our $Public_dir; our $Archive_dir;
+
+ if ($ZONE) {
+ print "# gatekeeper configuration as parsed for zone $ZONE:\n\n";
+ } else {
+ print "# gatekeeper configuration as parsed:\n\n";
+ }
+ print "[zone.$ZONE]\n" if $ZONE;
+ foreach my $item ([tag => $zone_tag], [logtag => $Log_Tag],
+ [pkgconfdir => $package_config_base],
+ [pkgstatedir => $package_state_base],
+ [inboxdir => $Inbox_dir], [scratchdir => $Scratch_dir],
+ [stagedir => $Stage_dir], [publicdir => $Public_dir],
+ [archivedir => $Archive_dir])
+ { print $item->[0],' = ',$item->[1],"\n" if $item->[1] }
+ if ($email_blacklist || $maintainers_bypkg
+ || $Public_Upload_Archive_Inbox || $Internal_Report_Inbox) {
+ print "\n[email]\n";
+ print "blacklist = $email_blacklist\n" if $email_blacklist;
+ print "maintainermap = $maintainers_bypkg\n" if $maintainers_bypkg;
+ print "\n"
+ if ($email_blacklist || $maintainers_bypkg)
+ && ($Public_Upload_Archive_Inbox || $Internal_Report_Inbox);
+ print "archivebox = $Public_Upload_Archive_Inbox\n"
+ if $Public_Upload_Archive_Inbox;
+ print "internalbox = $Internal_Report_Inbox\n"
+ if $Internal_Report_Inbox;
+ }
+ print "\n# END\n";
+ }
+
+ # Verify that all required configuration parameters are set
+ {
+ our $email_blacklist; our $maintainers_bypkg;
+ our $Public_Upload_Archive_Inbox; our $Internal_Report_Inbox;
+ our $zone_tag; our $Log_Tag; our $serials_path;
+ our $package_config_base; our $package_state_base;
+ our $Inbox_dir; our $Scratch_dir;
+ our $Stage_dir; our $Public_dir; our $Archive_dir;
+
+ my $ok = 1;
+
+ foreach my $item ([pkgconfdir => $package_config_base],
+ [pkgstatedir => $package_state_base],
+ [inboxdir => $Inbox_dir], [scratchdir => $Scratch_dir],
+ [stagedir => $Stage_dir], [publicdir => $Public_dir],
+ [archivedir => $Archive_dir]) {
+ unless ($item->[1]) {
+ $ok = 0;
+ print "gatekeeper: configuration parameter not set: $item->[0]\n";
+ }
+ }
+
+ die "gatekeeper: required configuration parameter(s) not set\n"
+ unless $ok;
+ }
+
+ exit 0 if $CheckConfigurationParse;
+
+ } # end of configuration handling skipped for --help and --version
}
if (WANT_VERSION) {
}
pod2usage(-verbose => 1, -exitval => 0) if WANT_HELP;
-pod2usage(-message => 'ERROR: Required parameter not given or invalid.',
- -verbose => 0, -exitval => 2)
- if ((ZONE ne 'ftp') && (ZONE ne 'alpha') && (ZONE ne 'distros'));
-
-my $zone_tag = 'ftp';
-$zone_tag = 'alpha' if (ZONE eq 'alpha');
-$zone_tag = 'gnu+linux-distros' if (ZONE eq 'distros');
-
-# Settings to configure:
-my $package_config_base = "/home/gatekpr/packages";
-{
- # where ftpd deposits the files for us to look at:
- our $Inbox_dir = "/home/upload/incoming/$zone_tag";
- # private dir on SAME FILESYSTEM as $Inbox_dir:
- our $Scratch_dir = "/var/tmp/$zone_tag-in";
- # top-level public ftp dir for installing files:
- our $Public_dir = "/home/$zone_tag/gnu";
- $Public_dir = "/home/ftp/$zone_tag"
- if ($zone_tag eq 'gnu+linux-distros'); # The distros go here
- # private dir on SAME FILESYSTEM as $Public_dir:
- our $Archive_dir = "/home/gatekpr/$zone_tag-archived";
- # private dir on SAME FILESYSTEM as $Public_dir:
- our $Stage_dir = "/var/tmp/$zone_tag-out";
-}
-
-# We sometimes want to exclude e-mail addresses from being emailed.
-# Specifically, e-mail addresses we import from gpg keys - keys are still
-# valid but associated e-mail addresses are not. Ward, 2011-02-08.
-my $email_blacklist = "/home/gatekpr/etc/email_blacklist";
-
-# List of all package maintainers
-my $maintainers_bypkg = "/home/gatekpr/etc/maintainers.bypkg";
-
-# E-mail addresses
-{
- # - public archive of successful upload reports and some errors
- our $Public_Upload_Archive_Inbox = 'ftp-upload-report@gnu.org';
- # - unmoderated collector of other errors and copies of some reports
- our $Internal_Report_Inbox = 'ftp-upload-script@gnu.org';
-}
-
-my $serials_path = "/home/gatekpr/etc/upload-ftp-serials.txt";
+# temporary scaffolding
+our $zone_tag;
+our $package_config_base;
+our $email_blacklist;
+our $maintainers_bypkg;
+our $serials_path;
# syslog destination
use constant SYSLOG_APP_IDENT => 'gatekeeper';
use constant SYSLOG_FACILITY => 'LOCAL5';
-if (IN_TEST_MODE) { # override the above for testing
- # override file paths to our testcase environment
- {
- # Again, the test environment is trusted, but we still run in taint mode.
- $ENV{TEST_BASE_DIR} =~ m/^([[:graph:] ]+$)/ && -d $1
- or die "gatekeeper: test mode: TEST_BASE_DIR not valid";
- my $base = $1; # untainted
-
- $package_config_base = File::Spec->catdir($base, 'packages');
-
- our $Inbox_dir = File::Spec->catdir($base, 'inbox');
- our $Scratch_dir = File::Spec->catdir($base, 'scratch');
- our $Stage_dir = File::Spec->catdir($base, 'stage');
- our $Public_dir = File::Spec->catdir($base, 'pub');
- our $Archive_dir = File::Spec->catdir($base, 'archive');
-
- $email_blacklist = File::Spec->catfile($base, 'email.blacklist');
- $maintainers_bypkg = File::Spec->catfile($base, 'm.bypkg');
- $serials_path = File::Spec->catfile($base, 'serial.txt');
- }
+if (IN_TEST_MODE) {
# verify mock gpgv
{
open my $gpgv,'-|',GPGV_BIN, '--version'
=cut
{
- # To identify which zone is being processed, ftp_syslog will prepend
- # this, inside parentheses, to all messages logged.
- if (IN_TEST_MODE) {
- # override log message tag
- our $Log_Tag = 'Test';
- } else {
- our $Log_Tag = 'GNU';
- $Log_Tag = 'Alpha' if (ZONE eq 'alpha');
- $Log_Tag = 'Distros' if (ZONE eq 'distros');
- }
-
# If this is set to a defined value, ftp_syslog will prepend it, inside
# square brackets, to all messages logged.
our $Phase = undef; # should be set using local