1 | #!@perlbin@ -w
|
---|
2 | #
|
---|
3 | # Licensed to the Apache Software Foundation (ASF) under one or more
|
---|
4 | # contributor license agreements. See the NOTICE file distributed with
|
---|
5 | # this work for additional information regarding copyright ownership.
|
---|
6 | # The ASF licenses this file to You under the Apache License, Version 2.0
|
---|
7 | # (the "License"); you may not use this file except in compliance with
|
---|
8 | # the License. You may obtain a copy of the License at
|
---|
9 | #
|
---|
10 | # http://www.apache.org/licenses/LICENSE-2.0
|
---|
11 | #
|
---|
12 | # Unless required by applicable law or agreed to in writing, software
|
---|
13 | # distributed under the License is distributed on an "AS IS" BASIS,
|
---|
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
15 | # See the License for the specific language governing permissions and
|
---|
16 | # limitations under the License.
|
---|
17 |
|
---|
18 | require 5.004;
|
---|
19 | use strict;
|
---|
20 | package apxs;
|
---|
21 |
|
---|
22 | ##
|
---|
23 | ## Configuration
|
---|
24 | ##
|
---|
25 |
|
---|
26 | my %config_vars = ();
|
---|
27 |
|
---|
28 | my $installbuilddir = "@exp_installbuilddir@";
|
---|
29 | get_config_vars("$installbuilddir/config_vars.mk",\%config_vars);
|
---|
30 |
|
---|
31 | # read the configuration variables once
|
---|
32 |
|
---|
33 | my $prefix = get_vars("prefix");
|
---|
34 | my $CFG_PREFIX = $prefix;
|
---|
35 | my $exec_prefix = get_vars("exec_prefix");
|
---|
36 | my $datadir = get_vars("datadir");
|
---|
37 | my $localstatedir = get_vars("localstatedir");
|
---|
38 | my $CFG_TARGET = get_vars("progname");
|
---|
39 | my $CFG_SYSCONFDIR = get_vars("sysconfdir");
|
---|
40 | my $CFG_CFLAGS = join ' ', map { get_vars($_) }
|
---|
41 | qw(SHLTCFLAGS CFLAGS NOTEST_CPPFLAGS EXTRA_CPPFLAGS EXTRA_CFLAGS);
|
---|
42 | my $includedir = get_vars("includedir");
|
---|
43 | my $CFG_INCLUDEDIR = eval qq("$includedir");
|
---|
44 | my $CFG_CC = get_vars("CC");
|
---|
45 | my $libexecdir = get_vars("libexecdir");
|
---|
46 | my $CFG_LIBEXECDIR = eval qq("$libexecdir");
|
---|
47 | my $sbindir = get_vars("sbindir");
|
---|
48 | my $CFG_SBINDIR = eval qq("$sbindir");
|
---|
49 | my $ltflags = $ENV{'LTFLAGS'};
|
---|
50 | $ltflags or $ltflags = "--silent";
|
---|
51 |
|
---|
52 | my %internal_vars = map {$_ => 1}
|
---|
53 | qw(TARGET CC CFLAGS CFLAGS_SHLIB LD_SHLIB LDFLAGS_SHLIB LIBS_SHLIB
|
---|
54 | PREFIX SBINDIR INCLUDEDIR LIBEXECDIR SYSCONFDIR);
|
---|
55 |
|
---|
56 | ##
|
---|
57 | ## parse argument line
|
---|
58 | ##
|
---|
59 |
|
---|
60 | # defaults for parameters
|
---|
61 | my $opt_n = '';
|
---|
62 | my $opt_g = '';
|
---|
63 | my $opt_c = 0;
|
---|
64 | my $opt_o = '';
|
---|
65 | my @opt_D = ();
|
---|
66 | my @opt_I = ();
|
---|
67 | my @opt_L = ();
|
---|
68 | my @opt_l = ();
|
---|
69 | my @opt_W = ();
|
---|
70 | my @opt_S = ();
|
---|
71 | my $opt_e = 0;
|
---|
72 | my $opt_i = 0;
|
---|
73 | my $opt_a = 0;
|
---|
74 | my $opt_A = 0;
|
---|
75 | my $opt_q = 0;
|
---|
76 | my $opt_h = 0;
|
---|
77 | my $opt_p = 0;
|
---|
78 |
|
---|
79 | # this subroutine is derived from Perl's getopts.pl with the enhancement of
|
---|
80 | # the "+" metacharacter at the format string to allow a list to be built by
|
---|
81 | # subsequent occurrences of the same option.
|
---|
82 | sub Getopts {
|
---|
83 | my ($argumentative, @ARGV) = @_;
|
---|
84 | my $errs = 0;
|
---|
85 | local $_;
|
---|
86 | local $[ = 0;
|
---|
87 |
|
---|
88 | my @args = split / */, $argumentative;
|
---|
89 | while (@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
|
---|
90 | my ($first, $rest) = ($1,$2);
|
---|
91 | if ($_ =~ m|^--$|) {
|
---|
92 | shift @ARGV;
|
---|
93 | last;
|
---|
94 | }
|
---|
95 | my $pos = index($argumentative,$first);
|
---|
96 | if ($pos >= $[) {
|
---|
97 | if ($pos < $#args && $args[$pos+1] eq ':') {
|
---|
98 | shift @ARGV;
|
---|
99 | if ($rest eq '') {
|
---|
100 | unless (@ARGV) {
|
---|
101 | error("Incomplete option: $first (needs an argument)");
|
---|
102 | $errs++;
|
---|
103 | }
|
---|
104 | $rest = shift(@ARGV);
|
---|
105 | }
|
---|
106 | eval "\$opt_$first = \$rest;";
|
---|
107 | }
|
---|
108 | elsif ($pos < $#args && $args[$pos+1] eq '+') {
|
---|
109 | shift @ARGV;
|
---|
110 | if ($rest eq '') {
|
---|
111 | unless (@ARGV) {
|
---|
112 | error("Incomplete option: $first (needs an argument)");
|
---|
113 | $errs++;
|
---|
114 | }
|
---|
115 | $rest = shift(@ARGV);
|
---|
116 | }
|
---|
117 | eval "push(\@opt_$first, \$rest);";
|
---|
118 | }
|
---|
119 | else {
|
---|
120 | eval "\$opt_$first = 1";
|
---|
121 | if ($rest eq '') {
|
---|
122 | shift(@ARGV);
|
---|
123 | }
|
---|
124 | else {
|
---|
125 | $ARGV[0] = "-$rest";
|
---|
126 | }
|
---|
127 | }
|
---|
128 | }
|
---|
129 | else {
|
---|
130 | error("Unknown option: $first");
|
---|
131 | $errs++;
|
---|
132 | if ($rest ne '') {
|
---|
133 | $ARGV[0] = "-$rest";
|
---|
134 | }
|
---|
135 | else {
|
---|
136 | shift(@ARGV);
|
---|
137 | }
|
---|
138 | }
|
---|
139 | }
|
---|
140 | return ($errs == 0, @ARGV);
|
---|
141 | }
|
---|
142 |
|
---|
143 | sub usage {
|
---|
144 | print STDERR "Usage: apxs -g [-S <var>=<val>] -n <modname>\n";
|
---|
145 | print STDERR " apxs -q [-S <var>=<val>] <query> ...\n";
|
---|
146 | print STDERR " apxs -c [-S <var>=<val>] [-o <dsofile>] [-D <name>[=<value>]]\n";
|
---|
147 | print STDERR " [-I <incdir>] [-L <libdir>] [-l <libname>] [-Wc,<flags>]\n";
|
---|
148 | print STDERR " [-Wl,<flags>] [-p] <files> ...\n";
|
---|
149 | print STDERR " apxs -i [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
|
---|
150 | print STDERR " apxs -e [-S <var>=<val>] [-a] [-A] [-n <modname>] <dsofile> ...\n";
|
---|
151 | exit(1);
|
---|
152 | }
|
---|
153 |
|
---|
154 | # option handling
|
---|
155 | my $rc;
|
---|
156 | ($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+W+S+eiaAp", @ARGV);
|
---|
157 | &usage if ($rc == 0);
|
---|
158 | &usage if ($#ARGV == -1 and not $opt_g);
|
---|
159 | &usage if (not $opt_q and not ($opt_g and $opt_n) and not $opt_i and not $opt_c and not $opt_e);
|
---|
160 |
|
---|
161 | # argument handling
|
---|
162 | my @args = @ARGV;
|
---|
163 | my $name = 'unknown';
|
---|
164 | $name = $opt_n if ($opt_n ne '');
|
---|
165 |
|
---|
166 | if (@opt_S) {
|
---|
167 | my ($opt_S);
|
---|
168 | foreach $opt_S (@opt_S) {
|
---|
169 | if ($opt_S =~ m/^([^=]+)=(.*)$/) {
|
---|
170 | my ($var) = $1;
|
---|
171 | my ($val) = $2;
|
---|
172 | my $oldval = eval "\$CFG_$var";
|
---|
173 |
|
---|
174 | unless ($var and $oldval) {
|
---|
175 | print STDERR "apxs:Error: no config variable $var\n";
|
---|
176 | &usage;
|
---|
177 | }
|
---|
178 |
|
---|
179 | eval "\$CFG_${var}=\"${val}\"";
|
---|
180 | } else {
|
---|
181 | print STDERR "apxs:Error: malformatted -S option\n";
|
---|
182 | &usage;
|
---|
183 | }
|
---|
184 | }
|
---|
185 | }
|
---|
186 |
|
---|
187 | ##
|
---|
188 | ## Initial shared object support check
|
---|
189 | ##
|
---|
190 | my $httpd = get_vars("sbindir") . "/" . get_vars("progname");
|
---|
191 | $httpd = eval qq("$httpd");
|
---|
192 | $httpd = eval qq("$httpd");
|
---|
193 | my $envvars = get_vars("sbindir") . "/envvars";
|
---|
194 | $envvars = eval qq("$envvars");
|
---|
195 | $envvars = eval qq("$envvars");
|
---|
196 |
|
---|
197 | #allow apxs to be run from the source tree, before installation
|
---|
198 | if ($0 =~ m:support/apxs$:) {
|
---|
199 | ($httpd = $0) =~ s:support/apxs$::;
|
---|
200 | }
|
---|
201 |
|
---|
202 | unless (-x "$httpd") {
|
---|
203 | error("$httpd not found or not executable");
|
---|
204 | exit 1;
|
---|
205 | }
|
---|
206 |
|
---|
207 | unless (grep /mod_so/, `. $envvars && $httpd -l`) {
|
---|
208 | error("Sorry, no shared object support for Apache");
|
---|
209 | error("available under your platform. Make sure");
|
---|
210 | error("the Apache module mod_so is compiled into");
|
---|
211 | error("your server binary `$httpd'.");
|
---|
212 | exit 1;
|
---|
213 | }
|
---|
214 |
|
---|
215 | sub get_config_vars{
|
---|
216 | my ($file, $rh_config) = @_;
|
---|
217 |
|
---|
218 | open IN, $file or die "cannot open $file: $!";
|
---|
219 | while (<IN>){
|
---|
220 | if (/^\s*(.*?)\s*=\s*(.*)$/){
|
---|
221 | $rh_config->{$1} = $2;
|
---|
222 | }
|
---|
223 | }
|
---|
224 | close IN;
|
---|
225 | }
|
---|
226 |
|
---|
227 | sub get_vars {
|
---|
228 | my $result = '';
|
---|
229 | my $ok = 0;
|
---|
230 | my $arg;
|
---|
231 | foreach $arg (@_) {
|
---|
232 | if (exists $config_vars{$arg} or exists $config_vars{lc $arg}) {
|
---|
233 | my $val = exists $config_vars{$arg}
|
---|
234 | ? $config_vars{$arg}
|
---|
235 | : $config_vars{lc $arg};
|
---|
236 | $val =~ s/[()]//g;
|
---|
237 | $result .= eval "qq($val)" if defined $val;
|
---|
238 | $result .= ";;";
|
---|
239 | $ok = 1;
|
---|
240 | }
|
---|
241 | if (not $ok) {
|
---|
242 | if (exists $internal_vars{$arg} or exists $internal_vars{lc $arg}) {
|
---|
243 | my $val = exists $internal_vars{$arg} ? $arg : lc $arg;
|
---|
244 | $val = eval "\$CFG_$val";
|
---|
245 | $result .= eval "qq($val)" if defined $val;
|
---|
246 | $result .= ";;";
|
---|
247 | $ok = 1;
|
---|
248 | }
|
---|
249 | if (not $ok) {
|
---|
250 | error("Invalid query string `$arg'");
|
---|
251 | exit(1);
|
---|
252 | }
|
---|
253 | }
|
---|
254 | }
|
---|
255 | $result =~ s|;;$||;
|
---|
256 | $result =~ s|:| |;
|
---|
257 | return $result;
|
---|
258 | }
|
---|
259 |
|
---|
260 | ##
|
---|
261 | ## Operation
|
---|
262 | ##
|
---|
263 |
|
---|
264 | # helper function for executing a list of
|
---|
265 | # system command with return code checks
|
---|
266 | sub execute_cmds {
|
---|
267 | my (@cmds) = @_;
|
---|
268 | my ($cmd, $rc);
|
---|
269 |
|
---|
270 | foreach $cmd (@cmds) {
|
---|
271 | notice($cmd);
|
---|
272 | $rc = system $cmd;
|
---|
273 | if ($rc) {
|
---|
274 | error(sprintf "Command failed with rc=%d\n", $rc << 8);
|
---|
275 | exit 1 ;
|
---|
276 | }
|
---|
277 | }
|
---|
278 | }
|
---|
279 |
|
---|
280 | if ($opt_g) {
|
---|
281 | ##
|
---|
282 | ## SAMPLE MODULE SOURCE GENERATION
|
---|
283 | ##
|
---|
284 |
|
---|
285 | if (-d $name) {
|
---|
286 | error("Directory `$name' already exists. Remove first");
|
---|
287 | exit(1);
|
---|
288 | }
|
---|
289 |
|
---|
290 | my $data = join('', <DATA>);
|
---|
291 | $data =~ s|%NAME%|$name|sg;
|
---|
292 | $data =~ s|%TARGET%|$CFG_TARGET|sg;
|
---|
293 | $data =~ s|%PREFIX%|$prefix|sg;
|
---|
294 | $data =~ s|%INSTALLBUILDDIR%|$installbuilddir|sg;
|
---|
295 |
|
---|
296 | my ($mkf, $mods, $src) = ($data =~ m|^(.+)-=#=-\n(.+)-=#=-\n(.+)|s);
|
---|
297 |
|
---|
298 | notice("Creating [DIR] $name");
|
---|
299 | system("mkdir $name");
|
---|
300 | notice("Creating [FILE] $name/Makefile");
|
---|
301 | open(FP, ">${name}/Makefile") || die;
|
---|
302 | print FP $mkf;
|
---|
303 | close(FP);
|
---|
304 | notice("Creating [FILE] $name/modules.mk");
|
---|
305 | open(FP, ">${name}/modules.mk") || die;
|
---|
306 | print FP $mods;
|
---|
307 | close(FP);
|
---|
308 | notice("Creating [FILE] $name/mod_$name.c");
|
---|
309 | open(FP, ">${name}/mod_${name}.c") || die;
|
---|
310 | print FP $src;
|
---|
311 | close(FP);
|
---|
312 | notice("Creating [FILE] $name/.deps");
|
---|
313 | system("touch ${name}/.deps");
|
---|
314 |
|
---|
315 | exit(0);
|
---|
316 | }
|
---|
317 |
|
---|
318 |
|
---|
319 | if ($opt_q) {
|
---|
320 | ##
|
---|
321 | ## QUERY INFORMATION
|
---|
322 | ##
|
---|
323 | my $result = get_vars(@args);
|
---|
324 | print "$result\n";
|
---|
325 | }
|
---|
326 |
|
---|
327 | my $apr_config = get_vars("APR_CONFIG");
|
---|
328 |
|
---|
329 | if (! -x "$apr_config") {
|
---|
330 | error("$apr_config not found!");
|
---|
331 | exit(1);
|
---|
332 | }
|
---|
333 |
|
---|
334 | my $apu_config = get_vars("APU_CONFIG");
|
---|
335 |
|
---|
336 | if (! -x "$apu_config") {
|
---|
337 | error("$apu_config not found!");
|
---|
338 | exit(1);
|
---|
339 | }
|
---|
340 |
|
---|
341 | my $libtool = `$apr_config --apr-libtool`;
|
---|
342 | chomp($libtool);
|
---|
343 |
|
---|
344 | my $apr_includedir = `$apr_config --includes`;
|
---|
345 | chomp($apr_includedir);
|
---|
346 | my $apu_includedir = `$apu_config --includes`;
|
---|
347 | chomp($apu_includedir);
|
---|
348 |
|
---|
349 | if ($opt_c) {
|
---|
350 | ##
|
---|
351 | ## SHARED OBJECT COMPILATION
|
---|
352 | ##
|
---|
353 |
|
---|
354 | # split files into sources and objects
|
---|
355 | my @srcs = ();
|
---|
356 | my @objs = ();
|
---|
357 | my $f;
|
---|
358 | foreach $f (@args) {
|
---|
359 | if ($f =~ m|\.c$|) {
|
---|
360 | push(@srcs, $f);
|
---|
361 | }
|
---|
362 | else {
|
---|
363 | push(@objs, $f);
|
---|
364 | }
|
---|
365 | }
|
---|
366 |
|
---|
367 | # determine output file
|
---|
368 | my $dso_file;
|
---|
369 | if ($opt_o eq '') {
|
---|
370 | if ($#srcs > -1) {
|
---|
371 | $dso_file = $srcs[0];
|
---|
372 | $dso_file =~ s|\.[^.]+$|.la|;
|
---|
373 | }
|
---|
374 | elsif ($#objs > -1) {
|
---|
375 | $dso_file = $objs[0];
|
---|
376 | $dso_file =~ s|\.[^.]+$|.la|;
|
---|
377 | }
|
---|
378 | else {
|
---|
379 | $dso_file = "mod_unknown.la";
|
---|
380 | }
|
---|
381 | }
|
---|
382 | else {
|
---|
383 | $dso_file = $opt_o;
|
---|
384 | $dso_file =~ s|\.[^.]+$|.la|;
|
---|
385 | }
|
---|
386 |
|
---|
387 | # create compilation commands
|
---|
388 | my @cmds = ();
|
---|
389 | my $opt = '';
|
---|
390 | my ($opt_Wc, $opt_I, $opt_D);
|
---|
391 | foreach $opt_Wc (@opt_W) {
|
---|
392 | $opt .= "$1 " if ($opt_Wc =~ m|^\s*c,(.*)$|);
|
---|
393 | }
|
---|
394 | foreach $opt_I (@opt_I) {
|
---|
395 | $opt .= "-I$opt_I ";
|
---|
396 | }
|
---|
397 | foreach $opt_D (@opt_D) {
|
---|
398 | $opt .= "-D$opt_D ";
|
---|
399 | }
|
---|
400 | my $cflags = "$CFG_CFLAGS";
|
---|
401 | my $s;
|
---|
402 | my $mod;
|
---|
403 | foreach $s (@srcs) {
|
---|
404 | my $slo = $s;
|
---|
405 | $slo =~ s|\.c$|.slo|;
|
---|
406 | my $lo = $s;
|
---|
407 | $lo =~ s|\.c$|.lo|;
|
---|
408 | my $la = $s;
|
---|
409 | $la =~ s|\.c$|.la|;
|
---|
410 | my $o = $s;
|
---|
411 | $o =~ s|\.c$|.o|;
|
---|
412 | push(@cmds, "$libtool $ltflags --mode=compile $CFG_CC $cflags -I$CFG_INCLUDEDIR $apr_includedir $apu_includedir $opt -c -o $lo $s && touch $slo");
|
---|
413 | unshift(@objs, $lo);
|
---|
414 | }
|
---|
415 |
|
---|
416 | # create link command
|
---|
417 | my $o;
|
---|
418 | my $lo;
|
---|
419 | foreach $o (@objs) {
|
---|
420 | $lo .= " $o";
|
---|
421 | }
|
---|
422 | my ($opt_Wl, $opt_L, $opt_l);
|
---|
423 | $opt = '';
|
---|
424 | foreach $opt_Wl (@opt_W) {
|
---|
425 | $opt .= "$1 " if ($opt_Wl =~ m|^\s*l,(.*)$|);
|
---|
426 | }
|
---|
427 | foreach $opt_L (@opt_L) {
|
---|
428 | $opt .= " -L$opt_L";
|
---|
429 | }
|
---|
430 | foreach $opt_l (@opt_l) {
|
---|
431 | $opt .= " -l$opt_l";
|
---|
432 | }
|
---|
433 |
|
---|
434 | if ($opt_p == 1) {
|
---|
435 |
|
---|
436 | my $apr_libs=`$apr_config --cflags --ldflags --link-libtool --libs`;
|
---|
437 | chomp($apr_libs);
|
---|
438 | my $apu_libs=`$apu_config --ldflags --link-libtool --libs`;
|
---|
439 | chomp($apu_libs);
|
---|
440 |
|
---|
441 | $opt .= " ".$apu_libs." ".$apr_libs;
|
---|
442 | }
|
---|
443 | else {
|
---|
444 | my $apr_ldflags=`$apr_config --ldflags`;
|
---|
445 | chomp($apr_ldflags);
|
---|
446 | $opt .= " -rpath $CFG_LIBEXECDIR -module -avoid-version $apr_ldflags";
|
---|
447 | }
|
---|
448 |
|
---|
449 | push(@cmds, "$libtool $ltflags --mode=link $CFG_CC -o $dso_file $opt $lo");
|
---|
450 |
|
---|
451 | # execute the commands
|
---|
452 | &execute_cmds(@cmds);
|
---|
453 |
|
---|
454 | # allow one-step compilation and installation
|
---|
455 | if ($opt_i or $opt_e) {
|
---|
456 | @args = ( $dso_file );
|
---|
457 | }
|
---|
458 | }
|
---|
459 |
|
---|
460 | if ($opt_i or $opt_e) {
|
---|
461 | ##
|
---|
462 | ## SHARED OBJECT INSTALLATION
|
---|
463 | ##
|
---|
464 |
|
---|
465 | # determine installation commands
|
---|
466 | # and corresponding LoadModule directive
|
---|
467 | my @lmd = ();
|
---|
468 | my @cmds = ();
|
---|
469 | my $f;
|
---|
470 | foreach $f (@args) {
|
---|
471 | # ack all potential gcc, hp/ux, win32+os2+aix and os/x extensions
|
---|
472 | if ($f !~ m#(\.so$|\.la$|\.sl$|\.dll$|\.dylib$|)#) {
|
---|
473 | error("file $f is not a shared object");
|
---|
474 | exit(1);
|
---|
475 | }
|
---|
476 | my $t = $f;
|
---|
477 | $t =~ s|^.+/([^/]+)$|$1|;
|
---|
478 | # use .so unambigiously for installed shared library modules
|
---|
479 | $t =~ s|\.[^./\\]+$|\.so|;
|
---|
480 | if ($opt_i) {
|
---|
481 | push(@cmds, "$installbuilddir/instdso.sh SH_LIBTOOL='" .
|
---|
482 | "$libtool' $f $CFG_LIBEXECDIR");
|
---|
483 | push(@cmds, "chmod 755 $CFG_LIBEXECDIR/$t");
|
---|
484 | }
|
---|
485 |
|
---|
486 | # determine module symbolname and filename
|
---|
487 | my $filename = '';
|
---|
488 | if ($name eq 'unknown') {
|
---|
489 | $name = '';
|
---|
490 | my $base = $f;
|
---|
491 | $base =~ s|\.[^.]+$||;
|
---|
492 | if (-f "$base.c") {
|
---|
493 | open(FP, "<$base.c");
|
---|
494 | my $content = join('', <FP>);
|
---|
495 | close(FP);
|
---|
496 | if ($content =~ m|.*module\s+(?:AP_MODULE_DECLARE_DATA\s+)?([a-zA-Z0-9_]+)_module\s*=\s*.*|s) {
|
---|
497 | $name = "$1";
|
---|
498 | $filename = "$base.c";
|
---|
499 | $filename =~ s|^[^/]+/||;
|
---|
500 | }
|
---|
501 | }
|
---|
502 | if ($name eq '') {
|
---|
503 | if ($base =~ m|.*mod_([a-zA-Z0-9_]+)\..+|) {
|
---|
504 | $name = "$1";
|
---|
505 | $filename = $base;
|
---|
506 | $filename =~ s|^[^/]+/||;
|
---|
507 | }
|
---|
508 | }
|
---|
509 | if ($name eq '') {
|
---|
510 | error("Sorry, cannot determine bootstrap symbol name");
|
---|
511 | error("Please specify one with option `-n'");
|
---|
512 | exit(1);
|
---|
513 | }
|
---|
514 | }
|
---|
515 | if ($filename eq '') {
|
---|
516 | $filename = "mod_${name}.c";
|
---|
517 | }
|
---|
518 | my $dir = $CFG_LIBEXECDIR;
|
---|
519 | $dir =~ s|^$CFG_PREFIX/?||;
|
---|
520 | $dir =~ s|(.)$|$1/|;
|
---|
521 | $t =~ s|\.la$|.so|;
|
---|
522 | push(@lmd, sprintf("LoadModule %-18s %s", "${name}_module", "$dir$t"));
|
---|
523 | }
|
---|
524 |
|
---|
525 | # execute the commands
|
---|
526 | &execute_cmds(@cmds);
|
---|
527 |
|
---|
528 | # activate module via LoadModule/AddModule directive
|
---|
529 | if ($opt_a or $opt_A) {
|
---|
530 | if (not -f "$CFG_SYSCONFDIR/$CFG_TARGET.conf") {
|
---|
531 | error("Config file $CFG_SYSCONFDIR/$CFG_TARGET.conf not found");
|
---|
532 | exit(1);
|
---|
533 | }
|
---|
534 |
|
---|
535 | open(FP, "<$CFG_SYSCONFDIR/$CFG_TARGET.conf") || die;
|
---|
536 | my $content = join('', <FP>);
|
---|
537 | close(FP);
|
---|
538 |
|
---|
539 | if ($content !~ m|\n#?\s*LoadModule\s+|) {
|
---|
540 | error("Activation failed for custom $CFG_SYSCONFDIR/$CFG_TARGET.conf file.");
|
---|
541 | error("At least one `LoadModule' directive already has to exist.");
|
---|
542 | exit(1);
|
---|
543 | }
|
---|
544 |
|
---|
545 | my $lmd;
|
---|
546 | my $c = '';
|
---|
547 | $c = '#' if ($opt_A);
|
---|
548 | foreach $lmd (@lmd) {
|
---|
549 | my $what = $opt_A ? "preparing" : "activating";
|
---|
550 | if ($content !~ m|\n#?\s*$lmd|) {
|
---|
551 | # check for open <containers>, so that the new LoadModule
|
---|
552 | # directive always appears *outside* of an <container>.
|
---|
553 |
|
---|
554 | my $before = ($content =~ m|^(.*\n)#?\s*LoadModule\s+[^\n]+\n|s)[0];
|
---|
555 |
|
---|
556 | # the '()=' trick forces list context and the scalar
|
---|
557 | # assignment counts the number of list members (aka number
|
---|
558 | # of matches) then
|
---|
559 | my $cntopen = () = ($before =~ m|^\s*<[^/].*$|mg);
|
---|
560 | my $cntclose = () = ($before =~ m|^\s*</.*$|mg);
|
---|
561 |
|
---|
562 | if ($cntopen == $cntclose) {
|
---|
563 | # fine. Last LoadModule is contextless.
|
---|
564 | $content =~ s|^(.*\n#?\s*LoadModule\s+[^\n]+\n)|$1$c$lmd\n|s;
|
---|
565 | }
|
---|
566 | elsif ($cntopen < $cntclose) {
|
---|
567 | error('Configuration file is not valid. There are sections'
|
---|
568 | . ' closed before opened.');
|
---|
569 | exit(1);
|
---|
570 | }
|
---|
571 | else {
|
---|
572 | # put our cmd after the section containing the last
|
---|
573 | # LoadModule.
|
---|
574 | my $found =
|
---|
575 | $content =~ s!\A ( # string and capture start
|
---|
576 | (?:(?:
|
---|
577 | ^\s* # start of conf line with a
|
---|
578 | (?:[^<]|<[^/]) # directive which does not
|
---|
579 | # start with '</'
|
---|
580 |
|
---|
581 | .*(?:$)\n # rest of the line.
|
---|
582 | # the '$' is in parentheses
|
---|
583 | # to avoid misinterpreting
|
---|
584 | # the string "$\" as
|
---|
585 | # perl variable.
|
---|
586 |
|
---|
587 | )* # catch as much as possible
|
---|
588 | # of such lines. (including
|
---|
589 | # zero)
|
---|
590 |
|
---|
591 | ^\s*</.*(?:$)\n? # after the above, we
|
---|
592 | # expect a config line with
|
---|
593 | # a closing container (</)
|
---|
594 |
|
---|
595 | ) {$cntopen} # the whole pattern (bunch
|
---|
596 | # of lines that end up with
|
---|
597 | # a closing directive) must
|
---|
598 | # be repeated $cntopen
|
---|
599 | # times. That's it.
|
---|
600 | # Simple, eh? ;-)
|
---|
601 |
|
---|
602 | ) # capture end
|
---|
603 | !$1$c$lmd\n!mx;
|
---|
604 |
|
---|
605 | unless ($found) {
|
---|
606 | error('Configuration file is not valid. There are '
|
---|
607 | . 'sections opened and not closed.');
|
---|
608 | exit(1);
|
---|
609 | }
|
---|
610 | }
|
---|
611 | } else {
|
---|
612 | # replace already existing LoadModule line
|
---|
613 | $content =~ s|^(.*\n)#?\s*$lmd[^\n]*\n|$1$c$lmd\n|s;
|
---|
614 | }
|
---|
615 | $lmd =~ m|LoadModule\s+(.+?)_module.*|;
|
---|
616 | notice("[$what module `$1' in $CFG_SYSCONFDIR/$CFG_TARGET.conf]");
|
---|
617 | }
|
---|
618 | if (@lmd) {
|
---|
619 | if (open(FP, ">$CFG_SYSCONFDIR/$CFG_TARGET.conf.new")) {
|
---|
620 | print FP $content;
|
---|
621 | close(FP);
|
---|
622 | system("cp $CFG_SYSCONFDIR/$CFG_TARGET.conf $CFG_SYSCONFDIR/$CFG_TARGET.conf.bak && " .
|
---|
623 | "cp $CFG_SYSCONFDIR/$CFG_TARGET.conf.new $CFG_SYSCONFDIR/$CFG_TARGET.conf && " .
|
---|
624 | "rm $CFG_SYSCONFDIR/$CFG_TARGET.conf.new");
|
---|
625 | } else {
|
---|
626 | notice("unable to open configuration file");
|
---|
627 | }
|
---|
628 | }
|
---|
629 | }
|
---|
630 | }
|
---|
631 |
|
---|
632 | sub error{
|
---|
633 | print STDERR "apxs:Error: $_[0].\n";
|
---|
634 | }
|
---|
635 |
|
---|
636 | sub notice{
|
---|
637 | print STDERR "$_[0]\n";
|
---|
638 | }
|
---|
639 |
|
---|
640 | ##EOF##
|
---|
641 | __DATA__
|
---|
642 | ##
|
---|
643 | ## Makefile -- Build procedure for sample %NAME% Apache module
|
---|
644 | ## Autogenerated via ``apxs -n %NAME% -g''.
|
---|
645 | ##
|
---|
646 |
|
---|
647 | builddir=.
|
---|
648 | top_srcdir=%PREFIX%
|
---|
649 | top_builddir=%PREFIX%
|
---|
650 | include %INSTALLBUILDDIR%/special.mk
|
---|
651 |
|
---|
652 | # the used tools
|
---|
653 | APXS=apxs
|
---|
654 | APACHECTL=apachectl
|
---|
655 |
|
---|
656 | # additional defines, includes and libraries
|
---|
657 | #DEFS=-Dmy_define=my_value
|
---|
658 | #INCLUDES=-Imy/include/dir
|
---|
659 | #LIBS=-Lmy/lib/dir -lmylib
|
---|
660 |
|
---|
661 | # the default target
|
---|
662 | all: local-shared-build
|
---|
663 |
|
---|
664 | # install the shared object file into Apache
|
---|
665 | install: install-modules-yes
|
---|
666 |
|
---|
667 | # cleanup
|
---|
668 | clean:
|
---|
669 | -rm -f mod_%NAME%.o mod_%NAME%.lo mod_%NAME%.slo mod_%NAME%.la
|
---|
670 |
|
---|
671 | # simple test
|
---|
672 | test: reload
|
---|
673 | lynx -mime_header http://localhost/%NAME%
|
---|
674 |
|
---|
675 | # install and activate shared object by reloading Apache to
|
---|
676 | # force a reload of the shared object file
|
---|
677 | reload: install restart
|
---|
678 |
|
---|
679 | # the general Apache start/restart/stop
|
---|
680 | # procedures
|
---|
681 | start:
|
---|
682 | $(APACHECTL) start
|
---|
683 | restart:
|
---|
684 | $(APACHECTL) restart
|
---|
685 | stop:
|
---|
686 | $(APACHECTL) stop
|
---|
687 |
|
---|
688 | -=#=-
|
---|
689 | mod_%NAME%.la: mod_%NAME%.slo
|
---|
690 | $(SH_LINK) -rpath $(libexecdir) -module -avoid-version mod_%NAME%.lo
|
---|
691 | DISTCLEAN_TARGETS = modules.mk
|
---|
692 | shared = mod_%NAME%.la
|
---|
693 | -=#=-
|
---|
694 | /*
|
---|
695 | ** mod_%NAME%.c -- Apache sample %NAME% module
|
---|
696 | ** [Autogenerated via ``apxs -n %NAME% -g'']
|
---|
697 | **
|
---|
698 | ** To play with this sample module first compile it into a
|
---|
699 | ** DSO file and install it into Apache's modules directory
|
---|
700 | ** by running:
|
---|
701 | **
|
---|
702 | ** $ apxs -c -i mod_%NAME%.c
|
---|
703 | **
|
---|
704 | ** Then activate it in Apache's %TARGET%.conf file for instance
|
---|
705 | ** for the URL /%NAME% in as follows:
|
---|
706 | **
|
---|
707 | ** # %TARGET%.conf
|
---|
708 | ** LoadModule %NAME%_module modules/mod_%NAME%.so
|
---|
709 | ** <Location /%NAME%>
|
---|
710 | ** SetHandler %NAME%
|
---|
711 | ** </Location>
|
---|
712 | **
|
---|
713 | ** Then after restarting Apache via
|
---|
714 | **
|
---|
715 | ** $ apachectl restart
|
---|
716 | **
|
---|
717 | ** you immediately can request the URL /%NAME% and watch for the
|
---|
718 | ** output of this module. This can be achieved for instance via:
|
---|
719 | **
|
---|
720 | ** $ lynx -mime_header http://localhost/%NAME%
|
---|
721 | **
|
---|
722 | ** The output should be similar to the following one:
|
---|
723 | **
|
---|
724 | ** HTTP/1.1 200 OK
|
---|
725 | ** Date: Tue, 31 Mar 1998 14:42:22 GMT
|
---|
726 | ** Server: Apache/1.3.4 (Unix)
|
---|
727 | ** Connection: close
|
---|
728 | ** Content-Type: text/html
|
---|
729 | **
|
---|
730 | ** The sample page from mod_%NAME%.c
|
---|
731 | */
|
---|
732 |
|
---|
733 | #include "httpd.h"
|
---|
734 | #include "http_config.h"
|
---|
735 | #include "http_protocol.h"
|
---|
736 | #include "ap_config.h"
|
---|
737 |
|
---|
738 | /* The sample content handler */
|
---|
739 | static int %NAME%_handler(request_rec *r)
|
---|
740 | {
|
---|
741 | if (strcmp(r->handler, "%NAME%")) {
|
---|
742 | return DECLINED;
|
---|
743 | }
|
---|
744 | r->content_type = "text/html";
|
---|
745 |
|
---|
746 | if (!r->header_only)
|
---|
747 | ap_rputs("The sample page from mod_%NAME%.c\n", r);
|
---|
748 | return OK;
|
---|
749 | }
|
---|
750 |
|
---|
751 | static void %NAME%_register_hooks(apr_pool_t *p)
|
---|
752 | {
|
---|
753 | ap_hook_handler(%NAME%_handler, NULL, NULL, APR_HOOK_MIDDLE);
|
---|
754 | }
|
---|
755 |
|
---|
756 | /* Dispatch list for API hooks */
|
---|
757 | module AP_MODULE_DECLARE_DATA %NAME%_module = {
|
---|
758 | STANDARD20_MODULE_STUFF,
|
---|
759 | NULL, /* create per-dir config structures */
|
---|
760 | NULL, /* merge per-dir config structures */
|
---|
761 | NULL, /* create per-server config structures */
|
---|
762 | NULL, /* merge per-server config structures */
|
---|
763 | NULL, /* table of config file commands */
|
---|
764 | %NAME%_register_hooks /* register hooks */
|
---|
765 | };
|
---|
766 |
|
---|