]> granicus.if.org Git - apache/blob - support/apxs.in
fix eval of vars incase string has quotes
[apache] / support / apxs.in
1 #!@perlbin@ -w
2 # ====================================================================
3 # The Apache Software License, Version 1.1
4 #
5 # Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
6 # reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
10 # are met:
11 #
12 # 1. Redistributions of source code must retain the above copyright
13 #    notice, this list of conditions and the following disclaimer.
14 #
15 # 2. Redistributions in binary form must reproduce the above copyright
16 #    notice, this list of conditions and the following disclaimer in
17 #    the documentation and/or other materials provided with the
18 #    distribution.
19 #
20 # 3. The end-user documentation included with the redistribution,
21 #    if any, must include the following acknowledgment:
22 #       "This product includes software developed by the
23 #        Apache Software Foundation (http://www.apache.org/)."
24 #    Alternately, this acknowledgment may appear in the software itself,
25 #    if and wherever such third-party acknowledgments normally appear.
26 #
27 # 4. The names "Apache" and "Apache Software Foundation" must
28 #    not be used to endorse or promote products derived from this
29 #    software without prior written permission. For written
30 #    permission, please contact apache@apache.org.
31 #
32 # 5. Products derived from this software may not be called "Apache",
33 #    nor may "Apache" appear in their name, without prior written
34 #    permission of the Apache Software Foundation.
35 #
36 # THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 # DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40 # ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 # SUCH DAMAGE.
48 # ====================================================================
49 #
50 # This software consists of voluntary contributions made by many
51 # individuals on behalf of the Apache Software Foundation.  For more
52 # information on the Apache Software Foundation, please see
53 # <http://www.apache.org/>.
54 #
55
56 require 5.003;
57 use strict;
58 package apxs;
59
60 ##
61 ##  Configuration
62 ##
63
64 my $prefix         = "@prefix@";
65 my $CFG_PREFIX     = $prefix;
66
67 # read the configuration variables once
68 my %config_vars = ();
69 get_config_vars("$prefix/build/config_vars.mk",\%config_vars);
70
71 my $exec_prefix    = get_vars("exec_prefix");
72 my $CFG_TARGET     = get_vars("progname");
73 my $CFG_SYSCONFDIR = get_vars("sysconfdir");
74 my $CFG_CFLAGS     = join ' ', map { get_vars($_) }
75   qw(SHLTCFLAGS CFLAGS NOTEST_CPPFLAGS EXTRA_CPPFLAGS EXTRA_CFLAGS);
76 my $includedir     = get_vars("includedir");
77 my $CFG_INCLUDEDIR = eval qq("$includedir");
78 my $CFG_CC         = get_vars("CC");
79 my $libexecdir     = get_vars("libexecdir");
80 my $CFG_LIBEXECDIR = eval qq("$libexecdir");
81 my $bindir         = get_vars("bindir");
82 my $CFG_SBINDIR    = eval qq("$bindir");
83
84 my %internal_vars = map {$_ => 1}
85     qw(TARGET CC CFLAGS CFLAGS_SHLIB LD_SHLIB LDFLAGS_SHLIB LIBS_SHLIB
86        PREFIX SBINDIR INCLUDEDIR LIBEXECDIR SYSCONFDIR);
87
88 ##
89 ##  parse argument line
90 ##
91
92 #   defaults for parameters
93 my $opt_n = '';
94 my $opt_g = '';
95 my $opt_c = 0;
96 my $opt_o = '';
97 my @opt_D = ();
98 my @opt_I = ();
99 my @opt_L = ();
100 my @opt_l = ();
101 my @opt_W = ();
102 my @opt_S = ();
103 my $opt_e = 0;
104 my $opt_i = 0;
105 my $opt_a = 0;
106 my $opt_A = 0;
107 my $opt_q = 0;
108 my $opt_h = 0;
109
110 #   this subroutine is derived from Perl's getopts.pl with the enhancement of
111 #   the "+" metacharater at the format string to allow a list to be build by
112 #   subsequent occurance of the same option.
113 sub Getopts {
114     my ($argumentative, @ARGV) = @_;
115     my $errs = 0;
116     local $_;
117     local $[ = 0;
118
119     my @args = split / */, $argumentative;
120     while (@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
121         my ($first, $rest) = ($1,$2);
122         if ($_ =~ m|^--$|) {
123             shift @ARGV;
124             last;
125         }
126         my $pos = index($argumentative,$first);
127         if ($pos >= $[) {
128             if ($args[$pos+1] eq ':') {
129                 shift @ARGV;
130                 if ($rest eq '') {
131                     unless (@ARGV) {
132                         error("Incomplete option: $first (needs an argument)");
133                         $errs++;
134                     }
135                     $rest = shift(@ARGV);
136                 }
137                 eval "\$opt_$first = \$rest;";
138             }
139             elsif ($args[$pos+1] eq '+') {
140                 shift @ARGV;
141                 if ($rest eq '') {
142                     unless (@ARGV) {
143                         error("Incomplete option: $first (needs an argument)");
144                         $errs++;
145                     }
146                     $rest = shift(@ARGV);
147                 }
148                 eval "push(\@opt_$first, \$rest);";
149             }
150             else {
151                 eval "\$opt_$first = 1";
152                 if ($rest eq '') {
153                     shift(@ARGV);
154                 }
155                 else {
156                     $ARGV[0] = "-$rest";
157                 }
158             }
159         }
160         else {
161             error("Unknown option: $first");
162             $errs++;
163             if ($rest ne '') {
164                 $ARGV[0] = "-$rest";
165             }
166             else {
167                 shift(@ARGV);
168             }
169         }
170     }
171     return ($errs == 0, @ARGV);
172 }
173
174 sub usage {
175     print STDERR "Usage: apxs -g [-S <var>=<val>] -n <modname>\n";
176     print STDERR "       apxs -q [-S <var>=<val>] <query> ...\n";
177     print STDERR "       apxs -c [-S <var>=<val>] [-o <dsofile>] [-D <name>[=<value>]]\n";
178     print STDERR "               [-I <incdir>] [-L <libdir>] [-l <libname>] [-Wc,<flags>]\n";
179     print STDERR "               [-Wl,<flags>] <files> ...\n";
180     print STDERR "       apxs -i [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
181     print STDERR "       apxs -e [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
182     exit(1);
183 }
184
185 #   option handling
186 my $rc;
187 ($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+W+S+eiaA", @ARGV);
188 &usage if ($rc == 0);
189 &usage if ($#ARGV == -1 and not $opt_g);
190 &usage if (not $opt_q and not ($opt_g and $opt_n) and not $opt_i and not $opt_c and not $opt_e);
191
192 #   argument handling
193 my @args = @ARGV;
194 my $name = 'unknown';
195 $name = $opt_n if ($opt_n ne '');
196
197 if (@opt_S) {
198     my ($opt_S);
199     foreach $opt_S (@opt_S) {
200         if ($opt_S =~ m/^([^=]+)=(.*)$/) {
201             my ($var) = $1;
202             my ($val) = $2;
203             my $oldval = eval "\$CFG_$var";
204
205             unless ($var and $oldval) {
206                 print STDERR "apxs:Error: no config variable $var\n";
207                 &usage;
208             }
209
210             eval "\$CFG_${var}=\"${val}\"";
211         } else {
212             print STDERR "apxs:Error: malformatted -S option\n";
213             &usage;
214         }       
215     }
216 }
217
218 ##
219 ##  Initial shared object support check
220 ##
221 my $httpd = get_vars("bindir") . "/" . get_vars("progname");
222 $httpd = eval qq("$httpd");
223 $httpd = eval qq("$httpd");
224
225 #allow apxs to be run from the source tree, before installation
226 if ($0 =~ m:support/apxs$:) {
227     ($httpd = $0) =~ s:support/apxs$::;
228 }
229
230 unless (-x "$httpd") {
231         error("$httpd not found or not executable");
232         exit 1;
233 }
234
235 unless (grep /mod_so/, `$httpd -l`) {
236     error("Sorry, no shared object support for Apache");
237     error("available under your platform. Make sure");
238     error("the Apache module mod_so is compiled into");
239     error("your server binary `$httpd'.");
240     exit 1;
241 }
242
243 sub get_config_vars{
244     my ($file, $rh_config) = @_;
245
246     open IN, $file or die "cannot open $file: $!";
247     while (<IN>){
248         if (/^\s*(.*?)\s*=\s*(.*)$/){
249             $rh_config->{$1} = $2;
250         }
251     }
252     close IN;
253 }
254
255 sub get_vars {
256     my $result = '';
257     my $ok = 0;
258     my $arg;
259     foreach $arg (@_) {
260         if (exists $config_vars{$arg} or exists $config_vars{lc $arg}) {
261             my $val = exists $config_vars{$arg}
262                 ? $config_vars{$arg}
263                 : $config_vars{lc $arg};
264             $val =~ s/[()]//g;
265             $result .= eval "qq($val)";
266             $result .= ";;";
267             $ok = 1;
268         }
269         if (not $ok) {
270             if (exists $internal_vars{$arg} or exists $internal_vars{lc $arg}) {
271                 my $val = exists $internal_vars{$arg} ? $arg : lc $arg;
272                 $val = eval "\$CFG_$val";
273                 $result .= eval "qq($val)";
274                 $result .= ";;";
275                 $ok = 1;
276             }
277             if (not $ok) {
278                 error("Invalid query string `$arg'");
279                 exit(1);
280             }
281         }
282     }
283     $result =~ s|;;$||;
284     $result =~ s|:| |;
285     return $result;
286 }
287
288 ##
289 ##  Operation
290 ##
291
292 #   helper function for executing a list of
293 #   system command with return code checks
294 sub execute_cmds {
295     my (@cmds) = @_;
296     my ($cmd, $rc);
297
298     foreach $cmd (@cmds) {
299         notice($cmd);
300         $rc = system $cmd;
301         if ($rc) {
302             error(sprintf "Command failed with rc=%d\n", $rc << 8);
303             exit 1 ;
304         }
305     }
306 }
307
308 if ($opt_g) {
309     ##
310     ##  SAMPLE MODULE SOURCE GENERATION
311     ##
312
313     if (-d $name) {
314         error("Directory `$name' already exists. Remove first");
315         exit(1);
316     }
317
318     my $data = join('', <DATA>);
319     $data =~ s|%NAME%|$name|sg;
320     $data =~ s|%TARGET%|$CFG_TARGET|sg;
321
322     my ($mkf, $mods, $src) = ($data =~ m|^(.+)-=#=-\n(.+)-=#=-\n(.+)|s);
323
324     notice("Creating [DIR]  $name");
325     system("mkdir $name");
326     notice("Creating [FILE] $name/Makefile");
327     open(FP, ">${name}/Makefile") || die;
328     print FP $mkf;
329     close(FP);
330     notice("Creating [FILE] $name/modules.mk");
331     open(FP, ">${name}/modules.mk") || die;
332     print FP $mods;
333     close(FP);
334     notice("Creating [FILE] $name/mod_$name.c");
335     open(FP, ">${name}/mod_${name}.c") || die;
336     print FP $src;
337     close(FP);
338     notice("Creating [FILE] $name/.deps");
339     system("touch ${name}/.deps");
340
341     exit(0);
342 }
343
344
345 if ($opt_q) {
346     ##
347     ##  QUERY INFORMATION 
348     ##
349     my $result = get_vars(@args);
350     print "$result";
351 }
352
353 if ($opt_c) {
354     ##
355     ##  SHARED OBJECT COMPILATION
356     ##
357
358     #   split files into sources and objects
359     my @srcs = ();
360     my @objs = ();
361     my $f;
362     foreach $f (@args) {
363         if ($f =~ m|\.c$|) {
364             push(@srcs, $f);
365         }
366         else {
367             push(@objs, $f);
368         }
369     }
370
371     #   determine output file
372     my $dso_file;
373     if ($opt_o eq '') {
374         if ($#srcs > -1) {
375             $dso_file = $srcs[0];
376             $dso_file =~ s|\.[^.]+$|.la|;
377         }
378         elsif ($#objs > -1) {
379             $dso_file = $objs[0];
380             $dso_file =~ s|\.[^.]+$|.la|;
381         }
382         else {
383             $dso_file = "mod_unknown.so";
384         }
385     }
386     else {
387         $dso_file = $opt_o;
388     }
389
390     #   create compilation commands
391     my @cmds = ();
392     my $opt = '';
393     my ($opt_Wc, $opt_I, $opt_D);
394     foreach $opt_Wc (@opt_W) {
395         $opt .= "$1 " if ($opt_Wc =~ m|^\s*c,(.*)$|);
396     }
397     foreach $opt_I (@opt_I) {
398         $opt .= "-I$opt_I ";
399     }
400     foreach $opt_D (@opt_D) {
401         $opt .= "-D$opt_D ";
402     }
403     my $cflags = "$CFG_CFLAGS";
404     my $s;
405     my $mod;
406     foreach $s (@srcs) {
407         my $slo = $s;
408         $slo =~ s|\.c$|.slo|;
409         my $lo = $s;
410         $lo =~ s|\.c$|.lo|;
411         my $la = $s;
412         $la =~ s|\.c$|.la|;
413         my $o = $s;
414         $o =~ s|\.c$|.o|;
415         push(@cmds, "$prefix/build/libtool --silent --mode=compile $CFG_CC $cflags -I$CFG_INCLUDEDIR $opt -c -o $lo $s && touch $slo");
416         unshift(@objs, $lo);
417     }
418
419     #   create link command
420     my $o;
421     my $lo;     
422     foreach $o (@objs) {
423         $lo .= " $o";
424     }
425     my ($opt_Wl, $opt_L, $opt_l);
426     foreach $opt_Wl (@opt_W) {
427         if ($CFG_CC !~ m/gcc$/) {
428             $opt .= " $1" if ($opt_Wl =~ m|^\s*l,(.*)$|);
429         } else {
430             $opt .= " -W$opt_Wl";
431         }
432     }
433     foreach $opt_L (@opt_L) {
434         $opt .= " -L$opt_L";
435     }
436     foreach $opt_l (@opt_l) {
437         $opt .= " -l$opt_l";
438     }
439
440     push(@cmds, "$prefix/build/libtool --silent --mode=link $CFG_CC -o $dso_file -rpath $CFG_LIBEXECDIR -module -avoid-version $opt $lo");
441
442     #   execute the commands
443     &execute_cmds(@cmds);
444
445     #   allow one-step compilation and installation
446     if ($opt_i or $opt_e) {
447         @args = ( $dso_file );
448     }
449 }
450
451 if ($opt_i or $opt_e) {
452     ##
453     ##  SHARED OBJECT INSTALLATION
454     ##
455
456     #   determine installation commands
457     #   and corresponding LoadModule/AddModule directives
458     my @lmd = ();
459     my @amd = ();
460     my @cmds = ();
461     my $f;
462     foreach $f (@args) {
463         if ($f !~ m#(\.so$|\.la$)#) {
464             error("file $f is not a shared object");
465             exit(1);
466         }
467         my $t = $f;
468         $t =~ s|^.+/([^/]+)$|$1|;
469         if ($opt_i) {
470             push(@cmds, "$prefix/build/libtool --mode=install cp $f $CFG_LIBEXECDIR/$t");
471             push(@cmds, "chmod 755 $CFG_LIBEXECDIR/$t");
472         }
473
474         #   determine module symbolname and filename
475         my $filename = '';
476         if ($name eq 'unknown') {
477             $name = '';
478             my $base = $f;
479             $base =~ s|\.[^.]+$||;
480             if (-f "$base.c") {
481                 open(FP, "<$base.c");
482                 my $content = join('', <FP>);
483                 close(FP);
484                 if ($content =~ m|.*module\s+(?:AP_MODULE_DECLARE_DATA\s+)?([a-zA-Z0-9_]+)_module\s*=\s*.*|s) {
485                     $name = "$1";
486                     $filename = "$base.c";
487                     $filename =~ s|^[^/]+/||;
488                 }
489             }
490             if ($name eq '') {
491                 if ($base =~ m|.*mod_([a-zA-Z0-9_]+)\..+|) {
492                     $name = "$1";
493                     $filename = $base;
494                     $filename =~ s|^[^/]+/||;
495                 }
496             }
497             if ($name eq '') {
498                 error("Sorry, cannot determine bootstrap symbol name");
499                 error("Please specify one with option `-n'");
500                 exit(1);
501             }
502         }
503         if ($filename eq '') {
504             $filename = "mod_${name}.c";
505         }
506         my $dir = $CFG_LIBEXECDIR;
507         $dir =~ s|^$CFG_PREFIX/?||;
508         $dir =~ s|(.)$|$1/|;
509         $t =~ s|\.la$|.so|;
510         push(@lmd, sprintf("LoadModule %-18s %s", "${name}_module", "$dir$t"));
511         push(@amd, sprintf("AddModule %s", $filename));
512     }
513
514     #   execute the commands
515     &execute_cmds(@cmds);
516
517     #   activate module via LoadModule/AddModule directive
518     if ($opt_a or $opt_A) {
519         if (not -f "$CFG_SYSCONFDIR/$CFG_TARGET.conf") {
520             error("Config file $CFG_SYSCONFDIR/$CFG_TARGET.conf not found");
521             exit(1);
522         }
523
524         open(FP, "<$CFG_SYSCONFDIR/$CFG_TARGET.conf") || die;
525         my $content = join('', <FP>);
526         close(FP);
527
528         if ($content !~ m|\n#?\s*LoadModule\s+|) {
529             error("Activation failed for custom $CFG_SYSCONFDIR/$CFG_TARGET.conf file.");
530             error("At least one `LoadModule' directive already has to exist.");
531             exit(1);
532         }
533
534         my $lmd;
535         my $c = '';
536         $c = '#' if ($opt_A);
537         foreach $lmd (@lmd) {
538             my $what = $opt_A ? "preparing" : "activating";
539             if ($content !~ m|\n#?\s*$lmd|) {
540                  $content =~ s|^(.*\n#?\s*LoadModule\s+[^\n]+\n)|$1$c$lmd\n|sg;
541             } else {
542                  $content =~ s|^(.*\n)#?\s*$lmd[^\n]*\n|$1$c$lmd\n|sg;
543             }
544             $lmd =~ m|LoadModule\s+(.+?)_module.*|;
545             notice("[$what module `$1' in $CFG_SYSCONFDIR/$CFG_TARGET.conf]");
546         }
547         my $amd;
548         foreach $amd (@amd) {
549             if ($content !~ m|\n#?\s*$amd|) {
550                  $content =~ s|^(.*\n#?\s*AddModule\s+[^\n]+\n)|$1$c$amd\n|sg;
551             } else {
552                  $content =~ s|^(.*\n)#?\s*$amd[^\n]*\n|$1$c$amd\n|sg;
553             }
554         }
555         if (@lmd or @amd) {
556             if (open(FP, ">$CFG_SYSCONFDIR/$CFG_TARGET.conf.new")) {
557                 print FP $content;
558                 close(FP);
559                 system("cp $CFG_SYSCONFDIR/$CFG_TARGET.conf $CFG_SYSCONFDIR/$CFG_TARGET.conf.bak && " .
560                        "cp $CFG_SYSCONFDIR/$CFG_TARGET.conf.new $CFG_SYSCONFDIR/$CFG_TARGET.conf && " .
561                        "rm $CFG_SYSCONFDIR/$CFG_TARGET.conf.new");
562             } else {
563                 notice("unable to open configuration file");
564             }
565         }
566     }
567 }
568
569 sub error{
570     print STDERR "apxs:Error: $_[0].\n";
571 }
572
573 sub notice{
574     print STDERR "$_[0]\n";
575 }
576
577 ##EOF##
578 __DATA__
579 ##
580 ##  Makefile -- Build procedure for sample %NAME% Apache module
581 ##  Autogenerated via ``apxs -n %NAME% -g''.
582 ##
583
584 builddir=$(shell pwd)
585 top_srcdir=/home/rbb/apachebin4
586 top_builddir=/home/rbb/apachebin4/build
587 include /home/rbb/apachebin4/build/special.mk
588
589 #   the used tools
590 APXS=apxs
591 APACHECTL=apachectl
592
593 #   additional defines, includes and libraries
594 #DEF=-Dmy_define=my_value
595 #INC=-Imy/include/dir
596 #LIB=-Lmy/lib/dir -lmylib
597
598 #   the default target
599 all: local-shared-build
600
601 #   install the shared object file into Apache 
602 install: install-modules
603
604 #   cleanup
605 clean:
606         -rm -f mod_%NAME%.o mod_%NAME%.lo mod_%NAME%.slo mod_%NAME%.la 
607
608 #   simple test
609 test: reload
610         lynx -mime_header http://localhost/%NAME%
611
612 #   install and activate shared object by reloading Apache to
613 #   force a reload of the shared object file
614 reload: install restart
615
616 #   the general Apache start/restart/stop
617 #   procedures
618 start:
619         $(APACHECTL) start
620 restart:
621         $(APACHECTL) restart
622 stop:
623         $(APACHECTL) stop
624
625 -=#=-
626 mod_%NAME%.la: mod_%NAME%.slo
627         $(SH_LINK) -rpath $(libexecdir) -module -avoid-version  mod_%NAME%.lo
628 DISTCLEAN_TARGETS = modules.mk
629 shared =  mod_%NAME%.la
630 -=#=-
631 /* 
632 **  mod_%NAME%.c -- Apache sample %NAME% module
633 **  [Autogenerated via ``apxs -n %NAME% -g'']
634 **
635 **  To play with this sample module first compile it into a
636 **  DSO file and install it into Apache's modules directory 
637 **  by running:
638 **
639 **    $ apxs -c -i mod_%NAME%.c
640 **
641 **  Then activate it in Apache's %TARGET%.conf file for instance
642 **  for the URL /%NAME% in as follows:
643 **
644 **    #   %TARGET%.conf
645 **    LoadModule %NAME%_module modules/mod_%NAME%.so
646 **    <Location /%NAME%>
647 **    SetHandler %NAME%
648 **    </Location>
649 **
650 **  Then after restarting Apache via
651 **
652 **    $ apachectl restart
653 **
654 **  you immediately can request the URL /%NAME% and watch for the
655 **  output of this module. This can be achieved for instance via:
656 **
657 **    $ lynx -mime_header http://localhost/%NAME% 
658 **
659 **  The output should be similar to the following one:
660 **
661 **    HTTP/1.1 200 OK
662 **    Date: Tue, 31 Mar 1998 14:42:22 GMT
663 **    Server: Apache/1.3.4 (Unix)
664 **    Connection: close
665 **    Content-Type: text/html
666 **  
667 **    The sample page from mod_%NAME%.c
668 */ 
669
670 #include "httpd.h"
671 #include "http_config.h"
672 #include "http_protocol.h"
673 #include "ap_config.h"
674
675 /* The sample content handler */
676 static int %NAME%_handler(request_rec *r)
677 {
678     if (strcmp(r->handler, "%NAME%")) {
679         return DECLINED;
680     }
681     r->content_type = "text/html";      
682
683     if (!r->header_only)
684         ap_rputs("The sample page from mod_%NAME%.c\n", r);
685     return OK;
686 }
687
688 static void %NAME%_register_hooks(apr_pool_t *p)
689 {
690     ap_hook_handler(%NAME%_handler, NULL, NULL, APR_HOOK_MIDDLE);
691 }
692
693 /* Dispatch list for API hooks */
694 module AP_MODULE_DECLARE_DATA %NAME%_module = {
695     STANDARD20_MODULE_STUFF, 
696     NULL,                  /* create per-dir    config structures */
697     NULL,                  /* merge  per-dir    config structures */
698     NULL,                  /* create per-server config structures */
699     NULL,                  /* merge  per-server config structures */
700     NULL,                  /* table of config file commands       */
701     %NAME%_register_hooks  /* register hooks                      */
702 };
703