# $Id: install,v 1.23 2005/08/13 22:41:38 kiesling Exp $

###
### TO DO
### 1. Add check for server run from inetd (ServerType directive). ### 2. Test for valid non-numeric user and group id's. ### 3. Make sure that the script can find htpasswd, etc. ### 4. Make sure that group ownership is set correctly if $group_ok. ###

use IO::Handle;
use warnings;

my ($l, $ans, $label, $s);

my $handle = new IO::Handle;
if (! $handle -> fdopen (fileno(STDIN), "r")) {

print "install: couldn't read standard input: $!\n"; exit 1;
}

print <<EOI;

OnSearch installation. If this program can't determine the site configuration, read INSTALL.html.

NOTE: If you've already installed OnSearch, make a backup copy. Press [Ctrl-C] to exit now if necessary.

EOI

my $httpd = find_httpd ();
my $httpd_version = get_httpd_version (); my $httpd_conf = find_httpd_conf ();

my $Port = get_port ();

chomp $httpd_conf;
print "Configuring for $httpd and $httpd_conf.\n\n";

###
### Values from http.conf. Also check for mod_ssi and mod_perl. ###

my ($cgi_ok, $serverparsed_ok, $mod_auth_ok, $group_ok); $cgi_ok = $serverparsed_ok = $mod_auth_ok = $group_ok = 0; my $add_handlers_ok = 0;
my $ServerName = '';
my $DocumentRoot = '';
my $ServerRoot = '';
my $User = '';
my $Group = '';

open HTTPD_CONF, "$httpd_conf" or die "$httpd_conf: $!\n"; while (defined ($l =<HTTPD_CONF>)) {

if ($l =~ /^\sServerName/) {

        ($label, $ServerName) = split /\s/, $l;
        $ServerName =~ s/\"//g;

}
if ($l =~ /^DocumentRoot/) {

        ($label, $DocumentRoot) = split /\s/, $l;
        $DocumentRoot =~ s/\"//g;

}
if ($l =~ /^ServerRoot/) {

        ($label, $ServerRoot) = split /\s/, $l;
        $ServerRoot =~ s/\"//g;

}
if ($l =~ /^\s
User\s+/) { ($label, $User) = split /\s/, $l; } if ($l =~ /^Group/) {

        ($label, $Group) = split /\s/, $l; 
        $group_ok = 1 if $Group =~ /^\d+$/; 

}
if ($l =~ /^Port\s/) { ($Port) = ($l =~ /\w+\s+(\d+)/); } $cgi_ok = 1 if $l =~ m/^\sAddHandler\s?cgi-script/

&& check_module ('mod_cgi', 'cgi_module'); if ($httpd_version =~ /^1\.3/) {

        $serverparsed_ok = 1 if ($l =~ /^\sAddHandler\s?server-parsed/
           && check_module ('mod_include', 'includes_module'));
    } elsif ($httpd_version =~ /^2\./) {
        $serverparsed_ok = 1 if ($l =~ /^\s*AddOutputFilter INCLUDES \.shtml/
           && check_module ('mod_include', 'includes_module'));

}
$mod_auth_ok = 1 if check_module ('mod_auth', 'auth_module'); }
close HTTPD_CONF;

note_missing_confs ();

##
## Values from onsearch.cfg.
##
my @conf;
my $WebLogDir = '';
my $DataDir = '';

open CONF, "onsearch.cfg" or die "onsearch.cfg: $!\n"; while (defined ($l = <CONF>)) {

push @conf, ($l);
}
close CONF;

($s) = grep /^WebLogDir/, @conf;
($label, $WebLogDir) = split /\s+/, $s;

($s) = grep /^DataDir/, @conf;
($label, $DataDir) = split /\s+/, $s;

print <<EOT;
The following values were found:
The Web site's name is $ServerName.
The Web site's document directory is $DocumentRoot. The Web server's version is $httpd_version. The Web server's directory is $ServerRoot. The Web server's process owner is $User. The Web server's port is $Port.
EOT

