#!/usr/local/bin/perl
#################################################################
#
# + FtpLocate - FTP search engine
#
# by Distributed System Lab E.E. NCKU Taiwan 2003
# http://turtle.ee.ncku.edu.tw/ftplocate/
#
#################################################################

use IO::Socket;

############################# subs ##############################

sub touch {
  foreach (@_) { 
    open(T, ">>$_"); close(T); 
  }
  chmod(0644, @_);
}


sub readfile {
  my $fname=$_[0];
  my @f;

  open(F, "$fname") || die "Open $fname for read error\n";
  @f=<F>;
  close(F);
  return(@f);
}

sub writefile {
  my ($fname,@f)=@_;

  open(F, ">$fname") || die "Open file $fname for write error\n";
  foreach (@f) { print F $_; }
  close(F);
  chmod(0644, $fname);
  return($fname);
}

sub do_config {
  my @f=@_;

  foreach (@f) {
    if ( /%/ ) {

      s!%FTPLOCATEHTMLDIR%!/$fldir!g;
      s!%FTPLOCATECGIDIR%!/cgi-bin/$fldir!g;

      s!%FTPLOCATEDIR%!$cgidir/$fldir!g;
      s!%LANG%!$lang!g;
      s!%TMPDIR%!$tmpdir!g;

      s!%HOSTNAME%!$fqdn!;
    }
  }
  return(@f);
}

sub uidgid {
  my $user=$_[0];
  my ($name, $pass, $uid, $gid);

  open(P, "/etc/passwd");
  while (<P>) {
    ($name, $pass, $uid, $gid)=split(/:/);
    if ( $user eq $name ) { return($uid, $gid); }
  }
  close(P);
  return(-1, -1);
}

sub mbfree {
  my $dir=$_[0];
  my ($fs, $total, $used, $free, $freepercent, $mp);

  open(DF, "df -k /tmp|");
  $_=<DF>; $_=<DF>; chop;
  close(DF);
  ($fs, $total, $used, $free, $freepercent, $mp)=split(/\s+/);
  return ($free/1024);
}

sub ask {
  my ($prompt, $default)=@_;
  my $ans;

  if ( $always_yes==1 ) { return $default; }

  print $prompt;
  $ans=<STDIN>; chop($ans);
  if ($ans eq "" ) {
    return $default;
  } else {
    return $ans;
  }
}

sub dirname {
  my $i;
  $i=rindex($_[0],'/');
  if ( $i > 0 ) {
    return substr($_[0], 0, $i);
  } else {
    return ".";
  }
}

use Sys::Hostname;
sub default_domain {
  my ($hostname, $fqdn);

  open (R, "/etc/resolv.conf");		# from resolv.conf
  while (<R>) {
    if ( /domain\s+\.?(.*)\s?/i ) { close(R); return($1); }
  }
  close(R);

  $hostname=hostname();			# from hostname
  if ($hostname =~ /\./ ) {
    return( substr($hostname,index($hostname,'.')+1) );
  }

  open (R, "/etc/hosts");		# from hosts
  while (<R>) {
    if ( /$hostname\./i ) {
      foreach ( split(/\s+/) ) {
        if ( /$hostname\./i && (length($_)>length($fqdn)) ) { $fqdn=$_; }
      }
      close(R);
      return( substr($fqdn,index($fqdn,'.')+1) );
    }
  }
  close(R);
  return("");
}


sub my_fqdn {
  my ($hostname, $domain);

  $hostname=hostname();
  if ( $hostname =~ /\./ ) {
    return $hostname;
  } else {
    return $hostname.'.'.default_domain();
  }
}

######################## global variable ########################

$DOCDIR=dirname($0)."/doc";
$BINDIR=dirname($0)."/bin";
$TEMPLATEDIR=dirname($0)."/template";

############################# main ##############################

foreach (@ARGV) {
  if ( /-y/i ) {	# define variable used by ask routine
    $always_yes=1;
  } elsif ( /-c/i ) {	# no exit in dependence error
    $always_install=1;
  } elsif ( /-bsdport/i ) {	# 
    $bsdport=1;
  }
}

print "
=================================================
FtpLocate Install Program
by Distributed System Lab E.E. NCKU Taiwan 2003
http://turtle.ee.ncku.edu.tw/ftplocate/
=================================================\n\n";


#################################################################
#
# check basic requirement for ftplocate
#
#################################################################

print "check uid...";
if ( $> == 0 ) {
  print "ok\n";
} else {
  print "\nYou need to be root to install this program\n\n";
  if ( !$always_install ) {
    exit 1;
  }
}

