diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-12-07 22:17:26 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-12-07 22:17:26 +0200 |
commit | 80da2c28a644a0640b8d167e31f28b43fc56a682 (patch) | |
tree | c1c7545065d3a81c93613b51483b50641fd84aaf | |
parent | 31a64151b3f675322eb8eadb8bae9887e0f82941 (diff) | |
download | acpp-80da2c28a644a0640b8d167e31f28b43fc56a682.tar.gz acpp-80da2c28a644a0640b8d167e31f28b43fc56a682.tar.bz2 |
Provide a way to pass arguments to the phase constructors
* Makefile.PL: Lower the required Perl version. Update prerequisites
* lib/Apache/Config/Preproc.pm (new): Get rid of -server_root.
Don't save filename along with options.
(server_root): Remove.
(_preproc): Handle optional arguments in the module list.
(_preproc_section): Don't pass $self to expand. It should have
been saved by new, if the need be.
* lib/Apache/Config/Preproc/compact.pm (new): Update.
* lib/Apache/Config/Preproc/ifmodule.pm (new): Update.
New arguments: preloaded => [ list of loaded modules ], and
probe => $val.
* lib/Apache/Config/Preproc/include.pm (new): Optional argument
server_root.
(expand): Change signature.
* lib/Apache/Config/Preproc/macro.pm (new, expand): Change signature.
-rw-r--r-- | Makefile.PL | 3 | ||||
-rw-r--r-- | lib/Apache/Config/Preproc.pm | 65 | ||||
-rw-r--r-- | lib/Apache/Config/Preproc/compact.pm | 4 | ||||
-rw-r--r-- | lib/Apache/Config/Preproc/ifmodule.pm | 180 | ||||
-rw-r--r-- | lib/Apache/Config/Preproc/include.pm | 29 | ||||
-rw-r--r-- | lib/Apache/Config/Preproc/macro.pm | 4 |
6 files changed, 234 insertions, 51 deletions
diff --git a/Makefile.PL b/Makefile.PL index f08c4f0..058045b 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -12,6 +12,7 @@ WriteMakefile(NAME => 'Apache::Config::Preproc', 'File::Spec' => '3.39_02', 'Text::ParseWords' => '3.27', 'File::Spec' => 0, + 'IPC::Open3' => 0 }, TEST_REQUIRES => { 'File::Basename' => 0, @@ -20,7 +21,7 @@ WriteMakefile(NAME => 'Apache::Config::Preproc', 'Test' => 0, 'autodie' => 0 }, - MIN_PERL_VERSION => 5.016001, + MIN_PERL_VERSION => 5.014002, META_MERGE => { 'meta-spec' => { version => 2 }, resources => { diff --git a/lib/Apache/Config/Preproc.pm b/lib/Apache/Config/Preproc.pm index 278519c..07cf61c 100644 --- a/lib/Apache/Config/Preproc.pm +++ b/lib/Apache/Config/Preproc.pm @@ -8,15 +8,13 @@ our $VERSION = '1.0'; sub new { my $class = shift; - my $server_root = Apache::Admin::Config::Tree::_get_arg(\@_, - '-server_root'); + my $file = shift; my $explist = Apache::Admin::Config::Tree::_get_arg(\@_, '-expand') || [ qw(include) ]; - my $self = $class->SUPER::new(@_) or return; + my $self = $class->SUPER::new($file, @_) or return; bless $self, $class; $self->{_options} = \@_; - $self->{_server_root} = $server_root; eval { return unless $self->_preproc($explist); @@ -29,16 +27,6 @@ sub new { return $self; } -sub server_root { - my $self = shift; - unless ($self->{_server_root}) { - if (my $d = $self->directive('ServerRoot')) { - $self->{_server_root} = $self->dequote($d->value); - } - } - return $self->{_server_root}; -} - sub dequote { my ($self, $str) = @_; if ($str =~ s/^"(.*)"$/$1/) { @@ -55,12 +43,22 @@ sub _preproc { return 1 unless @$explist; return $self->_preproc_section($self, - [ map { - my $mod = 'Apache::Config::Preproc::'.$_; - (my $file = $mod) =~ s|::|/|g; - require $file . '.pm'; - $mod->new - } @$explist ]); + [ map { + my ($mod,@arg); + if (ref($_) eq 'HASH') { + ($mod,my $ref) = each %$_; + @arg = @$ref; + } elsif (ref($_) eq 'ARRAY') { + @arg = @$_; + $mod = shift @arg; + } else { + $mod = $_; + } + $mod = 'Apache::Config::Preproc::'.$mod; + (my $file = $mod) =~ s|::|/|g; + require $file . '.pm'; + $mod->new($self, @arg) + } @$explist ]); } sub _preproc_section { @@ -70,7 +68,7 @@ sub _preproc_section { for (my $i = 0; defined(my $d = $section->select(-which => $i)); ) { foreach my $mod (@$modlist) { my @repl; - if ($mod->expand($self, $d, \@repl)) { + if ($mod->expand($d, \@repl)) { my $prev = $d; foreach my $r (@repl) { $prev = $section->add($r, -after => $prev); @@ -146,8 +144,8 @@ Rest of module functionality is inherited from B<Apache::Admin::Config>. =head2 new - $obj = new Apache::Config::Preproc [/path/to/file|handle], - [-expand => $modlist] [-server_root => $dirname] + $obj = new Apache::Config::Preproc /path/to/file|handle, + [-expand => $modlist] [-indent => $integer], ['-create'], ['-no-comment-grouping'], ['-no-blank-grouping'] @@ -165,13 +163,6 @@ expansions. If the B<-expand> argument is not supplied, only inlining of include files is performed. -=item B<-server_root> =E<gt> I<$dirname> - -Overrides the location of server root directory. By default, this -location is obtained from the value of the B<ServerRoot> statement in the -input configuration file. Use this keyword if the statement is absent (e.g. -if you are parsing an include file separately). - =back Rest of arguments is the same as for the B<Apache::Admin::Config> constructor: @@ -256,25 +247,23 @@ Each keyword I<phase> listed in the B<-expand> array causes loading of the module B<Apache::Config::Preproc::I<phase>>. This module must provide the following methods: -=head2 new +=head2 new($conf, ...) -Class constructor. Takes no arguments. +Class constructor. The B<$conf> argument is the configuration file object +(B<Apache::Config::Preproc>). Rest are arguments passed in the B<-expand> +argument. =head2 expand This method must perform actual expansion of a subtree of the parse tree. It is called as: - $phase->expand($conf, $subtree, $repl) + $phase->expand($subtree, $repl) Its arguments are: =over 4 -=item $conf - -Configuration file object (B<Apache::Config::Preproc>). - =item $subtree The subtree to be processed. @@ -295,7 +284,7 @@ is the B<expand> method definition from the B<Apache::Config::Preproc::compact> module: sub expand { - my ($self, $tree, $d, $repl) = @_; + my ($self, $d, $repl) = @_; return $d->type eq 'blank' || $d->type eq 'comment'; } diff --git a/lib/Apache/Config/Preproc/compact.pm b/lib/Apache/Config/Preproc/compact.pm index fc6e8ed..22fccc7 100644 --- a/lib/Apache/Config/Preproc/compact.pm +++ b/lib/Apache/Config/Preproc/compact.pm @@ -1,13 +1,15 @@ package Apache::Config::Preproc::compact; use strict; use warnings; +use Carp; sub new { + croak "too many arguments" unless @_ == 2; bless {}, shift } sub expand { - my ($self, $tree, $d, $repl) = @_; + my ($self, $d, $repl) = @_; return $d->type eq 'blank' || $d->type eq 'comment'; } diff --git a/lib/Apache/Config/Preproc/ifmodule.pm b/lib/Apache/Config/Preproc/ifmodule.pm index 033d20e..10cce3b 100644 --- a/lib/Apache/Config/Preproc/ifmodule.pm +++ b/lib/Apache/Config/Preproc/ifmodule.pm @@ -1,17 +1,46 @@ package Apache::Config::Preproc::ifmodule; use strict; use warnings; +use Carp; +use IPC::Open3; sub new { - bless {}, shift + my $class = shift; + my $conf = shift; + my $self = bless { conf => $conf }, $class; + local %_ = @_; + my $v; + if ($v = delete $_{preloaded}) { + croak "preloaded must be an arrayref" unless ref($v) eq 'ARRAY'; + @{$self->{preloaded}}{@$v} = @$v; + } + if ($v = delete $_{probe}) { + if (ref($v) eq 'ARRAY') { + $self->probe(@$v); + } else { + $self->probe; + } + } + return $self; +} + +sub conf { shift->{conf} } + +sub preloaded { + my $self = shift; + my $id = shift; + if (my $v = shift) { + $self->{preloaded}{$id} = $v; + } + return $self->{preloaded}{$id}; } sub expand { - my ($self, $tree, $d, $repl) = @_; + my ($self, $d, $repl) = @_; if ($d->type eq 'section' && lc($d->name) eq 'ifmodule') { my $id = $d->value; my $negate = $id =~ s/^!//; - my $res = $self->module_loaded($tree, $id); + my $res = $self->module_loaded($id); if ($negate) { $res = !$res; } @@ -24,10 +53,151 @@ sub expand { } sub module_loaded { - my ($self, $tree, $id) = @_; + my ($self, $id) = @_; + return 1 if $self->preloaded($id); return grep { (split /\s+/, $_->value)[0] eq $id - } $tree->directive('loadmodule'); + } $self->conf->directive('loadmodule'); +} + +# FIXME: This list is largely speculative; check Apache sources +my %modlist = ( + 'mod_authn_file.c' => 'authn_file_module', + 'mod_authn_dbm.c' => 'authn_dbm_module', + 'mod_authn_anon.c' => 'authn_anon_module', + 'mod_authn_dbd.c' => 'authn_dbd_module', + 'mod_authn_socache.c' => 'authn_socache_module', + 'mod_authn_core.c' => 'authn_core_module', + 'mod_authz_host.c' => 'authz_host_module', + 'mod_authz_groupfile.c' => 'authz_groupfile_module', + 'mod_authz_user.c' => 'authz_user_module', + 'mod_authz_dbm.c' => 'authz_dbm_module', + 'mod_authz_owner.c' => 'authz_owner_module', + 'mod_authz_dbd.c' => 'authz_dbd_module', + 'mod_authz_core.c' => 'authz_core_module', + 'mod_authnz_ldap.c' => 'authnz_ldap_module', + 'mod_access_compat.c' => 'access_compat_module', + 'mod_auth_basic.c' => 'auth_basic_module', + 'mod_auth_form.c' => 'auth_form_module', + 'mod_auth_digest.c' => 'auth_digest_module', + 'mod_allowmethods.c' => 'allowmethods_module', + 'mod_file_cache.c' => 'file_cache_module', + 'mod_cache.c' => 'cache_module', + 'mod_cache_disk.c' => 'cache_disk_module', + 'mod_socache_shmcb.c' => 'socache_shmcb_module', + 'mod_socache_dbm.c' => 'socache_dbm_module', + 'mod_socache_memcache.c' => 'socache_memcache_module', + 'mod_watchdog.c' => 'watchdog_module', + 'mod_dbd.c' => 'dbd_module', + 'mod_dumpio.c' => 'dumpio_module', + 'mod_echo.c' => 'echo_module', + 'mod_buffer.c' => 'buffer_module', + 'mod_data.c' => 'data_module', + 'mod_ratelimit.c' => 'ratelimit_module', + 'mod_reqtimeout.c' => 'reqtimeout_module', + 'mod_ext_filter.c' => 'ext_filter_module', + 'mod_request.c' => 'request_module', + 'mod_include.c' => 'include_module', + 'mod_filter.c' => 'filter_module', + 'mod_reflector.c' => 'reflector_module', + 'mod_substitute.c' => 'substitute_module', + 'mod_sed.c' => 'sed_module', + 'mod_charset_lite.c' => 'charset_lite_module', + 'mod_deflate.c' => 'deflate_module', + 'mod_xml2enc.c' => 'xml2enc_module', + 'mod_proxy_html.c' => 'proxy_html_module', + 'mod_mime.c' => 'mime_module', + 'mod_ldap.c' => 'ldap_module', + 'mod_log_config.c' => 'log_config_module', + 'mod_log_debug.c' => 'log_debug_module', + 'mod_log_forensic.c' => 'log_forensic_module', + 'mod_logio.c' => 'logio_module', + 'mod_env.c' => 'env_module', + 'mod_mime_magic.c' => 'mime_magic_module', + 'mod_expires.c' => 'expires_module', + 'mod_headers.c' => 'headers_module', + 'mod_usertrack.c' => 'usertrack_module', + 'mod_unique_id.c' => 'unique_id_module', + 'mod_setenvif.c' => 'setenvif_module', + 'mod_version.c' => 'version_module', + 'mod_remoteip.c' => 'remoteip_module', + 'mod_proxy.c' => 'proxy_module', + 'mod_proxy_connect.c' => 'proxy_connect_module', + 'mod_proxy_ftp.c' => 'proxy_ftp_module', + 'mod_proxy_http.c' => 'proxy_http_module', + 'mod_proxy_fcgi.c' => 'proxy_fcgi_module', + 'mod_proxy_scgi.c' => 'proxy_scgi_module', + 'mod_proxy_fdpass.c' => 'proxy_fdpass_module', + 'mod_proxy_ajp.c' => 'proxy_ajp_module', + 'mod_proxy_balancer.c' => 'proxy_balancer_module', + 'mod_proxy_express.c' => 'proxy_express_module', + 'mod_session.c' => 'session_module', + 'mod_session_cookie.c' => 'session_cookie_module', + 'mod_session_dbd.c' => 'session_dbd_module', + 'mod_slotmem_shm.c' => 'slotmem_shm_module', + 'mod_slotmem_plain.c' => 'slotmem_plain_module', + 'mod_ssl.c' => 'ssl_module', + 'mod_dialup.c' => 'dialup_module', + 'mod_lbmethod_byrequests.c' => 'lbmethod_byrequests_module', + 'mod_lbmethod_bytraffic.c' => 'lbmethod_bytraffic_module', + 'mod_lbmethod_bybusyness.c' => 'lbmethod_bybusyness_module', + 'mod_lbmethod_heartbeat.c' => 'lbmethod_heartbeat_module', + 'event.c' => 'mpm_event_module', + 'prefork.c' => 'mpm_prefork_module', + 'mod_unixd.c' => 'unixd_module', + 'mod_heartbeat.c' => 'heartbeat_module', + 'mod_heartmonitor.c' => 'heartmonitor_module', + 'mod_dav.c' => 'dav_module', + 'mod_status.c' => 'status_module', + 'mod_autoindex.c' => 'autoindex_module', + 'mod_asis.c' => 'asis_module', + 'mod_info.c' => 'info_module', + 'mod_cgid.c' => 'cgid_module', + 'mod_cgi.c' => 'cgi_module', + 'mod_vhost_alias.c' => 'vhost_alias_module', + 'mod_negotiation.c' => 'negotiation_module', + 'mod_dir.c' => 'dir_module', + 'mod_actions.c' => 'actions_module', + 'mod_speling.c' => 'speling_module', + 'mod_userdir.c' => 'userdir_module', + 'mod_alias.c' => 'alias_module', + 'mod_rewrite.c' => 'rewrite_module', + 'mod_dav.c' => 'dav_module', + 'mod_dav_fs.c' => 'dav_fs_module', + 'mod_dav_lock.c' => 'dav_lock_module', + 'mod_dav_svn.c' => 'dav_svn_module', + 'mod_authz_svn.c' => 'authz_svn_module', + 'mod_fcgid.c' => 'fcgid_module', + 'mod_dav_svn.c' => 'dav_svn_module', + 'mod_authz_svn.c' => 'authz_svn_module' +); + +sub probe { + my ($self, @servlist) = @_; + unless (@servlist) { + @servlist = qw(/usr/sbin/httpd /usr/sbin/apache2); + } + + open(my $nullout, '>', File::Spec->devnull); + open(my $nullin, '<', File::Spec->devnull); + foreach my $serv (@servlist) { + use Symbol 'gensym'; + my $fd = gensym; + eval { + if (my $pid = open3($nullin, $fd, $nullout, $serv, '-l')) { + while (<$fd>) { + chomp; + if (/^\s*(\S+\.c)$/ && exists($modlist{$1})) { + $self->preloaded($modlist{$1}, $1); + } + } + } + }; + close $fd; + last unless ($@) + } + close $nullin; + close $nullout; } 1; diff --git a/lib/Apache/Config/Preproc/include.pm b/lib/Apache/Config/Preproc/include.pm index 9959a59..f7e3142 100644 --- a/lib/Apache/Config/Preproc/include.pm +++ b/lib/Apache/Config/Preproc/include.pm @@ -7,18 +7,37 @@ use File::Spec; use Carp; sub new { - bless { included => {} }, shift + my $class = shift; + my $conf = shift; + my $self = bless { included => {}, conf => $conf }, $class; + local %_ = @_; + $self->{server_root} = delete $_{server_root}; + croak "unrecognized arguments" if keys(%_); + return $self; } +sub conf { shift->{conf} } + +sub server_root { + my $self = shift; + unless ($self->{server_root}) { + if (my $d = $self->conf->directive('ServerRoot')) { + $self->{server_root} = $self->conf->dequote($d->value); + } + } + return $self->{server_root}; +} + + sub expand { - my ($self, $tree, $d, $repl) = @_; + my ($self, $d, $repl) = @_; if ($d->type eq 'directive' && $d->name =~ /^include(optional)?$/i) { my $optional = $1; - my $pat = $tree->dequote($d->value); + my $pat = $self->conf->dequote($d->value); unless (File::Spec->file_name_is_absolute($pat)) { - if (my $d = $tree->server_root) { + if (my $d = $self->server_root) { $pat = File::Spec->catfile($d, $pat); } } @@ -30,7 +49,7 @@ sub expand { croak "file $file already included"; } if (my $inc = new Apache::Admin::Config($file, - @{$tree->options})) { + @{$self->conf->options})) { # NOTE: make sure each item is cloned push @$repl, map { $_->clone } $inc->select; } else { diff --git a/lib/Apache/Config/Preproc/macro.pm b/lib/Apache/Config/Preproc/macro.pm index 34bdd2b..ab97b62 100644 --- a/lib/Apache/Config/Preproc/macro.pm +++ b/lib/Apache/Config/Preproc/macro.pm @@ -2,8 +2,10 @@ package Apache::Config::Preproc::macro; use strict; use warnings; use Text::ParseWords; +use Carp; sub new { + croak "too many arguments" unless @_ == 2; bless {}, shift } @@ -18,7 +20,7 @@ sub install_macro { } sub expand { - my ($self, $tree, $d, $repl) = @_; + my ($self, $d, $repl) = @_; if ($d->type eq 'section' && lc($d->name) eq 'macro') { $self->install_macro(Apache::Config::Preproc::macro::defn->new($d)); return 1; |