[18814] | 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 |
|
---|