print "check perl...";
eval { require "sys/syscall.ph"; };
if (!$@) {
  print "ok\n";
} else {
  print qq|\n\nperl *.ph file not found, pease do\n\n|.
        qq|cd /usr/include\n|.
        qq|h2ph -r -l .\n|.
        qq|\nto create ph files (Don't miss the dot at the line)\n\n|;
  if ( !$always_install ) {
    exit 1;
  }
}

print "check glimpse...";
if ( (-x "/usr/local/bin/agrep"   || -x "/usr/bin/agrep")
  && (-x "/usr/local/bin/glimpse" || -x "/usr/bin/glimpse") ) {
  print "ok\n";
} else {
  print "\nPlease install Glimpse(http://glimpse.cs.arizona.edu) first\n\n";
  if ( !$always_install ) {
    exit 1;
  }
}
  
print "check web server...";
$remote_sock=new IO::Socket::INET(	Proto=>'tcp',
					PeerAddr=>'localhost',
					PeerPort=>80,);
if ( $remote_sock ) {
  print "ok\n";
} else {
  print "\nPlease install a web server first\n\n";
  if ( !$always_install ) {
    exit 1;
  }
}


#################################################################
#
# guess default
#
#################################################################

$deffqdn=my_fqdn();
$defwwwuser='nobody';
$defwwwuser='apache' if ( (uidgid('apache'))[0]>0 );
$defwwwuser='www' if ( (uidgid('www'))[0]>0 );
$defhtmldir="/usr/local/www/data";
$defcgidir="/usr/local/www/cgi-bin";

if ( $bsdport ) { #if bsd port, pre-mkdir to bypass the below dir check
  $defwwwuser='www';
  if ( ! -d "/usr/local/www/data" ) {
    mkdir("/usr/local/www/data", 0755);
  }
  if ( ! -d "/usr/local/www/cgi-bin" ) {
    mkdir("/usr/local/www/cgi-bin", 0755);
  }
}

foreach (
	"/usr/local/www/data",
	"/usr/local/apache/data",
	"/opt/apache/share/data", 
	"/opt/apache/data",
	"/var/www/html",
	"/usr/local/www/data") {
  if ( -d $_ ) { $defhtmldir=$_; last }
}

foreach (
	"/usr/local/www/cgi-bin",
	"/usr/local/apache/cgi-bin",
	"/opt/apache/share/cgi-bin", 
	"/opt/apache/cgi-bin",
	"/var/www/cgi-bin",
	"/usr/local/www/cgi-bin") {
  if ( -d $_ ) { $defcgidir=$_; last }
}


#####################################################################
#
# confirm setting
#
#################################################################

$fqdn=ask(
"\nWhat is the domainname of your machine?
(default: $deffqdn)\n", $deffqdn);
print "The machine's domainname is [$fqdn]\n";

for ($i=0; $i<3; $i++) {
  $wwwuser=ask(
"\nWhich user does your web server run as?
(default: $defwwwuser)\n", $defwwwuser);
  ($uid, $gid)=uidgid($wwwuser);
  if ($uid>0) {
    print "Web server effective user is [$wwwuser]\n"; last; 
  } else {
    print "User $wwwuser doesn't exist\n";
  }
}
die "Too many retry, abort...\n" unless $i<3;


for ($i=0; $i<3; $i++) {
  $htmldir=ask(
"\nWhat is your system HTML path?
(default: $defhtmldir)\n", $defhtmldir);
  if ( -d "$htmldir" ) {
    print "Your system HTML path is [$htmldir]\n"; last; 
  } else {
    print "Dir $htmldir doesn't exist\n";
  }
}
die "Too many retry, abort...\n" unless $i<3;


for ($i=0; $i<3; $i++) {
  $cgidir=ask(
"\nWhat is your system CGI path?
(default: $defcgidir)\n", $defcgidir);
  if ( -d "$cgidir" ) {
    print "Your system CGI path is [$cgidir]\n"; last;
  } else {
    print "Dir $cgidir doesn't exist\n";
  }
}
die "Too many retry, abort...\n" unless $i<3;


for ($i=0; $i<3; $i++) {
  $fldir=ask(
"\nWhat subdir will be used for FtpLocate under HTML and CGI?
(default: ftplocate)\n", "ftplocate");

  if ( -d "$htmldir/$fldir" || -d "$cgidir/$fldir" ) {
    if ( -d "$htmldir/$fldir" ) { print "$htmldir/$fldir exists,\n"; }
    if ( -d "$cgidir/$fldir" ) { print "$cgidir/$fldir exists,\n"; }
    if ( ask("rename to $fldir.old?(Y/n)", "y") !~ /^n/i ) {
      rename("$htmldir/$fldir", "$htmldir/$fldir.old");
      rename("$cgidir/$fldir", "$cgidir/$fldir.old");
      print "rename $fldir to $fldir.old\n";
      last;
    } 
  } else {
    last;
  }
}
die "Too many retry, abort...\n" unless $i<3;
print "The FtpLocate html dir is [$htmldir/$fldir]\n";
print "The FtpLocate  cgi dir is [$cgidir/$fldir]\n";


if ( mbfree("/tmp") >= 100 ) {
  $deftmpdir="/tmp";
} else {
  $deftmpdir="$cgidir/$fldir/tmp";
}
$tmpdir=ask(
"\nWhat is the tmp directory for FtpLocate?
(default: $deftmpdir, at least 100mb free space is required)\n", $deftmpdir);
print "The tmp directory for FtpLocate is [$tmpdir]\n";


$lang=ask(
"\nWhat language do you prefer? 
(e for english, z for tradition chinese, default is english)\n", "english");
if ( $lang =~ /^z/i ) {
  $lang="zhtw";
} else {
  $lang="english";
}
print "The language for FtpLocate is [$lang]\n";

if ( ask("\n
=================================================
The setting for Ftplocate is
=================================================
domainname:	$fqdn
www user:	$wwwuser
help/doc dir:	$htmldir/$fldir
program dir:	$cgidir/$fldir
filelist dir:	$cgidir/$fldir/filelist
desc dir:	$cgidir/$fldir/desc
cache dir:	$cgidir/$fldir/cache
tmp dir:	$tmpdir
language: 	$lang

Are you sure to start installation?(Y/n)", "Y") =~ /^n/i ) {
  die "Canceled by user!\n";
}

#################################################################
#
# mkdir, copy files, config templates
#
#################################################################

# mkdir...
mkdir("$htmldir/$fldir", 0755);
mkdir("$cgidir/$fldir", 0755);
mkdir("$cgidir/$fldir/filelist", 0755);
mkdir("$cgidir/$fldir/desc", 0755);
mkdir("$cgidir/$fldir/cache", 0755);
if ( ! -d $tmpdir ) { mkdir("$tmpdir", 0755); }

# copy files...
print "cp doc to $htmldir/$fldir\n";
`cp $DOCDIR/* $htmldir/$fldir`;
print "cp bin to $cgidir/$fldir\n";
`cp $BINDIR/* $cgidir/$fldir`;

print "config templates\n";
# copy files by template
writefile("$htmldir/$fldir/index.html",
	do_config(readfile("$TEMPLATEDIR/index.html")) );
writefile("$htmldir/$fldir/help.english.html",
	do_config(readfile("$TEMPLATEDIR/help.english.html")) );
writefile("$htmldir/$fldir/help.zhtw.html",
	do_config(readfile("$TEMPLATEDIR/help.zhtw.html")) );

writefile("$cgidir/$fldir/config",
	do_config(readfile("$TEMPLATEDIR/config")) );
writefile("$cgidir/$fldir/config.site",
	do_config(readfile("$TEMPLATEDIR/config.site")) );
writefile("$cgidir/$fldir/indexer.sh",
	do_config(readfile("$TEMPLATEDIR/indexer.sh")) );

writefile("/usr/local/bin/ftplocate",
	do_config(readfile("$TEMPLATEDIR/ftplocate")) );

print "set owner and mode\n";
chdir("$cgidir/$fldir");
touch("log.map", "log.system", "log.user");
($uid, $gid)=uidgid($wwwuser);
chown($uid, $gid, "cache", "log.map", "log.user", "log.system");
chown($uid, $gid, $tmpdir) if ($tmpdir ne "/tmp") ;
chmod(0755, "indexer.sh", "/usr/local/bin/ftplocate");

print "\nInstallation completes...\n";

print "
To enable your FtpLocate search engine, you have to:\n\n";

if ($^X ne "/usr/local/bin/perl") {
   print "0. Please change the '#!/usr/local/bin/perl' to '#!$^X' in $cgidir/$fldir/*pl\n";
}
print "1. find the effective user of your http process and ensure
   $cgidir/$fldir/cache 
   $cgidir/$fldir/log.user 
   $tmpdir
   are writable by that user ($wwwuser)
2. edit config.site:	$cgidir/$fldir/config.site
3. run indexer.sh:	$cgidir/$fldir/indexer.sh
4. test text client:	/usr/local/bin/ftplocate
5. test FtpLocate CGI:	http://$fqdn/cgi-bin/$fldir/flsummary.pl
";

$free=int(mbfree("$cgidir/$fldir"));
if (  $free < 100 ) {
  print "
The free space available for $cgidir/$fldir is only $free MB!
Since FtpLocate will use large disk space in data collecting and indexing,
we strongly suggest you move dir filelist and desc to another partition.
";
}
print "\nThanks for using FtpLocate :)\n\nChung-Kie Tung  08/28/2003\n\n";


syntax highlighted by Code2HTML, v. 0.9.1