summaryrefslogtreecommitdiffstats
path: root/debian/a2query.in
diff options
context:
space:
mode:
Diffstat (limited to 'debian/a2query.in')
-rwxr-xr-xdebian/a2query.in426
1 files changed, 426 insertions, 0 deletions
diff --git a/debian/a2query.in b/debian/a2query.in
new file mode 100755
index 0000000..f9f1a91
--- /dev/null
+++ b/debian/a2query.in
@@ -0,0 +1,426 @@
+#! /usr/bin/perl
+
+# a2query - Apache2 helper to retrieve configuration informations
+# Copyright (C) 2012 Arno Töll <debian@toell.net>
+#
+# This program is licensed at your choice under the terms of the GNU General
+# Public License version 2+ or under the terms of the Apache Software License
+# 2.0.
+#
+# For GPL-2+:
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+#
+# For ASF 2.0:
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+use feature "switch";
+use strict;
+use Getopt::Std;
+
+=head1 NAME
+
+a2query - retrieve runtime configuration from a local Apache 2 HTTP server
+
+=cut
+
+
+our $APACHE2 = "apache2ctl";
+our $API = "__API__";
+our $MODULE_DIR = "__MODULE_DIR__";
+our $SERVER_VERSION = "__SERVER_VERSION__";
+our $MODULE_DIR = "/usr/lib/apache2/modules/";
+our $STATE_DIR = "/var/lib/apache2";
+our @STATES = ("maint", "admin");
+
+our $MPM = "invalid";
+our $CONFIG_DIR = "/etc/apache2";
+our $QUIET = 0;
+
+# time to introduce more _exit_ values
+our $E_OK = '0';
+our $E_FOUND = '0';
+our $E_NOTFOUND = '1';
+our $E_OFFBYADMIN = '32';
+our $E_OFFBYMAINT = '33';
+our @RETVALS = ( $E_OK, $E_FOUND, $E_OFFBYADMIN, $E_NOTFOUND, $E_OFFBYMAINT );
+
+our @MODULES = ();
+our @CONFS = ();
+our @SITES =();
+our @HELP = ();
+our %verbose_state = ( 'admin' => 'site administrator', 'maint' => 'maintainer script', 'unknown' => 'unknown' );
+
+=head1 SYNOPSIS
+
+B<a2query> [S<-m> [I<MODULE>]] [S<-s> [I<SITE>]] [S<-c> [I<CONF>]] [S<-a>] [S<-v>]
+[S<-M>] [S<-d>] [S<-h>]
+
+=head1 DESCRIPTION
+
+B<a2query> is a program designed to retrieve configuration values from a locally
+available Apache 2 HTTP web server. It was designed to be as robust as possible
+by returning feasible values even if the Apache 2 syntax validator fails.
+
+This program is primarily meant to be used from maintainer scripts.
+
+=head1 OPTIONS
+
+=over 4
+
+=item S<-a>
+
+Returns the Apache 2 "Module Magic Version" (API version) number, the server was
+compiled with. The returned version does not contain any minor versions which
+are known to be compatible with the major version returned.
+
+=item S<-c> [I<CONF>]
+
+Checks whether the configuration I<CONF> is enabled. If no argument was given,
+all enabled configuration files are being returned. I<CONF> is compared by
+string comparison by ignoring a leading "mod_" prefix and possibly a '.conf' or
+'.load' suffix.
+
+=item S<-h>
+
+Displays a brief summary how the program can be called and exits.
+
+=item S<-m> [I<MODULE>]
+
+Checks whether the module I<MODULE> is enabled, The argument is interpreted in
+the same way, as for configuration files queried by the S<-c> switch.
+
+=item S<-M>
+
+Returns the currently enabled Apache 2 MPM (Multi Processing Module).
+
+=item S<-s> [I<SITE>]
+
+Checks whether the module I<SITE> is enabled, The argument is interpreted in
+the same way, as for configuration files queried by the S<-c> switch.
+
+
+=item S<-v>
+
+returns the currently installed Apache 2 HTTP server version
+
+=item S<-q>
+
+suppress any output. This is useful to invoke a2query from another script. This
+is useful if only the return code is of interest.
+
+=back
+
+=head1 EXIT CODES
+
+B<a2query> returns with a zero (S<0>) exit status if the requested operation was
+effectuated successfully and with a non-zero status otherwise. In case of an
+error it leaves with error code S<32> if a requested module, site or
+configuration was not found and S<33> if a module, site or configuration was
+disabled by a maintainer script. However, exit status S<1> is returned if the
+module was not found at all
+
+=head1 SEE ALSO
+
+L<apache2ctl>(8), L<apache2>(8), L<perl>(1)
+
+=head1 AUTHOR
+
+This manual and L<a2query> was written by Arno Toell <debian@toell.net>.
+
+=cut
+
+sub output
+{
+ print @_ unless $QUIET;
+}
+
+sub warning
+{
+ print STDERR @_ unless $QUIET;
+}
+
+sub fail
+{
+ die('usage: fail($reason, $retval)') if @_ != 2;
+ my $reason = shift;
+ my $retval = shift;
+ warning "$reason\n";
+ exit $retval;
+}
+
+sub load_defaults
+{
+ my @out = `$APACHE2 -V 2>/dev/null`;
+ return if $?;
+ foreach my $line (@out)
+ {
+ if ($line =~ m/(Server version|Server MPM|Magic Number):\s+(.*?)$/)
+ {
+ my ($pattern, $value) = ($1, $2);
+ if ($pattern =~ /version/)
+ {
+ $SERVER_VERSION = $value;
+ $SERVER_VERSION =~ s/[^\d\.]//g;
+ }
+ elsif ($pattern =~ /MPM/)
+ {
+ $MPM = $value;
+ }
+ elsif ($pattern =~ /Magic/)
+ {
+ $API = $value;
+ $API =~ s/\:\d+//;
+ }
+ }
+ }
+
+}
+
+sub load_modules
+{
+ my $conf_dir = $CONFIG_DIR . "/mods-enabled";
+ opendir(DIR, $conf_dir) || fail("$conf_dir: $!", 1);
+ while ( readdir(DIR) )
+ {
+ my $file = $_;
+ next if $file !~ m/\.load$/;
+ $file =~ s/\.load//;
+ if ($file =~ /mpm_(event|worker|prefork)/)
+ {
+ $MPM = $1 if $MPM eq 'invalid';
+ if (grep { $_ =~ m/^mpm_(?:event|worker|prefork)/ } @MODULES)
+ {
+ fail("There is more than one MPM loaded. Do not proceed due to undefined results", 1);
+ }
+ }
+ push @MODULES, $file;
+ }
+ closedir(DIR);
+}
+
+
+sub load_conf
+{
+ if ($#CONFS >= 0)
+ {
+ return;
+ }
+ my $conf_dir = $CONFIG_DIR . "/conf-enabled";
+ opendir(DIR, $conf_dir) || fail("$conf_dir: $!", 1);
+ while ( readdir(DIR) )
+ {
+ my $file = $_;
+ next if $file !~ m/\.conf$/;
+ $file =~ s/\.conf$//;
+ push @CONFS, $file;
+ }
+ closedir(DIR);
+}
+
+
+sub load_sites
+{
+ if ($#SITES >= 0)
+ {
+ return;
+ }
+ my $conf_dir = $CONFIG_DIR . "/sites-enabled";
+ opendir(DIR, $conf_dir) || fail("$conf_dir: $!", 1);
+ while ( readdir(DIR) )
+ {
+ my $file = $_;
+ next if $file !~ m/\.conf$/;
+ $file =~ s/\.conf$//;
+ push @SITES, $file;
+ }
+ closedir(DIR);
+}
+
+sub switch_history
+{
+ die('usage: switch_history([module|site|conf], [enabled|disabled], $name)') if @_ != 3;
+ my $which = shift;
+ my $what = shift;
+ my $name = shift;
+
+ $name =~ s/\.conf$//;
+
+ foreach my $state (@STATES)
+ {
+ my $state_token = "$STATE_DIR/$which/$what" . "_by_$state/" . $name;
+ if (-e $state_token)
+ {
+ return $state;
+ }
+ }
+ return 0;
+}
+
+
+sub query_state
+{
+ my $type = shift;
+ my $pattern = shift;
+ my $listref = shift;
+
+ $pattern =~ s/^mod//;
+ $pattern =~ s/\.(conf|load)//;
+ my @candidates;
+
+ if ($pattern)
+ {
+ @candidates = grep { $_ eq $pattern } @{ $listref };
+ }
+ else
+ {
+ @candidates = @{ $listref }
+ }
+
+ my $matches = 0;
+ foreach my $module (@candidates)
+ {
+ my $state = switch_history($type, "enabled", $module);
+ if (!$state)
+ {
+ $state = "unknown";
+ }
+ output("$module (enabled by $verbose_state{$state})\n");
+ $matches++;
+ }
+ if (!$matches)
+ {
+ my $reason = "No $type matches $pattern";
+ my $retval = $E_NOTFOUND;
+ my $state = switch_history($type, "disabled", $pattern);
+ if ($state)
+ {
+ $reason .= " (disabled by $verbose_state{$state})";
+ if ($state eq 'maint')
+ {
+ $retval = $E_OFFBYMAINT;
+ }
+ if ($state eq 'admin')
+ {
+ $retval = $E_OFFBYADMIN;
+ }
+ }
+ fail($reason, $retval);
+ }
+}
+
+load_defaults();
+load_modules();
+
+my %opts;
+my $help = 1;
+getopts('m:s:c:havMdq', \%opts);
+#foreach my $key (keys %opts) { print("$key=$opts{$key}\n");}
+
+push @HELP, ["q", "suppress any output. Useful for invocation from scripts"];
+if (exists $opts{'q'})
+{
+ --$help;
+ $QUIET=1;
+}
+
+push @HELP, ["m [MODULE]", "checks whether the module MODULE is enabled, lists all enabled modules if no argument was given"];
+if (exists $opts{'m'})
+{
+ --$help;
+ query_state('module', $opts{'m'}, \@MODULES);
+}
+
+push @HELP, ["s [SITE]", "checks whether the site SITE is enabled, lists all sites if no argument was given"];
+if (exists $opts{'s'})
+{
+ --$help;
+ load_sites();
+ query_state('site', $opts{'s'}, \@SITES);
+}
+
+
+push @HELP, ["c [CONF]", "checks whether the configuration CONF is enabled, lists all configurations if no argument was given"];
+if (exists $opts{'c'})
+{
+ --$help;
+ load_conf();
+ query_state('conf', $opts{'c'}, \@CONFS);
+}
+
+
+push @HELP, ["a", "returns the current Apache 2 module magic version"];
+if (exists $opts{'a'})
+{
+ --$help;
+ output("$API\n");
+}
+
+
+push @HELP, ["v", "returns the current Apache 2 version"];
+if (exists $opts{'v'})
+{
+ --$help;
+ output("$SERVER_VERSION\n");
+}
+
+push @HELP, ["M", "returns the enabled Apache 2 MPM"];
+if (exists $opts{'M'})
+{
+ --$help;
+ output("$MPM\n");
+}
+
+push @HELP, ["d", "returns the Apache 2 module directory"];
+if (exists $opts{'d'})
+{
+ --$help;
+ output("$MODULE_DIR\n");
+}
+
+push @HELP, ["h", "display this help"];
+if (exists $opts{'h'} or $help == 1)
+{
+ my $usage = "$0 ";
+ map { $usage .= "-$_->[0] " } @HELP;
+ print("Usage: $usage\n");
+ my $switch_name;
+ my $description;
+ format STDOUT =
+@<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+"-$switch_name", $description,
+~~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+ $description,
+.
+ foreach my $switch (@HELP)
+ {
+ ($switch_name, $description) = ($switch->[0], $switch->[1]);
+ write STDOUT;
+ }
+ exit $E_OK;
+}
+
+# vim: syntax=perl sw=8 sts=8 sr noet