diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-02-22 12:54:30 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-02-22 12:54:30 +0200 |
commit | c16f2363476167d59a2eaad38ef9e98f032ebdd1 (patch) | |
tree | 9cac41ac5cd55e76d872c9a977187484a76092f0 /lib/Apache | |
parent | 3c71a4b3c78a8b25258e858135cd239d22bd83c9 (diff) | |
download | apache-defaults-c16f2363476167d59a2eaad38ef9e98f032ebdd1.tar.gz apache-defaults-c16f2363476167d59a2eaad38ef9e98f032ebdd1.tar.bz2 |
Improve error reporting; Add documentation and test suite.
Diffstat (limited to 'lib/Apache')
-rw-r--r-- | lib/Apache/Defaults.pm | 226 |
1 files changed, 212 insertions, 14 deletions
diff --git a/lib/Apache/Defaults.pm b/lib/Apache/Defaults.pm index 13c729e..08c4865 100644 --- a/lib/Apache/Defaults.pm +++ b/lib/Apache/Defaults.pm @@ -5,6 +5,7 @@ use File::Spec; use IPC::Open3; use Shell::GetEnv; use DateTime::Format::Strptime; +use Text::ParseWords; use Symbol 'gensym'; use Carp; @@ -26,22 +27,28 @@ sub new { @servlist = qw(/usr/sbin/httpd /usr/sbin/apache2); } - if (my @select = grep { -x $_ } @servlist) { + if (my @select = grep { -x $_->[0] } + map { [ shellwords($_) ] } @servlist) { $self->{server} = shift @select; } else { croak "No suitable httpd binary found"; } if ($v = delete $_{environ}) { - $self->{environ} = Shell::GetEnv->new('sh', ". $v", startup => 0) - ->envs; - } + my $env = Shell::GetEnv->new('sh', ". $v", + { startup => 0 }); + if ($env->status) { + croak "Got status ".$env->status." trying to inherit environment"; + } + $self->{environ} = $env->envs; + } croak "unrecognized arguments" if keys(%_); return $self; } -sub server { shift->{server} } +sub server { shift->{server}[0] } +sub server_command { @{shift->{server}} } sub environ { shift->{environ} } sub probe { @@ -50,17 +57,31 @@ sub probe { open(my $nullout, '>', File::Spec->devnull); open(my $nullin, '<', File::Spec->devnull); - my $fd = gensym; + my $out = gensym; + my $err = gensym; local %ENV = %{$self->{environ}} if $self->{environ}; - if (my $pid = open3($nullin, $fd, $nullout, $self->server, @opt)) { - while (<$fd>) { + if (my $pid = open3($nullin, $out, $err, + $self->server_command, @opt)) { + while (<$out>) { chomp; last unless &{$cb}($_); } + waitpid($pid, 0); + if ($? == -1) { + croak "failed to execute " .$self->server . ": $!"; + } elsif ($? & 127) { + croak sprintf("%s died with signal %d%s", + $self->server, $? & 127, + ($? & 128) ? ' (core dumped)' : ''); + } elsif (my $code = $? >> 8) { + local $/ = undef; + croak sprintf("%s terminated with status %d; error message: %s", + $self->server, $code, <$err>); + } } - close $fd; close $nullin; - close $nullout; + close $out; + close $err; } sub dequote { @@ -84,7 +105,6 @@ sub _get_version_info { $self->{built} = DateTime::Format::Strptime->new( pattern => '%b %d %Y %H:%M%S', - strict => 1, locale => 'en_US', time_zone => 'UTC', on_error => 'undef' @@ -104,7 +124,7 @@ sub _get_version_info { $self->{MPM_forked} = $+{b} eq 'yes'; } elsif (/^\s+-D\s+(?<name>.+?)=(?<val>.+)$/) { $self->{defines}{$+{name}} = $self->dequote($+{val}); - } elsif (/^\s+-D\s+(?<name>.+?)(?:\s*(?<com>.+))?$/) { + } elsif (/^\s+-D\s+(?<name>\S+)(?:\s*(?<com>.+))?$/) { $self->{defines}{$+{name}} = 1; } return 1; @@ -139,7 +159,10 @@ sub server_root { shift->defines('HTTPD_ROOT') } sub defines { my $self = shift; $self->_get_version_info; - return @{$self->{defines}}{@_}; + if (@_) { + return @{$self->{defines}}{@_}; + } + return sort keys %{$self->{defines}}; } # List of module sources and corresponding identifiers, obtained from the @@ -271,7 +294,7 @@ sub preloaded { if (@_) { return @{$self->{preloaded}}{@_}; } - return keys %{$self->{preloaded}}; + return sort keys %{$self->{preloaded}}; } sub _get_module_info { @@ -290,3 +313,178 @@ sub _get_module_info { } 1; +__END__ +=head1 NAME + +Apache::Defaults - Get default settings for Apache httpd daemon + +=head1 SYNOPSIS + + $x = new Apache::Defaults; + print $x->name; + print $x->version; + print $x->server_root; + print $x->built; + print $x->architecture; + print $x->MPM; + print $x->defines('DYNAMIC_MODULE_LIMIT'); + print $x->preloaded('cgi_module'); + +=head1 DESCRIPTION + +Detects the default settings of the Apache httpd daemon by invoking +it with appropriate options and analyzing its output. + +=head1 METHODS + +=head2 new + + $x = new Apache::Defaults(%attrs); + +Detects the settings of the apache server and returns the object representing +them. Attributes (I<%attrs>) are: + +=over 4 + +=item C<server> + +Full pathname of the B<httpd> binary to inspect. The argument can also be +a reference to the list of possible pathnames. In this case, the first of +them that exists on disk and has executable privileges will be used. Full +command line can also be used, e.g.: + + server => '/usr/sbin/httpd -d /etc/httpd' + +The default used in the absense of this attribute is: + + [ '/usr/sbin/httpd', '/usr/sbin/apache2' ] + +=item C<environ> + +Name of the shell script that sets the environment for B<httpd> invocation. +For some obscure reason, B<httpd> attempts to read its configuration file +even if invoked with the B<-V> option (which is intended to print the version +and build parameters of the daemon). It will fail if its configuration refers +to the environment variables, defined elsewhere. This situation is quite +common in Debian-based distributions, which define the environment variables +in file F</etc/apache2/envvars>. This attribute is intended to cope with +such problems, e.g.: + + $x = new Apache::Defaults(environ => /etc/apache2/envvars) + +=back + +The method will I<croak> if an error occurs (e.g. the server binary +is not found or exits with failure). + +=head2 server + + $s = $x->server; + +Returns the pathname of the B<httpd> binary. + +=head2 server_command + + @cmd = $x->server_command; + +Returns full command line of the B<httpd> binary. + +=head2 environ + + $hashref = $x->environ + +Returns a reference to the environment used when invoking the server. + +=head2 name + + $s = $x->name; + +Returns server implementation name (normally C<Apache>). + +=head2 version + + $v = $x->version; + +Returns server version (as string). + +=head2 platform + + $s = $x->platform; + +Platform (distribution) on which the binary is compiled. + +=head2 architecture + +Architecture for which the server is built. + +=head2 built + + $d = $x->built; + +Returns a B<DateTime> object, representing the time when the server +was built. + +=head2 loaded_with + +APR tools with which the server is loaded. + +=head2 compiled_with + +APR tools with which the server is compiled. + +=head2 MPM + +MPM module loaded in the configuration. + +=head2 MPM_threaded + +True if the MPM is threaded. + +=head2 MPM_forked + +True if the MPM is forked. + +=head2 defines + + @names = $x->defines; + +Returns the list of symbolic names defined during the compilation. The +names are in lexical order. + + @values = $x->defines(@names); + +Returns values of the named defines. + +=head2 server_root + + $s = $x->server_root; + +Returns default server root directory. This is equivalent to + + $x->defines('HTTPD_ROOT'); + +=head2 preloaded + + @ids = $x->preloaded; + +Returns the list of the preloaded module identifiers, in lexical order. + + @sources = $x->preloaded(@ids); + +Returns the list of module source names for the given source identifiers. +For non-existing identifiers, B<undef> is returned. + +=head1 LICENSE + +GPLv3+: GNU GPL version 3 or later, see +L<http://gnu.org/licenses/gpl.html>. + +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. + +=head1 AUTHORS + +Sergey Poznyakoff <gray@gnu.org> + +=cut + |