###
### Create subdirectories.
###

my ($subdir) = grep /^OnSearchDir/, @conf; chomp $subdir;
$subdir =~ s/^OnSearchDir\W?(.*)/$1/;
my $onsearchdir = "$DocumentRoot/$subdir"; my $onsearchbindir = $onsearchdatadir = ''; print <<DIROK;

I'm going to install OnSearch in $onsearchdir. Is this okay (y/n)? DIROK
$ans = getkey ();
if ($ans !~ /y/i) {
print <<DIRNOTOK;

If you want to install OnSearch in a different directory, edit the value of "OnSearchDir" in onsearch.cfg and then restart the installation. Exiting

DIRNOTOK
exit 1;
}

print "Creating OnSearch's program and data directories.\n"; mkdirtree ($WebLogDir, 0755);
mkdirtree ($DataDir, 0755);
mkdirtree ($onsearchdir, 0755);
mkdirtree ("$onsearchdir/admin", 0755); mkdirtree ("$onsearchdir/doc", 0755);
mkdirtree ("$onsearchdir/images", 0755); mkdirtree ("$onsearchdir/cache", 0755); mkdirtree ("$onsearchdir/plugins", 0755); mkdirtree ("$onsearchdir/webpages", 0755); mkdirtree ("$onsearchdir/uploads", 0755);

###
### Copy the files.
###
print "Installing program files.\n";
`cp -R html/ $onsearchdir >/dev/null 2>&1`; `cp images/ "$onsearchdir/images" >/dev/null 2>&1`; `cp -R cgi/ $onsearchdir >/dev/null 2>&1`; `cp doc/ "$onsearchdir/doc" >/dev/null 2>&1`; `cp plugins/* "$onsearchdir/plugins" >/dev/null 2>&1`;

###
### Install Perl libraries.
###

print "Installing Perl libraries.\n";
`cd lib && (perl Makefile.PL LIB="$onsearchdir/lib" && make install && make clean)`; `chown -R $User "$onsearchdir/lib"`;
`chgrp $Group "$onsearchdir/lib"` if $group_ok;

###
### Install OnSearchIO under PerlIO
###
`cd lib/OnSearch/OnSearchIO && (perl Makefile.PL && make install && make clean)`;

###
### Set permissions.
###

print "Setting permissions.\n";

`chown -R $User $onsearchdir`;
`chgrp -R $Group $onsearchdir` if $group_ok; `chown $User $WebLogDir`;
`chgrp $Group $WebLogDir` if $group_ok; `chmod 0775 $WebLogDir`;
`chmod 0755 $onsearchdir`;
`chown $User $DataDir`;
`chgrp $Group $DataDir` if $group_ok;
`chmod 0700 $DataDir`;

foreach (qw/ alert.cgi error.cgi main.cgi search.cgi archive.cgi

        results.cgi filters.cgi index.cgi/) {
        `chmod 0755 "$onsearchdir/$_"`;

}
foreach (qw/adminform.cgi/) {

`chmod 0755 "$onsearchdir/admin/$_"`; }

foreach (qw/jpeg null ongzip pdf postscript text html/) {

`chmod +x "$onsearchdir/plugins/$_"`; }

###
### Find top-level document directories. ###

my @tldirs;
push @tldirs, ($DocumentRoot);

print <<TDS1;

OnSearch will use $DocumentRoot as its top-level document directory. Is this okay (y/n)?
TDS1
$ans = getkey ();
if ($ans !~ /y/i) {

tlds
$#tldirs = -1;

print <<TDS2;

You need to enter the top-level directories, one per line. After entering the directory names, hit <Enter> on a blank line.

TDS2

     while (1) {
         $ans = getkey ();
         last if (! length ($ans));
         push @tldirs, ($ans);
     }

print <<TDS3;

You entered:

TDS3
foreach (@tldirs) {print "$_\n" if length ($_); }

print <<TDS4;

Is this okay (y/n)?
TDS4

$ans = getkey ();
if ($ans !~ /y/i) {

print "Okay, trying again.\n";
goto tlds;
}

}

