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 ## parse argument line
95 # defaults for parameters
112 # this subroutine is derived from Perl's getopts.pl with the enhancement of
113 # the "+" metacharater at the format string to allow a list to be build by
114 # subsequent occurance of the same option.
116 my ($argumentative, @ARGV) = @_;
117 my (@args, $first, $rest, $pos);
122 @args = split( / */, $argumentative);
123 while(@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
124 ($first, $rest) = ($1,$2);
129 $pos = index($argumentative,$first);
131 if($args[$pos+1] eq ':') {
135 print STDERR "apxs:Error: Incomplete option: $first (needs an argument)\n";
138 $rest = shift(@ARGV);
140 eval "\$opt_$first = \$rest;";
142 elsif ($args[$pos+1] eq '+') {
146 print STDERR "apxs:Error: Incomplete option: $first (needs an argument)\n";
149 $rest = shift(@ARGV);
151 eval "push(\@opt_$first, \$rest);";
154 eval "\$opt_$first = 1";
164 print STDERR "apxs:Error: Unknown option: $first\n";
174 return ($errs == 0, @ARGV);
178 print STDERR "Usage: apxs -g [-S <var>=<val>] -n <modname>\n";
179 print STDERR " apxs -q [-S <var>=<val>] <query> ...\n";
180 print STDERR " apxs -c [-S <var>=<val>] [-o <dsofile>] [-D <name>[=<value>]]\n";
181 print STDERR " [-I <incdir>] [-L <libdir>] [-l <libname>] [-Wc,<flags>]\n";
182 print STDERR " [-Wl,<flags>] <files> ...\n";
183 print STDERR " apxs -i [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
184 print STDERR " apxs -e [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
190 ($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+W+S+eiaA", @ARGV);
191 &usage if ($rc == 0);
192 &usage if ($#ARGV == -1 and not $opt_g);
193 &usage if (not $opt_q and not ($opt_g and $opt_n) and not $opt_i and not $opt_c and not $opt_e);
197 my $name = 'unknown';
198 $name = $opt_n if ($opt_n ne '');
202 foreach $opt_S (@opt_S) {
203 if ($opt_S =~ m/^([^=]+)=(.*)$/) {
206 my $oldval = eval "\$CFG_$var";
208 unless ($var and $oldval) {
209 print STDERR "apxs:Error: no config variable $var\n";
213 eval "\$CFG_${var}=\"${val}\"";
215 print STDERR "apxs:Error: malformatted -S option\n";
222 ## Initial shared object support check
224 if (not -x "$CFG_SBINDIR/$CFG_TARGET") {
225 print STDERR "apxs:Error: $CFG_SBINDIR/$CFG_TARGET not found or not executable\n";
228 if (not grep(/mod_so/, `$CFG_SBINDIR/$CFG_TARGET -l`)) {
229 print STDERR "apxs:Error: Sorry, no shared object support for Apache\n";
230 print STDERR "apxs:Error: available under your platform. Make sure\n";
231 print STDERR "apxs:Error: the Apache module mod_so is compiled into\n";
232 print STDERR "apxs:Error: your server binary `$CFG_SBINDIR/$CFG_TARGET'.\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 if (open(FP, ">$CFG_SYSCONFDIR/$CFG_TARGET.conf.new")) {
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");
521 print STDERR "unable to open configuration file\n";
530 ## Makefile -- Build procedure for sample %NAME% Apache module
531 ## Autogenerated via ``apxs -n %NAME% -g''.
538 # additional defines, includes and libraries
539 #DEF=-Dmy_define=my_value
540 #INC=-Imy/include/dir
541 #LIB=-Lmy/lib/dir -lmylib
546 # compile the shared object file
547 mod_%NAME%.so: mod_%NAME%.c
548 $(APXS) -c $(DEF) $(INC) $(LIB) mod_%NAME%.c
550 # install the shared object file into Apache
552 $(APXS) -i -a -n '%NAME%' mod_%NAME%.so
556 -rm -f mod_%NAME%.o mod_%NAME%.so
560 lynx -mime_header http://localhost/%NAME%
562 # install and activate shared object by reloading Apache to
563 # force a reload of the shared object file
564 reload: install restart
566 # the general Apache start/restart/stop
577 ** mod_%NAME%.c -- Apache sample %NAME% module
578 ** [Autogenerated via ``apxs -n %NAME% -g'']
580 ** To play with this sample module first compile it into a
581 ** DSO file and install it into Apache's libexec directory
584 ** $ apxs -c -i mod_%NAME%.c
586 ** Then activate it in Apache's %TARGET%.conf file for instance
587 ** for the URL /%NAME% in as follows:
590 ** LoadModule %NAME%_module libexec/mod_%NAME%.so
591 ** <Location /%NAME%>
595 ** Then after restarting Apache via
597 ** $ apachectl restart
599 ** you immediately can request the URL /%NAME and watch for the
600 ** output of this module. This can be achieved for instance via:
602 ** $ lynx -mime_header http://localhost/%NAME%
604 ** The output should be similar to the following one:
607 ** Date: Tue, 31 Mar 1998 14:42:22 GMT
608 ** Server: Apache/1.3.4 (Unix)
610 ** Content-Type: text/html
612 ** The sample page from mod_%NAME%.c
616 #include "http_config.h"
617 #include "http_protocol.h"
618 #include "ap_config.h"
620 /* The sample content handler */
621 static int %NAME%_handler(request_rec *r)
623 r->content_type = "text/html";
624 ap_send_http_header(r);
626 ap_rputs("The sample page from mod_%NAME%.c\n", r);
630 /* Dispatch list of content handlers */
631 static const handler_rec %NAME%_handlers[] = {
632 { "%NAME%", %NAME%_handler },
636 /* Dispatch list for API hooks */
637 module MODULE_VAR_EXPORT %NAME%_module = {
638 STANDARD_MODULE_STUFF,
639 NULL, /* module initializer */
640 NULL, /* create per-dir config structures */
641 NULL, /* merge per-dir config structures */
642 NULL, /* create per-server config structures */
643 NULL, /* merge per-server config structures */
644 NULL, /* table of config file commands */
645 %NAME%_handlers, /* [#8] MIME-typed-dispatched handlers */
646 NULL, /* [#1] URI to filename translation */
647 NULL, /* [#4] validate user id from request */
648 NULL, /* [#5] check if the user is ok _here_ */
649 NULL, /* [#3] check access by host address */
650 NULL, /* [#6] determine MIME type */
651 NULL, /* [#7] pre-run fixups */
652 NULL, /* [#9] log a transaction */
653 NULL, /* [#2] header parser */
654 NULL, /* child_init */
655 NULL, /* child_exit */
656 NULL /* [#0] post read-request */