diff options
Diffstat (limited to '')
-rwxr-xr-x | debian/debhelper/dh_apache2.in | 582 |
1 files changed, 582 insertions, 0 deletions
diff --git a/debian/debhelper/dh_apache2.in b/debian/debhelper/dh_apache2.in new file mode 100755 index 0000000..dcb5f59 --- /dev/null +++ b/debian/debhelper/dh_apache2.in @@ -0,0 +1,582 @@ +#! /usr/bin/perl + +# dh_apache2 - Apache2 configuration elper for debhelper +# 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 vserion 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 strict; +use File::Find; +use Debian::Debhelper::Dh_Lib; + + +=head1 NAME + +dh_apache2 - register configuration snippets to the Apache web server + +=cut + +# auto-generated do not edit +our $API = "__API__"; +our $OPENSSL = "__OPENSSL__"; +our $MODULE_DIR = "__MODULE_DIR__"; +our $SERVER_VERSION = "__SERVER_VERSION__"; + +sub apache_api_version +{ + return "apache2-api-$API"; +} + +sub apache_api_ssl_version +{ + return "apache2-api-$API-$OPENSSL"; +} + +sub apache_depends +{ + # TODO XXX this should be determined from ap_mmn.h, too. + my $ret = apache_api_version() . ", apache2-bin ( >= 2.4.16 )"; + if (have_apache2_ssl_dev()) { + $ret .= ", " . apache_api_ssl_version(); + } + return $ret; +} + +sub apache_version +{ + return ">= $SERVER_VERSION~"; +} + +sub apache_api_installdir +{ + return $MODULE_DIR; +} + +sub apache_conf_installdir +{ + my $type = shift; + return "etc/apache2/${type}-available/" +} + +sub have_apache2_ssl_dev +{ + open(my $fd, "<", "debian/control") or die "Cannot open debian/control: $!"; + my $line; + my $builddeps = ""; + while (defined ($line = <$fd>)) { + chomp $line; + if ($line =~ m{^Build-Depends:}i) { + $builddeps .= $line; + } elsif ($builddeps) { + if ($line =~ m{^\s}) { + $builddeps .= $line; + } else { + last; + } + } + } + if ($builddeps =~ m{\bapache2-ssl-dev\b}) { + return 1; + } else { + return; + } +} + +=head1 SYNOPSIS + +B<dh_apache2> [S<I<debhelper options>>] [S<B<--conditional>>=I<expression>] [B<--error-handler=>I<function>] [B<-n>|B<--noscripts>] + [B<-e>|B<--noenable>] [B<-r>|B<--restart>] + +=head1 DESCRIPTION + +B<dh_apache2> is a debhelper program that is responsible for correctly installing +Apache2 configuration snippets and setting postinst, prerm and dependencies in +Apache2 web server modules and web applications. + +It supports the following configuration types + +=over 4 + +=item * +Apache2 modules + +=item * +Apache2 configuration snippets for web applications + +=item * +Apache2 sites + +=back + +B<dh_apache2> supports two modes: A limited auto-configuration heuristic or +alternatively a configuration file driven approach. If a file named +debian/package.apache2 exists, actual actions are determined by that file. + +=head1 OPERATION MODES + +B<dh_apache2> can be used in two modes: A configuration file driven approach and +a heuristic approach. The configuration driven mode is fully documented in the +B<FILES> section below. This mode is activated by supplying a L<debhelper(7)> +configuration file (e.g. debian/I<package>.apache2). + +The alternative is a heuristic mode, in which no files are installed through +B<dh_apache2>. Instead the helper will scan the package installation directory +for recognized files and guess their purpose depending on their installation +path in the file system. Use with caution. + +=head1 INVOCATION + +B<dh_apache2> is not part of debhelper and might require information available +in the apache2-dev package. Packages making use of B<dh_apache2> should declare +a build-dependency against the virtual B<dh-apache2> package. + +B<dh_apache2> supports both, called directly from a debian/rules file or as +L<dh(1)> addon. In the former case the helper should run after L<dh_install(1)> +or their respective counter parts in local implementations at earliest. +Alternatively it can be used as L<dh> addon by invoking it with + + %: + dh $@ --with apache2 + +=head1 FILES + +=over 4 + +=item debian/I<package>.apache2 + +=item debian/apache2 + +=back + +Lists files to be registered with the Apache 2 HTTP server. The file is +interpreted as line separated list of installation stanzas, where each entry +consists of whitespace separated values conforming to the file semantics below. + +=head2 FILE SEMANTICS + +Each line consists of a triple + +I<type> I<file> [I<arguments>] + +where the values are interpreted as follows: + + +=head3 I<type> + +Denotes the type of file to be installed. Recognized values are B<conf> +for Apache2 global configuration snippets, B<site> for virtual host +configurations and B<mod> for Apache2 modules. + +=head3 I<file> + +Is interpreted as existing file name within the source package. No path +expansion is effectuated. Just like L<dh_install(1)>, B<dh_apache2> can not +rename files. + +=head3 I<arguments> + +Is inrerpreted as optional arguments if any, currently used by B<conf> +stanzas only + +=head2 GLOBAL CONFIGURATION FILES + +Global configuration files (determined by the B<conf> type) must have a I<.conf> +suffix and are installed to I</etc/apache2/conf-available>. Moreover, the +configuration is activated in the maintainer script at installation time. + +Such global configuration snippets are supposed to be used by web applications. +Such stanzas accept an optional third I<arguments> which is interpreted as +dependency line of alternative web servers the package supports. See I<EXAMPLES> +below. + +B<dh_apache2> will set dependencies in B<${misc:Recommends}> accordingly when +this type of configuration is found. Alternatives from the optional I<argument> +is incorporated into this dependency line. + +=head2 SITE CONFIGURATION FILES + +Site configuration files (determined by the B<site> type) must have a I<.conf> +suffix and are installed to I</etc/apache2/sites-available>. Moreover, the +configuration is activated in the maintainer script at installation time. + +Such global configuration snippets are supposed to be used by web applications +and third party packages which install virtual host configurations. This type of +configuration sets the same dependencies as configuration files. + +=head2 MODULES + +Modules are handled specially and are determined by the B<mod> type. Modules can +either have a I<.conf> or I<.load> suffix. In that case the file is interpreted +as module load file or module configuration file respectively and is nstalled to +I</etc/apache2/mods-available>. If the file is ending with a I<.so> suffix it is +interpreted as actual module shared object and is installed to the Apache module +directory. Moreover, if a I<.load> file is installed the configuration is +activated in the maintainer script at installation time. + +A typical module configuration has two lines, one for the I<.load> file, and one +for the I<.so> file, albeit the latter could be installed by upstream's +makefile, too. + +B<dh_apache2> will set dependencies in B<${misc:Depends}> accordingly when +this type of configuration is found. + +=head1 OPTIONS + +=over 4 + +=item B<--error-handler=>I<function> + +Call the named shell I<function> if running the maintainer script fails. The +function should be provided in the F<prerm> and F<postinst> scripts, before the +B<#DEBHELPER#> token. + +=item S<B<--conditional>>=I<function> + +Only execute maintainer scripts if the named shell I<function> evaluates to a +true value at installation time. This is useful to web applications which want +to install Apache configuration files depending on a user input, for example if +they interface to the user through L<debconf(1)>. + +The defaults is to always execute the scripts. The named function should be +provided in the F<prerm>, F<postrm> and F<postinst> scripts, before the +B<#DEBHELPER#> token. + +=item S<B<--restart>> S<B<-r>> + +In maintainer scripts, do not try to reload the web server, but restart it. +Otherwise the default action is used, which means global configuration and +sites make the web server to be reloaded on success, modules are restarted. + +=item B<-e>, B<--noenable> + +Install maintainer scripts accordingly, but do not enable the scripts or +configuration by default. + +=item B<-n>, B<--noscripts> + +Do not modify F<postinst>/F<postrm>/F<prerm> maintainer scripts. + + +=back + +=head1 NOTES + +Note that this command is not idempotent. L<dh_prep(1)> should be called +between invocations of this command. Otherwise, it may cause multiple +instances of the same text to be added to maintainer scripts. + +=head1 EXAMPLES + +The examples below lists valid entries for a debian/I<package>.apache2 file. For +example, the two lines below install a fictional I<mod_foo> Apache module along +a Debian specific I<.load> file: + + mod src/foo/mod_foo.so + mod debian/foo.load + +The example below installs a fictional web application called phpmyfoo supplied +in a package which also supports Lighttpd and nginx: + + conf debian/phpmyfoo.conf lighttpd (>= 1.4.30) | nginx-full + +Or, the same example again this time without support for other web servers: + + conf debian/phpmyfoo.conf + +As a final example, install a module called I<mod_foo> along with a site +configuration for a fictional site configuration for the site I<example.com>: + + mod src/foo/mod_foo.so + mod debian/foo.load + mod debian/foo.conf + site debian/example_com.conf + +=head1 SEE ALSO + +L<apache2ctl>(8), L<a2query>(8), L<debhelper>(7), L<dh>(1) + +=head1 AUTHOR + +This manual and L<dh_apache2> was written by Arno Toell <debian@toell.net>. + +=cut + + +## +## main code starts here +## + +init(options => { + "conditional=s" => \$dh{CONDITIONAL}, + "r|restart" => \$dh{RESTART}, + "e|noenable" => \$dh{NOENABLE}, +}); + +if (!$dh{CONDITIONAL}) +{ + $dh{CONDITIONAL} = 'true'; +} +elsif ($dh{CONDITIONAL} !~ /^\w+$/) { + die "The conditional function name must only contain ASCII letters, numbers, and underscores\n"; +} + +if ($dh{RESTART}) +{ + $dh{RESTART} = 'restart'; +} +else +{ + $dh{RESTART} = ''; +} + +foreach my $package ((@{$dh{DOPACKAGES}})) +{ + my %PACKAGE_TYPE = ( + has_a_module => [], + has_a_conf_file => [], + has_a_site_conf => [], + dependency_line => "", + handler => $dh{ERROR_HANDLER}, + conditional => $dh{CONDITIONAL} + ); + + my $file = pkgfile($package, "apache2"); + my $tmp = tmpdir($package); + + my @files_to_register = filedoublearray($file, ".") if $file; + foreach my $line (@files_to_register) + { + my $type = lc(shift @{$line}) if $line->[0]; + my $source = shift @{$line} if $line->[0]; + my @arguments = map {"$_ "} @{$line}; + + $type .= "s" unless $type eq "conf"; + my $installdir = $tmp . "/" . apache_conf_installdir($type); + + #verbose_print("$type -- $source -- @arguments\n\n"); + + if ($type eq "mods" or $type eq "sites" or $type eq "conf") + { + my $basesource = basename($source); + + if ($type eq "mods") + { + if ($basesource =~ m/\.load$/) + { + my $enablename = $basesource; + $enablename =~ s/\.load$//; + push @{$PACKAGE_TYPE{'has_a_module'}}, $enablename; + verbose_print("Installing module configuration $enablename into $installdir\n"); + } + elsif ($basesource =~ m/\.so$/) + { + my $modinstalldir = $tmp . "/" . apache_api_installdir(); + verbose_print("Installing module binary $source into $modinstalldir\n"); + if (! -d $modinstalldir) + { + complex_doit("mkdir","-p", $modinstalldir); + complex_doit("chmod","755","$modinstalldir"); + } + complex_doit("cp", $source, $modinstalldir); + next; + } + + error("module: \"$basesource\" needs .conf, .so or .load suffix") if $basesource !~ m/\.(conf|load|so)/; + } + elsif ($type eq "sites") + { + push @{$PACKAGE_TYPE{'has_a_site_conf'}}, $basesource; + verbose_print("Installing site configuration $basesource into $installdir\n"); + } + elsif($type eq "conf") + { + + if ($#arguments >= 0) + { + $PACKAGE_TYPE{'dependency_line'} .= " | " . join("", @arguments); + } + + if ($basesource =~ m/\.conf/) + { + my $enablename = $basesource; + $enablename =~ s/\.conf$//; + push + @{$PACKAGE_TYPE{'has_a_conf_file'}}, $enablename; + verbose_print("Installing global configuration $enablename into $installdir\n"); + } + error("configuration file: \"$basesource\" needs .conf suffix") if $basesource !~ m/\.conf/; + } + + if (! -d $installdir) + { + complex_doit("mkdir","-p",$installdir); + complex_doit("chmod","755","$installdir"); + } + complex_doit("cp",$source,$installdir); + complex_doit("chmod","644","$installdir/$basesource"); + + } + else + { + error("Unknown parameter: $type\n"); + } + + } + + + if (! $file) + { + # do black magic only if there is no .apache2 configuration file + find({ no_chdir => 1, + wanted => sub + { + my ($dir, $file) = (dirname($File::Find::name), basename($File::Find::name)); + # remove extension + my $conf_name = $file; + $conf_name =~ s/\.[^.]+$//; + + if ($dir =~ m#etc/apache2/mods-available# and $file =~ m#.(load|conf)$#) + { + verbose_print("package $package appears to be a web server module\n"); + push @{$PACKAGE_TYPE{'has_a_module'}}, $conf_name if $file =~ m/\.load/; + } + if ($dir =~ m#etc/apache2/sites-available# and $file =~ m#.conf$#) + { + verbose_print("package $package appears to contain a virtual host configuration\n"); + push @{$PACKAGE_TYPE{'has_a_site_conf'}}, $conf_name; + } + if ($dir =~ m#etc/apache2/conf-available# and $file =~ m#.conf$#) + { + verbose_print("package $package appears to contain a global configuration file \n"); + push @{$PACKAGE_TYPE{'has_a_conf_file'}}, $conf_name; + } + + + + }}, tmpdir($package)); + } + + + my @postinst_autoscripts; + + if ($#{$PACKAGE_TYPE{'has_a_module'}} >= 0) + { + if ($package !~ m/libapache2-mod-\w+?/) + { + warning("Package $package appears to be an Apache module. It should comply to the package naming scheme libapache2-mod-<modulename>\n"); + } + addsubstvar($package, "misc:Depends", apache_depends()); + + my $modules = ""; + foreach my $module (@{$PACKAGE_TYPE{'has_a_module'}}) + { + $modules .= "$module "; + } + + push @postinst_autoscripts, ["enmod", $modules]; + } + + if ($#{$PACKAGE_TYPE{'has_a_conf_file'}} >= 0 or $#{$PACKAGE_TYPE{'has_a_site_conf'}} >= 0) + { + $PACKAGE_TYPE{'dependency_line'} .= "| httpd"; + addsubstvar($package, "misc:Recommends", "apache2 ( >= 2.4.6-4~ ) " . $PACKAGE_TYPE{'dependency_line'} ); + + my $confs = ""; + my $sites = ""; + + foreach my $conf (@{$PACKAGE_TYPE{'has_a_conf_file'}}) + { + $confs .= "$conf "; + } + + foreach my $site (@{$PACKAGE_TYPE{'has_a_site_conf'}}) + { + $sites .= "$site "; + } + + if ($confs) + { + push @postinst_autoscripts, ["enconf", $confs]; + } + if ($sites) + { + push @postinst_autoscripts, ["ensite", $sites]; + } + + } + + if (! $dh{NOSCRIPTS}) + { + foreach my $ref (@postinst_autoscripts) + { + for my $script_type (qw/postinst prerm postrm/) + { + if ($script_type eq "postinst" && $dh{NOENABLE}) + { + next + } + + my %replacements = ( + HELPER => $ref->[0], + NAMES => $ref->[1], + ERROR_HANDLER => $PACKAGE_TYPE{handler}, + CONDITIONAL_VARIABLE => $PACKAGE_TYPE{conditional}, + ACTION => $dh{RESTART}, + ); + + if ($script_type eq "prerm" || $script_type eq "postrm") + { + $replacements{'HELPER'} =~ s/en/dis/; + } + + my $sed_command = ""; + foreach my $key (sort keys %replacements) + { + my $val = $replacements{$key}; + # Use a control char as separator for sed, to + # reduce escaping issues. Everything else is + # passed verbatim, i.e. it must not contain any + # shell or sed special characters. + my $sep = "\x17"; + $sed_command .= "s" . $sep . "#$key#" . + $sep . $val . + $sep . "g; "; + } + + autoscript($package, "$script_type", "$script_type-apache2", $sed_command); + } + } + } +} + +# vim: syntax=perl sw=8 sts=8 sr noet |