###
### Edit onsearch.cfg
###
print "Updating OnSearch's configuration.\n"; open NEWCONFIG, ">$onsearchdir/onsearch.cfg" or die "onsearch.cfg: $!\n";

foreach my $o (@conf) {

      if ($o =~ /^BinDir/) {
         ($label, $onsearchbindir) = split /\s+/, $o;
         chomp $onsearchbindir;
      }
        
      if ($o =~ /^DataDir/) {
         ($label, $onsearchdatadir) = split /\s+/, $o;
         chomp $onsearchdatadir;
      }

      if ($o =~ /^ServerName/) {
        chomp $ServerName;
        print NEWCONFIG "ServerName $ServerName\n";
        next;
      } 
      if ($o =~ /^SearchRoot/) { 
         foreach my $t (@tldirs) {
            chomp $t;
            print NEWCONFIG "SearchRoot $t\n" if length ($t);
         }
         next;
      }
      if ($o =~ /^ExcludeDir/) { 
          print NEWCONFIG "ExcludeDir $onsearchdir/cache\n";
          print NEWCONFIG "ExcludeDir $onsearchdir/lib\n";
          next;
      }
      if ($o =~ /^User/) {
          chomp $User;
          print NEWCONFIG "User $User\n";
          next;
      }
      print NEWCONFIG $o;

}

close NEWCONFIG;
`chown $User "$onsearchdir/onsearch.cfg"`; `chgrp $Group "$onsearchdir/onsearch.cfg"` if $group_ok;

###
### Find perl, modules, and version.
###

my ($perl_bin);

chomp ($perl_bin = `which perl`);
if (!length ($perl_bin)) {
print <<PB;

I can't locate the Perl interpreter. Make sure that it is installed in your search path and is named "perl."

PB
exit 1;
}
print "Perl is $perl_bin\n";
if ($^V lt v5.6.0) {
print <<PV;
OnSearch was written using Perl version 5.6.0. You should consider upgrading, especially if the Perl version is earlier than 5.4. PV
}

###
### Find gcc and version.
###

my ($gcc_bin, $gcc_version);
chomp ($gcc_bin = `which gcc`);
if (!length ($gcc_bin)) {
print <<GB;
I can't locate GCC. Make sure that it is installed in your search path and is named "gcc."
GB
exit 1;
}
print "GCC is $gcc_bin\n";
chomp ($gcc_version = `gcc --version`); if ($gcc_version lt '2.7.2') {
print <<GV;
OnSearch was written using GCC version 2.95.4. You should consider upgrading, especially if the compiler version is earlier than 2.7.2. GV
}
print "GCC version is $gcc_version.\n";

open MAKETMPL, "src/Makefile.tmpl" or die "src/Makefile.tmpl: $!\n"; open MAKE, ">src/Makefile" or die "src/Makefile: $!\n";

