1# $OpenBSD: Httpd.pm,v 1.1 2015/07/16 16:35:57 reyk Exp $ 2 3# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org> 4# Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18use strict; 19use warnings; 20 21package Httpd; 22use parent 'Proc'; 23use Carp; 24use File::Basename; 25 26sub new { 27 my $class = shift; 28 my %args = @_; 29 $args{chroot} ||= "."; 30 $args{logfile} ||= $args{chroot}."/httpd.log"; 31 $args{up} ||= $args{dryrun} || "server_launch: "; 32 $args{down} ||= $args{dryrun} ? "httpd.conf:" : "parent terminating"; 33 $args{func} = sub { Carp::confess "$class func may not be called" }; 34 $args{conffile} ||= "httpd.conf"; 35 my $self = Proc::new($class, %args); 36 ref($self->{http}) eq 'ARRAY' 37 or $self->{http} = [ split("\n", $self->{http} || "") ]; 38 $self->{listenaddr} 39 or croak "$class listen addr not given"; 40 $self->{listenport} 41 or croak "$class listen port not given"; 42 43 my $test = basename($self->{testfile} || ""); 44 # tls does not allow a too long session id, so truncate it 45 substr($test, 25, length($test) - 25, "") if length($test) > 25; 46 open(my $fh, '>', $self->{conffile}) 47 or die ref($self), " conf file $self->{conffile} create failed: $!"; 48 49 # substitute variables in config file 50 my $curdir = dirname($0) || "."; 51 my $connectport = $self->{connectport}; 52 my $connectaddr = $self->{connectaddr}; 53 my $listenaddr = $self->{listenaddr}; 54 my $listenport = $self->{listenport}; 55 56 print $fh "prefork 1\n"; # only crashes of first child are observed 57 print $fh "chroot \"".$args{chroot}."\"\n"; 58 print $fh "logdir \"".$args{chroot}."\"\n"; 59 60 my @http = @{$self->{http}}; 61 print $fh "server \"www.$test.local\" {"; 62 my $tls = $self->{listentls} ? "tls " : ""; 63 print $fh "\n\tlisten on $self->{listenaddr} ". 64 "${tls}port $self->{listenport}" unless grep { /^listen / } @http; 65 # substitute variables in config file 66 foreach (@http) { 67 s/(\$[a-z]+)/$1/eeg; 68 } 69 print $fh map { "\n\t$_" } @http; 70 if ($self->{listentls}) { 71 print $fh "\n"; 72 print $fh "\ttls certificate \"".$args{chroot}."/server.crt\"\n"; 73 print $fh "\ttls key \"".$args{chroot}."/server.key\""; 74 } 75 print $fh "\n\troot \"/\""; 76 print $fh "\n\tlog style combined"; 77 print $fh "\n}\n"; 78 79 return $self; 80} 81 82sub child { 83 my $self = shift; 84 my @sudo = $ENV{SUDO} ? $ENV{SUDO} : (); 85 my @ktrace = $ENV{KTRACE} ? ($ENV{KTRACE}, "-i") : (); 86 my $httpd = $ENV{HTTPD} ? $ENV{HTTPD} : "httpd"; 87 my @cmd = (@sudo, @ktrace, $httpd, "-dvv", "-f", $self->{conffile}); 88 print STDERR "execute: @cmd\n"; 89 exec @cmd; 90 die ref($self), " exec '@cmd' failed: $!"; 91} 92 931; 94