2 ## ====================================================================
3 ## Copyright (c) 1998-1999 The Apache Group. All rights reserved.
5 ## Redistribution and use in source and binary forms, with or without
6 ## modification, are permitted provided that the following conditions
9 ## 1. Redistributions of source code must retain the above copyright
10 ## notice, this list of conditions and the following disclaimer.
12 ## 2. Redistributions in binary form must reproduce the above copyright
13 ## notice, this list of conditions and the following disclaimer in
14 ## the documentation and/or other materials provided with the
17 ## 3. All advertising materials mentioning features or use of this
18 ## software must display the following acknowledgment:
19 ## "This product includes software developed by the Apache Group
20 ## for use in the Apache HTTP server project (http://www.apache.org/)."
22 ## 4. The names "Apache Server" and "Apache Group" must not be used to
23 ## endorse or promote products derived from this software without
24 ## prior written permission. For written permission, please contact
27 ## 5. Products derived from this software may not be called "Apache"
28 ## nor may "Apache" appear in their names without prior written
29 ## permission of the Apache Group.
31 ## 6. Redistributions of any form whatsoever must retain the following
33 ## "This product includes software developed by the Apache Group
34 ## for use in the Apache HTTP server project (http://www.apache.org/)."
36 ## THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
37 ## EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 ## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 ## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
40 ## ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 ## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 ## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 ## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 ## OF THE POSSIBILITY OF SUCH DAMAGE.
48 ## ====================================================================
50 ## This software consists of voluntary contributions made by many
51 ## individuals on behalf of the Apache Group and was originally based
52 ## on public domain software written at the National Center for
53 ## Supercomputing Applications, University of Illinois, Urbana-Champaign.
54 ## For more information on the Apache Group and the Apache HTTP server
55 ## project, please see <http://www.apache.org/>.
59 ## apxs -- APache eXtenSion tool
60 ## Written by Ralf S. Engelschall <rse@apache.org>
71 my $CFG_TARGET = '@TARGET@'; # substituted via Makefile.tmpl
72 my $CFG_CC = '@CC@'; # substituted via Makefile.tmpl
73 my $CFG_CFLAGS = '@CFLAGS@'; # substituted via Makefile.tmpl
74 my $CFG_CFLAGS_SHLIB = '@CFLAGS_SHLIB@'; # substituted via Makefile.tmpl
75 my $CFG_LD_SHLIB = '@LD_SHLIB@'; # substituted via Makefile.tmpl
76 my $CFG_LDFLAGS_SHLIB = '@LDFLAGS_MOD_SHLIB@'; # substituted via Makefile.tmpl
77 my $CFG_LIBS_SHLIB = '@LIBS_SHLIB@'; # substituted via Makefile.tmpl
78 my $CFG_PREFIX = '@prefix@'; # substituted via APACI install
79 my $CFG_SBINDIR = '@sbindir@'; # substituted via APACI install
80 my $CFG_INCLUDEDIR = '@includedir@'; # substituted via APACI install
81 my $CFG_LIBEXECDIR = '@libexecdir@'; # substituted via APACI install
82 my $CFG_SYSCONFDIR = '@sysconfdir@'; # substituted via APACI install
85 ## Cleanup the above stuff
87 $CFG_CFLAGS =~ s|^\s+||;
88 $CFG_CFLAGS =~ s|\s+$||;
89 $CFG_CFLAGS =~ s|\s+`.+apaci`||;
92 ## Initial shared object support check
94 if (not -x "$CFG_SBINDIR/$CFG_TARGET") {
95 print STDERR "apxs:Error: $CFG_SBINDIR/$CFG_TARGET not found or not executable\n";
98 if (not grep(/mod_so/, `$CFG_SBINDIR/$CFG_TARGET -l`)) {
99 print STDERR "apxs:Error: Sorry, no shared object support for Apache\n";
100 print STDERR "apxs:Error: available under your platform. Make sure\n";
101 print STDERR "apxs:Error: the Apache module mod_so is compiled into\n";
102 print STDERR "apxs:Error: your server binary `$CFG_SBINDIR/$CFG_TARGET'.\n";
107 ## parse argument line
110 # defaults for parameters
127 # this subroutine is derived from Perl's getopts.pl with the enhancement of
128 # the "+" metacharater at the format string to allow a list to be build by
129 # subsequent occurance of the same option.
131 my ($argumentative, @ARGV) = @_;
132 my (@args, $first, $rest, $pos);
137 @args = split( / */, $argumentative);
138 while(@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
139 ($first, $rest) = ($1,$2);
144 $pos = index($argumentative,$first);
146 if($args[$pos+1] eq ':') {
150 print STDERR "apxs:Error: Incomplete option: $first (needs an argument)\n";
153 $rest = shift(@ARGV);
155 eval "\$opt_$first = \$rest;";
157 elsif ($args[$pos+1] eq '+') {
161 print STDERR "apxs:Error: Incomplete option: $first (needs an argument)\n";
164 $rest = shift(@ARGV);
166 eval "push(\@opt_$first, \$rest);";
169 eval "\$opt_$first = 1";
179 print STDERR "apxs:Error: Unknown option: $first\n";
189 return ($errs == 0, @ARGV);
193 print STDERR "Usage: apxs -g [-S <var>=<val>] -n <modname>\n";
194 print STDERR " apxs -q [-S <var>=<val>] <query> ...\n";
195 print STDERR " apxs -c [-S <var>=<val>] [-o <dsofile>] [-D <name>[=<value>]]\n";
196 print STDERR " [-I <incdir>] [-L <libdir>] [-l <libname>] [-Wc,<flags>]\n";
197 print STDERR " [-Wl,<flags>] <files> ...\n";
198 print STDERR " apxs -i [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
199 print STDERR " apxs -e [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
205 ($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+W+S+eiaA", @ARGV);
206 &usage if ($rc == 0);
207 &usage if ($#ARGV == -1 and not $opt_g);
208 &usage if (not $opt_q and not ($opt_g and $opt_n) and not $opt_i and not $opt_c and not $opt_e);
212 my $name = 'unknown';
213 $name = $opt_n if ($opt_n ne '');
217 foreach $opt_S (@opt_S) {
218 if ($opt_S =~ m/^([^=]+)=(.*)$/) {
221 my $oldval = eval "\$CFG_$var";
223 unless ($var and $oldval) {
224 print STDERR "apxs:Error: no config variable $var\n";
228 eval "\$CFG_${var}=\"${val}\"";
230 print STDERR "apxs:Error: malformatted -S option\n";
240 # helper function for executing a list of
241 # system command with return code checks
246 foreach $cmd (@cmds) {
247 print STDERR "$cmd\n";
248 $rc = system("$cmd");
250 printf(STDERR "apxs:Break: Command failed with rc=%d\n", $rc << 8);
258 ## SAMPLE MODULE SOURCE GENERATION
262 print STDERR "apxs:Error: Directory `$name' already exists. Remove first\n";
266 my $data = join('', <DATA>);
267 $data =~ s|%NAME%|$name|sg;
268 $data =~ s|%TARGET%|$CFG_TARGET|sg;
270 my ($mkf, $src) = ($data =~ m|^(.+)-=#=-\n(.+)|s);
272 print STDERR "Creating [DIR] $name\n";
273 system("mkdir $name");
274 print STDERR "Creating [FILE] $name/Makefile\n";
275 open(FP, ">${name}/Makefile") || die;
278 print STDERR "Creating [FILE] $name/mod_$name.c\n";
279 open(FP, ">${name}/mod_${name}.c") || die;
294 foreach $arg (@args) {
298 TARGET CC CFLAGS CFLAGS_SHLIB LD_SHLIB LDFLAGS_SHLIB LIBS_SHLIB
299 PREFIX SBINDIR INCLUDEDIR LIBEXECDIR SYSCONFDIR
301 if ($arg eq $name or $arg eq lc($name)) {
302 my $val = eval "\$CFG_$name";
303 $result .= "${val}::";
308 printf(STDERR "apxs:Error: Invalid query string `%s'\n", $arg);
319 ## SHARED OBJECT COMPILATION
322 # split files into sources and objects
335 # determine output file
339 $dso_file = $srcs[0];
340 $dso_file =~ s|\.[^.]+$|.so|;
342 elsif ($#objs > -1) {
343 $dso_file = $objs[0];
344 $dso_file =~ s|\.[^.]+$|.so|;
347 $dso_file = "mod_unknown.so";
354 # create compilation commands
357 my ($opt_Wc, $opt_I, $opt_D);
358 foreach $opt_Wc (@opt_W) {
359 $opt .= "$1 " if ($opt_Wc =~ m|^\s*c,(.*)$|);
361 foreach $opt_I (@opt_I) {
364 foreach $opt_D (@opt_D) {
367 my $cflags = "$CFG_CFLAGS $CFG_CFLAGS_SHLIB";
372 push(@cmds, "$CFG_CC $cflags -I$CFG_INCLUDEDIR $opt -c $s");
376 # create link command
377 my $cmd = "$CFG_LD_SHLIB $CFG_LDFLAGS_SHLIB -o $dso_file";
383 my ($opt_Wl, $opt_L, $opt_l);
384 foreach $opt_Wl (@opt_W) {
385 if($CFG_LD_SHLIB ne "gcc") {
386 $opt .= " $1" if ($opt_Wl =~ m|^\s*l,(.*)$|);
388 $opt .= " -W$opt_Wl";
391 foreach $opt_L (@opt_L) {
394 foreach $opt_l (@opt_l) {
398 $cmd .= " $CFG_LIBS_SHLIB";
401 # execute the commands
402 &execute_cmds(@cmds);
404 # allow one-step compilation and installation
405 if ($opt_i or $opt_e) {
406 @args = ( $dso_file );
410 if ($opt_i or $opt_e) {
412 ## SHARED OBJECT INSTALLATION
415 # determine installation commands
416 # and corresponding LoadModule/AddModule directives
422 if ($f !~ m|\.so$|) {
423 print STDERR "apxs:Error: file $f is not a shared object\n";
427 $t =~ s|^.+/([^/]+)$|$1|;
429 push(@cmds, "cp $f $CFG_LIBEXECDIR/$t");
430 push(@cmds, "chmod 755 $CFG_LIBEXECDIR/$t");
433 # determine module symbolname and filename
435 if ($name eq 'unknown') {
438 $base =~ s|\.[^.]+$||;
440 open(FP, "<$base.c");
441 my $content = join('', <FP>);
443 if ($content =~ m|.*module\s+(?:MODULE_VAR_EXPORT\s+)?([a-zA-Z0-9_]+)_module\s*=\s*.*|s) {
445 $filename = "$base.c";
446 $filename =~ s|^[^/]+/||;
450 if ($base =~ m|.*mod_([a-zA-Z0-9_]+)\..+|) {
453 $filename =~ s|^[^/]+/||;
457 print "apxs:Error: Sorry, cannot determine bootstrap symbol name\n";
458 print "apxs:Error: Please specify one with option `-n'\n";
462 if ($filename eq '') {
463 $filename = "mod_${name}.c";
465 my $dir = $CFG_LIBEXECDIR;
466 $dir =~ s|^$CFG_PREFIX/?||;
468 push(@lmd, sprintf("LoadModule %-18s %s", "${name}_module", "$dir$t"));
469 push(@amd, sprintf("AddModule %s", $filename));
472 # execute the commands
473 &execute_cmds(@cmds);
475 # activate module via LoadModule/AddModule directive
476 if ($opt_a or $opt_A) {
477 if (not -f "$CFG_SYSCONFDIR/$CFG_TARGET.conf") {
478 print "apxs:Error: Config file $CFG_SYSCONFDIR/$CFG_TARGET.conf not found\n";
482 open(FP, "<$CFG_SYSCONFDIR/$CFG_TARGET.conf") || die;
483 my $content = join('', <FP>);
486 if ($content !~ m|\n#?\s*LoadModule\s+|) {
487 print STDERR "apxs:Error: Activation failed for custom $CFG_SYSCONFDIR/$CFG_TARGET.conf file.\n";
488 print STDERR "apxs:Error: At least one `LoadModule' directive already has to exist.\n";
494 $c = '#' if ($opt_A);
495 foreach $lmd (@lmd) {
496 my $what = $opt_A ? "preparing" : "activating";
497 if ($content !~ m|\n#?\s*$lmd|) {
498 $content =~ s|^(.*\n#?\s*LoadModule\s+[^\n]+\n)|$1$c$lmd\n|sg;
500 $content =~ s|^(.*\n)#?\s*$lmd[^\n]*\n|$1$c$lmd\n|sg;
502 $lmd =~ m|LoadModule\s+(.+?)_module.*|;
503 print STDERR "[$what module `$1' in $CFG_SYSCONFDIR/$CFG_TARGET.conf]\n";
506 foreach $amd (@amd) {
507 if ($content !~ m|\n#?\s*$amd|) {
508 $content =~ s|^(.*\n#?\s*AddModule\s+[^\n]+\n)|$1$c$amd\n|sg;
510 $content =~ s|^(.*\n)#?\s*$amd[^\n]*\n|$1$c$amd\n|sg;
514 open(FP, ">$CFG_SYSCONFDIR/$CFG_TARGET.conf.new") || die;
517 system("cp $CFG_SYSCONFDIR/$CFG_TARGET.conf $CFG_SYSCONFDIR/$CFG_TARGET.conf.bak && " .
518 "cp $CFG_SYSCONFDIR/$CFG_TARGET.conf.new $CFG_SYSCONFDIR/$CFG_TARGET.conf && " .
519 "rm $CFG_SYSCONFDIR/$CFG_TARGET.conf.new");
527 ## Makefile -- Build procedure for sample %NAME% Apache module
528 ## Autogenerated via ``apxs -n %NAME% -g''.
535 # additional defines, includes and libraries
536 #DEF=-Dmy_define=my_value
537 #INC=-Imy/include/dir
538 #LIB=-Lmy/lib/dir -lmylib
543 # compile the shared object file
544 mod_%NAME%.so: mod_%NAME%.c
545 $(APXS) -c $(DEF) $(INC) $(LIB) mod_%NAME%.c
547 # install the shared object file into Apache
549 $(APXS) -i -a -n '%NAME%' mod_%NAME%.so
553 -rm -f mod_%NAME%.o mod_%NAME%.so
557 lynx -mime_header http://localhost/%NAME%
559 # install and activate shared object by reloading Apache to
560 # force a reload of the shared object file
561 reload: install restart
563 # the general Apache start/restart/stop
574 ** mod_%NAME%.c -- Apache sample %NAME% module
575 ** [Autogenerated via ``apxs -n %NAME% -g'']
577 ** To play with this sample module first compile it into a
578 ** DSO file and install it into Apache's libexec directory
581 ** $ apxs -c -i mod_%NAME%.c
583 ** Then activate it in Apache's %TARGET%.conf file for instance
584 ** for the URL /%NAME% in as follows:
587 ** LoadModule %NAME%_module libexec/mod_%NAME%.so
588 ** <Location /%NAME%>
592 ** Then after restarting Apache via
594 ** $ apachectl restart
596 ** you immediately can request the URL /%NAME and watch for the
597 ** output of this module. This can be achieved for instance via:
599 ** $ lynx -mime_header http://localhost/%NAME%
601 ** The output should be similar to the following one:
604 ** Date: Tue, 31 Mar 1998 14:42:22 GMT
605 ** Server: Apache/1.3.4 (Unix)
607 ** Content-Type: text/html
609 ** The sample page from mod_%NAME%.c
613 #include "http_config.h"
614 #include "http_protocol.h"
615 #include "ap_config.h"
617 /* The sample content handler */
618 static int %NAME%_handler(request_rec *r)
620 r->content_type = "text/html";
621 ap_send_http_header(r);
623 ap_rputs("The sample page from mod_%NAME%.c\n", r);
627 /* Dispatch list of content handlers */
628 static const handler_rec %NAME%_handlers[] = {
629 { "%NAME%", %NAME%_handler },
633 /* Dispatch list for API hooks */
634 module MODULE_VAR_EXPORT %NAME%_module = {
635 STANDARD_MODULE_STUFF,
636 NULL, /* module initializer */
637 NULL, /* create per-dir config structures */
638 NULL, /* merge per-dir config structures */
639 NULL, /* create per-server config structures */
640 NULL, /* merge per-server config structures */
641 NULL, /* table of config file commands */
642 %NAME%_handlers, /* [#8] MIME-typed-dispatched handlers */
643 NULL, /* [#1] URI to filename translation */
644 NULL, /* [#4] validate user id from request */
645 NULL, /* [#5] check if the user is ok _here_ */
646 NULL, /* [#3] check access by host address */
647 NULL, /* [#6] determine MIME type */
648 NULL, /* [#7] pre-run fixups */
649 NULL, /* [#9] log a transaction */
650 NULL, /* [#2] header parser */
651 NULL, /* child_init */
652 NULL, /* child_exit */
653 NULL /* [#0] post read-request */