while (defined ($l = <MAKETMPL>)) {

if ($l =~ /\@bindir\@/) {

$l =~ s"\@bindir\@"$onsearchbindir"; }
if ($l =~ /\@datadir\@/) {

$l =~ s"\@datadir\@"$onsearchdatadir"; }
if ($l =~ /\@onsearchdir\@/) {

$l =~ s"\@onsearchdir\@"$onsearchdir"; }
print MAKE $l;
}

close MAKE;
close MAKETMPL;

`rm -f /tmp/.onsearch.sock*`;

print "Building the indexing daemon.\n"; `cd src && make install >/tmp/onsearch.bld 2>&1`;

if (! -f 'src/onindex') {

print <<MAKEERR;

There was an error building the onsearch index program. The output of "make" is:

MAKEERR

open ERR, "/tmp/onsearch.bld" or die "/tmp/onsearch.bld: $!\n"; undef $/;
print <ERR>;
close ERR;
unlink '/tmp/onsearch.bld';
print "\nCleaning up....\n";
`sh -c "rm -rf $onsearchdir /usr/local/etc/init.d/onindex"`; exit 1;
} else {

unlink '/tmp/onsearch.bld';
`cd src && make clean`;
}

print "Installing man pages.\n";

open MAKETMPL, "doc/Makefile.tmpl" or die "src/Makefile.tmpl: $!\n"; open MAKE, ">doc/Makefile" or die "src/Makefile: $!\n";

while (defined ($l = <MAKETMPL>)) {

if ($l =~ /\@bindir\@/) {

$l =~ s"\@bindir\@"$onsearchbindir"; }
if ($l =~ /\@datadir\@/) {

$l =~ s"\@datadir\@"$onsearchdatadir"; }
if ($l =~ /\@onsearchdir\@/) {

$l =~ s"\@onsearchdir\@"$onsearchdir"; }
if ($l =~ /\@weblogdir\@/) {

$l =~ s"\@weblogdir\@"$WebLogDir"; }
print MAKE $l;
}

close MAKE;
close MAKETMPL;
# Don't need to cd back because these run in a subshell. `cd doc && (make all >/dev/null 2>&1)`; `cd doc && make clean >/dev/null 2>&1`;

###
### OnSearch Directory Wrapper
###
print <<EOT;
I'm going to add OnSearch's configuration to $httpd_conf. I'll copy the original httpd.conf file to httpd.conf.onsearch-save.

You can skip this step, and then configure the Web server manually, using the template in doc/conf.tmpl. Should I continue (y/n)?
EOT
$ans = getkey ();
if ($ans !~ /y/i) {

print "Okay, skipping.\n";
goto auth;
}

`cp "$httpd_conf" "$httpd_conf.onsearch-save"`; my $t1 = dir_wrapper_template ($onsearchdir); `echo "$t1" >>"$httpd_conf"`;

###
### Authentication
###
auth:
print <<EOT;

I'm going to add password authentication information to your Web server configuration and then try to restart the server.

With authentication enabled, users must enter a user name and password to perform administrative tasks. For passwords to work the Web server must include mod_auth in its configuration.

During the process, the installation will copy your old $httpd_conf to $httpd_conf.onsearch-save, so you can restore your previous configuration if necessary.

You can skip this step, but then you will not have password protection for administrative tasks.

Should I continue (y/n)?
EOT
$ans = getkey ();
if ($ans !~ /y/i) {

print "Okay, skipping.\n";
goto done;
}

my ($apachectl_prog, $htpasswd_prog);

$apachectl_prog = "$ServerRoot/bin/apachectl"; if (! -x $apachectl_prog) {

$apachectl_prog = `which apachectl`; chomp $apachectl_prog;
if (! -x $apachectl_prog) {
print <<EOT;

I can't find the apachectl utility. Try to determine that it is in either $ServerRoot/bin or in a directory named in the operating system's search path.

EOT

goto done;
}
}

$htpasswd_prog = "$ServerRoot/bin/htpasswd"; if (! -x $htpasswd_prog) {

$htpasswd_prog = `which htpasswd`;
chomp $htpasswd_prog;
if (! -x $htpasswd_prog) {
print <<EOT;

I can't find the htpasswd utility. Try to determine that it is in either $ServerRoot/bin or in a directory named in the operating system's search path.

EOT

goto done;
}
}

print <<EOT;
Saving the Web server's configuration.
EOT
`cp "$httpd_conf" "$httpd_conf.onsearch-save"`

if (! -f "$httpd_conf.onsearch-save");

print <<EOT;
Adding authentication information to $httpd_conf. EOT

my $p1 = auth_template ($onsearchdir);
`echo "$p1" >>"$httpd_conf"`;

print <<EOT;
Creating the OnSearch group file.
EOT
$p1 = group_template ();
`echo "$p1" >/usr/local/etc/ongroup`;

print <<EOT;
Creating the OnSearch password file.

NOTE: INSTALL.html tells you how to log in for the first time. EOT
`$htpasswd_prog -nb onsearch onsearch >/usr/local/etc/onpasswd`;

print <<EOT;

Now restarting the Web server...

EOT
`$apachectl_prog restart`;

done

my ($starturl, $docurl);
if ($Port eq '80') {

        $starturl = "http://$ServerName/$subdir/index.shtml";
        $docurl = "http://$ServerName/$subdir/doc/userguide.html#admin"
} else {
        $starturl = "http://$ServerName:$Port/$subdir/index.shtml";
        $docurl = "http://$ServerName:$Port/$subdir/doc/userguide.html#admin"

}
print <<EOT;

Done. If the installation was correct, you should be able to browse to

$starturl

The OnSearch User Guide's administration chapter,

$docurl

and the onindex(8) manual page, describe how to index files and start using OnSearch.

EOT

$handle -> close;

exit 0;

##
## Create directories
##

sub mkdir_wrap {

my $d =$_[0];
my $a;
if (($a = `mkdir -p $d 2>&1`) =~ /cannot create directory/i) {

        print STDERR "$a\n";
        return -1;

}
return 0;
}

##
## Keyboard input.
##

sub getkey {

my $key;
$key = $handle -> getline;
chomp $key;
return $key;
}

###
### Make subdirs
###

sub mkdirtree {

my ($dir, $mask) = @_;
my ($parent) =

($dir =~ /(.)\/.$/);
if (! -d $parent) {

mkdirtree ($parent, $mask);
}
if (! -d $dir) {

        print "$dir.\n";
        mkdir ($dir, $mask) or die "Could not make directory $dir: $!\n";

}
}

##
## Missing Conf Variable
##

sub missing_conf {

my $c = $_[0];

print <<EOT;

I can't locate the "$c" directive.
EOT
}

sub dir_wrapper_template {

my ($progdir) = @_;
my $f = qq|
# Added by OnSearch installation.

<Directory $progdir>

Options ExecCGI Includes
AddHandler cgi-script .cgi
AddType text/html .shtml
AddHandler server-parsed .shtml
</Directory>
|;
return $f
}

sub auth_template {

my ($progdir) = @_;
my $f = qq|
# Added by OnSearch installation.

<Directory $progdir/admin>

AuthType Basic
AuthName OnSearch
AuthUserFile /usr/local/etc/onpasswd AuthGroupFile /usr/local/etc/ongroup require group onsearch
</Directory>
|;
return $f
}

sub group_template {
my $f = qq|onsearch: onsearch|;
return $f;
}

###
### First check the httpd settings.
### Then check normal locations.
### Then search.
### Then warn user.
###

sub find_httpd_conf {

my @HTTP_CONF_PATHS = qw(/etc/apache/httpd.conf

                             /usr/local/apache/conf/httpd.conf
                             /usr/local/apache2/conf/httpd.conf);

my @conffiles = ();
my @httpdroots = ();
my ($httpdroot, $conffile, $ans, $i, $altconf);

###
### First check the server's configuration. ###

my @conflines = grep /httpd.conf/, split /\n/, `$httpd -V`; ($conffile) = ($conflines[0] =~ /SERVER_CONFIG_FILE=\"(.*?)\"/);

@httpdroots = grep /HTTPD_ROOT/, split /\n/, `$httpd -V`; ($httpdroot) = ($httpdroots[0] =~ /HTTPD_ROOT=\"(.*?)\"/);

if (-f $conffile) {

print <<EOT;
The Web server's configuration file is $conffile. Is this correct (y/n)? EOT

        $ans = getkey ();
        if ($ans =~ /y/i) {
            return $conffile;
        }

}

if (-f "$httpdroot/$conffile") {

print <<EOT;
The Web server's configuration file is $httpdroot/$conffile. Is this correct (y/n)?
EOT

        $ans = getkey ();
        if ($ans =~ /y/i) {
            return "$httpdroot/$conffile";
        }

}

###
### Next, scan standard directories. ###

foreach my $f (@HTTP_CONF_PATHS) {

        if (-f $f) {
            push @conffiles, ($f);
        }

}

###
### Found one standard httpd.conf file. ##
if ($
conffiles == 0) {

        $conffile = $conffiles[0];
        print <<EOT;

The Web server's configuration file is $conffile. Is this correct (y/n)? EOT

        $ans = getkey ();
        if ($ans =~ /y/i) {
            return $conffiles[0];
        } else {
            goto HTTPD_CONF_SEARCH;
        }

###
### Found multiple standard httpd.conf files. ##
} elsif ($
conffiles > 0) {

print <<EOT;
You have several configuration files.
EOT

        $i = 1;
        print $i++ . ". $\n" foreach (@conffiles);
        print "$i. Search for other httpd.conf files.\n";
        print <<EOT;

Which should I use?
EOT

        $ans = getkey ();
        chomp $ans;
        if (($ans - 1) <= $#conffiles) {
            $conffile = $conffiles[$ans-1];
            return $conffile;
        } else {
            goto HTTPDCONF_SEARCH;
        }

}

HTTPD CONF SEARCH
print <<EOT;

Searching for Web server configuration files in non-standard directories. This may take several minutes.

EOT

@conffiles = split /\n/, `find / -name "httpd.conf"`;

if ($#conffiles >= 0) {

print <<EOT;
The system has the following httpd.conf files: EOT

        $i = 1;
        print $i++ . ". $_\n" foreach (@conffiles);
        print <<EOT;

Which should I use?
EOT

        $ans = getkey ();
        chomp $ans;
    } else {
        print <<EOT;

Whoa, dude! OnSearch requires Apache, and it doesn't seem to be installed here. You can download Apache from http://www.apache.org/.

If you are certain, absolutely CERTAIN, that Apache is installed and operating correctly on this system, read the fine INSTALL.html manual installation instructions and install OnSearch manually.

Bye....
EOT

exit 1;

}

}

sub note_missing_confs {

return if ($ServerName && $ServerRoot && $DocumentRoot &&

               $User && $Group && $cgi_ok && 
               $serverparsed_ok && $mod_auth_ok);

missing_conf ('ServerName') unless $ServerName; missing_conf ('ServerRoot') unless $ServerRoot; missing_conf ('DocumentRoot') unless $DocumentRoot; missing_conf ('User') unless $User; missing_conf ('Group') unless $Group; missing_conf ('AddHandler cgi-script') unless $cgi_ok; missing_conf ('AddHandler server-parsed') unless $serverparsed_ok; missing_conf ('LoadModule auth_module') unless $mod_auth_ok;

print <<EOT;

You need to determine that these values are set correctly.

If this program still can't determine your Web site's configuration, INSTALL.html, "doc/conf.tmpl," and "doc/auth.tmpl" contain example handlers.

EOT
}

###
### First check ps output for running httpd. (Make sure the ps ### entry lists the httpd path.)
### Then search binary directories.
### Then if httpd hasn't been found, ask user. ### Note: Some vendors install httpd as "apache," so check that ### name also.
###
sub find_httpd {

my @bindirs = qw|/usr/sbin /usr/local/sbin /usr/local/apache/bin

/usr/local/apache2/bin|;
my ($ps_prog, $httpd_prog);
my (@httpdprocs, @psfields, @dups) ;

open PS, "ps -ax 2>&1|" or die "ps: $!."; @httpd_procs = grep /httpd|apache/, <PS>; close PS;

PROC: foreach my $h (@httpd_procs) {

        chomp $h;
        @psfields = split /\s+/, $h;
        foreach my $p (@psfields) {
            if (-x $p) {
                next PROC if scalar grep /$p/, @dups;
                $ps_prog = $p;
                push @dups, ($ps_prog);
            }
        }

        if ($ps_prog) {
            print "The Web server is $ps_prog.  Is this correct (y/n)?\n";
            $ans = getkey ();
            if ($ans =~ /y/i) {
                $httpd_prog = $ps_prog;
                last PROC;
            } else {
                next PROC;
            }
        }

}
return $httpd_prog if $httpd_prog;

###
### Next, search bin directories.
###

foreach my $bindir (@bindirs) {

        next if scalar grep m"$bindir\/(apache|httpd)", @dups;
        if (-x "$bindir/apache") {
            $httpd_prog = "$bindir/apache";
        } elsif (-x "$bindir/httpd") {
            $httpd_prog = "$bindir/httpd" if -x "$bindir/httpd";
        } else {
            undef $httpd_prog;
        }

        if ($httpd_prog) {
            print "The Web server is $httpd_prog.  Is this correct (y/n)?\n";
            $ans = getkey ();
            if ($ans =~ /y/i) {
                return $httpd_prog;
            } else {
                next;
            }
        }

}

print <<EOT;
Whoa, dude! I can't find your Web in anything like a normal directory. Is Apache installed somewhere else? If so, type in its path name. EOT

$httpd_prog = getkey ();
chomp $httpd_prog;
return $httpd_prog;
}

sub get_httpd_version {

my ($version) = (`$httpd -v` =~ m'Apache/(.*?)\s+'sm); return $version;
}

sub check_module {

my ($module_name, $module_label) = @_;

my $l;
my $mod_ok = 0;
my @compiled_in = grep /$module_name/, split /\n/, `$httpd -l`; return 1 if $compiled_in[0] && $compiled_in[0] =~ /$module_name/;

open CONF, "$httpd_conf" or die "$httpd_conf: $!\n"; while (defined ($l = <CONF>)) {

if ($l =~ m"^\s*LoadModule\s?$module_label") { $mod_ok = 1; last; } }
close CONF;
return $mod_ok;
}

sub get_port {

my ($l, @lines, $pline, $label, $ipaddr, $port);

open CONF, $httpd_conf || die "Can't open $httpd_conf: $!.";

while (defined ($l = <CONF>)) {

        chomp $l;
        push @lines, ($l);

}
close CONF;

###
### Check for a Port directive.
###
if (scalar grep /^\sPort/, @lines) {

        ($pline) = grep /^\sPort/, @lines;
        if (length ($pline)) {
            ($label, $port) = split /\s+/, $pline;
            return $port;
        }

}

###
### Check for a Listen directive, which could also have an ### IP address.
###
if (scalar grep /^\sListen/, @lines) {

        ($pline) = grep /^\sListen/, @lines;
        if (length ($pline)) {
            if ($pline =~ m/\:/) {
                ($label, $ipaddr, $port) = 
                    ($pline =~ /^\s*(\w+)\s+(\S+):(\d+)/);
            } else {
                ($label, $port) = split /\s+/, $pline;
            }
            return $port;
        }

}

###
### If not there, check the ServerName directive for a ### Port number.
###
if (scalar grep /^\sServerName/, @lines) {

        ($pline) = grep /^\sServerName/, @lines;
        if (length ($pline)) {
            if ($pline =~ m/\:/) {
                ($label, $ipaddr, $port) = 
                    ($pline =~ /^\s*(\w+)\s+(\S+):(\d+)/);
            } else {
                ($label, $port) = split /\s+/, $pline;
            }
            return $port;
        }

}

print <<EOT;
I can't determine the Web server's network port. I'll assume that the port number is 80. Is that okay (y/n) EOT

$ans = getkey ();
if ($ans =~ /y/i) {

        $port = 80;
        return $port;

} else {
print <<EOT;
You might want to determine that the port number is specified correctly in http.conf before proceeding. Exiting.... EOT

exit 1;
}
}