diff options
Diffstat (limited to 'debian/a2query.in')
-rwxr-xr-x | debian/a2query.in | 426 |
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 |