From: Steven Foster
Subject: Script to automate your local veronica menu (maltshop-0.2).
Apparently-To:
[email protected]
Status: OR
#!/usr/local/bin/perl
#
# Copyright (C) Steven Foster 1994
#
# You are welcome to modify this software in any way you desire, for
# your use or for use AT YOUR SITE. However, you MAY NOT redistribute
# any modified forms of this program. To maintain consistency, please
# forward your changes, improvements and suggestions to me
# (
[email protected] ).
#
# DISCLAIMER
# No warranty is expressed or implied that this software will be suitable
# for any particular purpose, or that it will work at all. This source
# code is supplied "as-is", and you should ascertain that it is suitable
# for your purpose before running it. Neither I nor any other person or
# institution assumes any responsibility or liability for any undesirable
# consequences of the use of this software.
#
# ---------------- What is this program? -------------------------
#
# This script will build a veronica-access menu on your local gopher server.
# This does not mean you will run a veronica server of your own; rather, you
# will have a locally-held menu of veronica servers. The menu will be
# updated automatically, to show only those veronica servers currently
# operating.
#
# Reasons to have a local veronica menu:
#
# 1. Your users will have veronica access in spite of downtime at
# Nevada or Minnesota.
#
# 2. The veronica access menus at Nevada and Minnesota
# are getting too busy. Everyone's response time will be
# better if gopher sites have locally-held links to the veronica
# servers.
#
# 3. You have the most up-to-date menu. You can configure this
# program to check all veronica servers as often as you like.
# If a veronica server is down, or too slow, it will not appear
# on your menu.
#
# What it does:
#
# This script runs as a cron job. It polls a list of known, public
# veronica servers, determining which are reachable. It then builds a
# link-file in the data heirarchy of your gopher server, at a location
# you specify. You should specify a folder called something like:
# "Search GopherSpace using veronica".
# We recommend that you set the crontab to run the script every
# twenty minutes or so.
#
# Periodically, the script will get a new, updated list of public
# veronica servers from an authoritative site. You can set this
# update frequency to your liking. The program is shipped with a
# setting for six-day intervals. New veronica servers do not come
# online all that often, so this is probably often enough.
# You can set the update interval ( in days ) by editing a variable
# at the top of the program file.
#
# This program needs no maintenance. After you have edited the
# configuration variables, it will run by itself.
#
# INSTALLATION:
#
# The script has been tested with perl-4.036 on Ultrix, Solaris,
# and NeXT-OS.
#
# Install this script in a convenient location, for instance as
# /usr/local/bin/mkvermenu. Edit the crontab file to run the
# script at about 20 minute intervals. A sample crontab entry is:
#
# 18,38,58 * * * * root /usr/local/bin/mkvermenu
#
# There is some variation is crontab formats for various systems.
# Check the format to be sure.
#
# Edit the configuration options at the beginning of the program.
# You need to specify a file name where the script can keep its
# list of known servers, and a directory and filename for the
# file of gopher links that constitute the veronica menu. The latter
# directory and file must be in your gopher server's data heirarchy,
# at the location where you want the veronica menu to appear.
# Both these files must be writable by the PID that executes the
# script. If you run as root, no problem.
# Also, specify a writable tmp directory for the script to use.
#
# The remaining configuration variables are simple.
# A maximum of eight server entries is enough, since each server
# needs two lines on the menu, one for item searches and one for
# directory-only searches.
# Leave the six-day update period as is, unless you have a
# good reason to change it.
# There is an option that allows you to turn off the presentation
# of the search-gopher-directories items on the menu, should you
# want to do that.
#
# --------------------------------------------------------------------
# --- Set the following paths and options for your system ---------
#
# Full pathname for the local list of known veronica servers.
# If not present, this file will be created when program is installed.
# NOTE: This program must have write permission to this file.
$veronicaList = '/usr/local/etc/veronica.sites';
# Directory (in your gopher menu) where you want to put the
# list of veronica servers.
# NOTE: This program must have write permission to this directory.
$VeronicaDir = '/usr/local/gopher-data/veronica';
# Name for the file of links that will be built in $VeronicaDir.
# NOTE: This program must have write permission to this file.
$LinkFile = '.Links-veronica';
# readable/writable tmp directory for use by this script.
$TmpDir = '/tmp';
# Maximum number of servers you want to appear on your menu:
$MaxServers = 8;
# Interval in days between auto-updating the veronica site list
# This MUST be at least one.
$UpdateInterval = 6;
# Include "Search gopher directories" searches on the links menu.
# Set to 0 to omit directory-type searches from your menu.
$Include_gopher_dir_srch = 1;
# Include menu items for two veronica documents on the Nevada menu.
# Set to 0 to skip them....
$Include_docs = 1;
# Set this to see program's progress
$Debug = 0;
# ------------- End of configuration options ---------------------------
# -------------- Don't edit the stuff below. ---------------------------
$master_veronica_list = "veronica.scs.unr.edu 70 0/veronica/.veronica.sites\n";
$master_veronica_list2 = "gopher.tc.umn.edu 70 0/Other Gopher and Information Servers/Veronica/.veronica.sites\n";
&Initialize;
if ( ! ( $#verList >= 0 ) ) { exit; }
if ($Debug){ print "BEFORE connect:\n"; }
if ($Debug){ print " servers are: \n\r @verList \n"; }
# Try the veronica servers
&Connect;
# make the file of links
&Write;
# move file of links into place on gopher menu
$cmd = "cp $TmpDir/verlinks.tmp $VeronicaDir/$LinkFile";
system($cmd);
unlink ("$TmpDir/verlinks.tmp");
$rm_cache_cmd = "rm $VeronicaDir/.cac*";
system ("$rm_cache_cmd");
exit;
#==========================================================================
sub Initialize
{
$SIG{'INT'} = 'IGNORE';
$SIG{'ALRM'} = 'Alarm';
require 'sys/socket.ph';
$Date = `date`;
chop ($Date);
($Name, $Aliases, $Proto) = getprotobyname('tcp');
push ( @Listhosts, $master_veronica_list );
push ( @Listhosts, $master_veronica_list2 );
$sockaddr = 'S n a4 x8';
# read list of known veronica servers
open (veronicas, "< $veronicaList");
while (<veronicas>)
{
if ( /^\#/ ) { next; }
if ( /^\+/ ) { s/^\+\s*//; push ( @Listhosts, $_ ); next; }
if ( /^\!/ ) { s/^\!\s*//; push ( @verList, $_); }
}
close (veronicas);
# open temp file for new links list.
open (Link, "> $TmpDir/verlinks.tmp");
select (Link); $| = 1; select (STDOUT);
print Link "# This file automatically created by crontab on\n";
print Link "# $Date\n";
# Is it time to get a new master list of veronica sites?
# If no file of links, this is probably first startup, so get new list
if ( ! (-e "$VeronicaDir/$LinkFile" ))
{ &UpDateHostList; return; }
# If no veronica sites file, get new list
if ( ! (-e "$veronicaList" ))
{ &UpDateHostList; return; }
# If no servers were found in the veronica sites file, get new list
if ( ! ( $#verList >= 0 ) )
{ &UpDateHostList; return; }
# If sites file is too old, get new list
if ( $UpdateInterval < 1 ) { $UpdateInterval = 6; }
if ( ( -M $veronicaList) >= $UpdateInterval )
{ &UpDateHostList; return;}
} # end initialize
# ----------------------------------------------------------------------
sub UpDateHostList
{
foreach $host ( @Listhosts )
{
( $Lhost, $Lport, $Lpath ) = split ( /\s+/, $host, 3);
if ($Debug) { print "list host: $Lhost $Lport $Lpath"; }
chop ( $Lpath );
$! = '';
if ( &OpenServer ( $Lhost, $Lport ) )
{
if ( !$! )
{
print SERVER "$Lpath\r\n";
@NewList = <SERVER>;
close (SERVER);
# return must be at least two lines long
if ( !( $#NewList >= 1) ) { next; }
# line format must be ok
$BADFORMAT = 0;
foreach (@NewList)
{
s/\r//;
if ( /^\#/ ) { next; }
if ( /^\./ ) { next; }
if ( /^\s*$/ ) { next; }
if ( /^\+/ ) { s/^\+\s*//; push ( @NewListhosts, $_ ); next; }
if ( /^\!/ ) { s/^\!\s*//; push ( @NewverList, $_); next; }
$BADFORMAT = 1;
}
if ($BADFORMAT) { next; }
# Merge old and new lists of site-file-servers
foreach $a ( @NewListhosts )
{
( $NLhost, $NLport, $NLpath ) = split ( /\s+/, $a, 3);
chop ($NLpath);
$HL{"$NLhost\t$NLport\t$NLpath"} = $a;
}
foreach $a ( @Listhosts )
{
( $NLhost, $NLport, $NLpath ) = split ( /\s+/, $a, 3);
chop ($NLpath);
$HL{"$NLhost\t$NLport\t$NLpath"} = $a;
}
if ($Debug) { print "writing new veronica sites list\n"; }
open ( TMPLIST, ">$TmpDir/newhostlist.tmp" );
print TMPLIST "# File $veronicaList created on: \n";
print TMPLIST "# $Date\n";
print TMPLIST "# Using veronica site data from:\n";
print TMPLIST "# $Lhost $Lport $Lpath\n";
print TMPLIST "# Do not change the format of lines in this file;\n";
print TMPLIST "# the special characters are required by the program\n";
print TMPLIST "#\n";
# write list of site-file-servers
foreach $uniq ( keys ( %HL) )
{ print TMPLIST "+$HL{$uniq}"; }
# write list of veronica servers
foreach ( @NewverList )
{ print TMPLIST "!$_"; }
close (TMPLIST);
# working list of veronicas is now new list
undef @verList;
@verList = @NewverList;
# here copy tempfile to real sites file.
$cmd = "cp $TmpDir/newhostlist.tmp $veronicaList";
system($cmd);
unlink ("$TmpDir/newhostlist.tmp");
last;
}
}
close ( SERVER );
}
}
sub OpenServer
{
local ( $server, $port ) = @_;
$sockaddr = 'S n a4 x8';
(($name, $aliases, $type, $len, $saddr) = gethostbyname($server))
|| do {warn "Bad gethostbyname!\n"; return (0); };
$sin = pack($sockaddr, &AF_INET, $port, $saddr);
socket(SERVER, &AF_INET, &SOCK_STREAM, $Proto)
|| do {warn "Bad socket call!\n"; return (0);};
connect ( SERVER, $sin)
|| do {warn "Bad connect call!\n"; return (0);};
select (SERVER); $| = 1; select (STDOUT); $| = 1;
return (1);
}
sub Connect
{
$Slimit = ( $#verList + 1 ) - $MaxServers;
if ($Slimit < 0) { $Slimit = 0; }
while ( $#verList >= $Slimit )
{
alarm ('40');
$Line = shift(@verList);
chop $Line;
if($Debug){ print "Now call $Line \n"; }
next unless ($Line);
($Host,$Port,$Description,$Version) = split (/\s*\!\s*/, $Line, 4);
($Name, $Aliases, $Type, $Length, $RHostAddr) =
gethostbyname($Host);
$RHostSocketAddr = pack ($sockaddr, &AF_INET, $Port, $RHostAddr);
socket (S, &AF_INET, &SOCK_STREAM, $Proto)
|| warn "Can't create socket: $!\n";
#bind (S, $HostSocketAddr)
# || warn "Can't bind socket: $!\n";
$! = '';
connect (S, $RHostSocketAddr);
if (!$!)
{
select (S); $| = 1; select (STDOUT);
print S "-m?\r\n";
$Reply = <S>;
if ($Reply =~ /^.*\t.*\t.*\t\d+/)
{
push (@veronicas, "$Host $Port $Description");
}
}
else
{
print Link "# Can't connect to $Description: $!\n";
}
}
alarm(0);
}
sub Write
{
$Numb = 0;
if ( $Include_docs )
{
$Numb++;
print Link "Type=0\n";
print Link "Name=veronica FAQ (from Nevada)\n";
print Link "Path=0/veronica/veronica-faq\n";
print Link "Host=veronica.scs.unr.edu\n";
print Link "Port=70\n";
print Link "Numb=$Numb\n";
print Link "#\n";
$Numb++;
print Link "Type=0\n";
print Link "Name=How to compose veronica queries (from Nevada)\n";
print Link "Path=0/veronica/how-to-query-veronica\n";
print Link "Host=veronica.scs.unr.edu\n";
print Link "Port=70\n";
print Link "Numb=$Numb\n";
print Link "#\n";
}
foreach (@veronicas)
{
next unless ($_);
$Numb++;
($Host, $Port, $Description) = split (/\s+/, $_, 3);
print Link "Type=7\n";
print Link "Name=veronica server at $Description\n";
print Link "Path=\n";
print Link "Host=$Host\n";
print Link "Port=$Port\n";
print Link "Numb=$Numb\n";
print Link "#\n";
}
if ( $Include_gopher_dir_srch )
{
foreach (@veronicas)
{
next unless ($_);
$Numb++;
($Host, $Port, $Description) = split (/\s+/, $_, 3);
print Link "Type=7\n";
print Link "Name=Search Gopher Directory Titles at $Description\n";
print Link "Path=-t1 \n";
print Link "Host=$Host\n";
print Link "Port=$Port\n";
print Link "Numb=$Numb\n";
print Link "#\n";
}
}
close (Link);
}
sub Alarm
{
alarm (0);
print Link "# Alarm $Description\n";
&Connect;
}