#!/usr/local/bin/perl
#
# info2www - Gateway between GNU Info nodes and WWW
$id = '$Id: info2www,v 1.2 1994/07/28 15:39:38 lmdrsm Rel lmdrsm $';
#
# This is a script conforming to the CGI - Common Gateway Interface
#
# Author: Roar Smith (lmdrsm@lmd.ericsson.se)
#
# Copyright: This program is in the Public Domain.
#
# The original code (most of &info2html) was written by
# Eelco van Asperen (evas@cs.few.eur.nl).
#
# TODO:
# -----
# * Present a list of choices when there is no exact match for the requested
# Info file but multiple non-exact matches exist.
#
# * Use Tag Table to find possible file and offset.
#
#
#----------------- CONFIGURATION -----------------------------------------------
#
# Set $DEBUG = 1; to debug what's happening
#
$DEBUG = 0;
#
# INFOPATH is the path of direcories in which to search for Info node files.
#
@INFOPATH =
(
"/com/http/okoma/yuuji/yatex/info2",
"/usr/local/info",
);
#
# ALLOWPATH specifies whether info files with may be specified with path-names
# outside of those directories included in INFOPATH .
# It is a possible security hole to set this variable to a true value,
# because *any* file on the system could then be accessed through this gateway.
$ALLOWPATH = 0;
#
# ALIAS is a map of aliases - look for the alias if the node itself isn't found.
# The key (first entry) is the node filename, the value (second entry) is the
# alias. Both are basenames (i.e. no path!) with no capital letters.
# Note that the keys *must* be unique!
#
%ALIAS =
(
'emacs', 'lemacs',
'g++', 'gcc',
'c++', 'gcc',
'gunzip', 'gzip',
'zcat' , 'gzip',
'elisp', 'lispref'
);
#
# URL of the icons used for indicating references and stuff:
# $INFO_ICON - Icon at the top left of each document
# $UP_ICON - Icon used in an "Up:" hyperlink at the top
# $NEXT_ICON - Icon used in a "Next:" hyperlink at the top
# $PREV_ICON - Icon used in a "Prev:" hyperlink at the top
# $MENU_ICON - Icon used in front of each menu label
#
# Set these to "" if you don't want them used.
#
$INFO_ICON = "/~yuuji/yatex/info2/infodoc.gif";
$UP_ICON = "/~yuuji/yatex/info2/up.gif";
$NEXT_ICON = "/~yuuji/yatex/info2/next.gif";
$PREV_ICON = "/~yuuji/yatex/info2/prev.gif";
$MENU_ICON = "/~yuuji/yatex/info2/menu.gif";
#
# URL for documentation on info2www
#
# Set this to "" if you don't want it used.
#
$DOCREF = "/~yuuji/yatex/info2/info2www.html";
#
# CACHE is the dbm(3) or ndbm(3) file for cacheing lookup information.
# Set this to "" if you don't want it used.
# The effective user of this script should have write permissions to
# the directory in which the dbm files reside.
#
$CACHE = "/var/adm/info2www_cache";
#
# These are the defines for file-locking with flock(2)
#
$LOCK_SH = 1;
$LOCK_EX = 2;
$LOCK_NB = 4;
$LOCK_UN = 8;
#----------------- MAIN --------------------------------------------------------
print "Content-type: text/html\n"; #-- Mime header for NCSA httpd
print "\n";
print "$id
\n" if $DEBUG;
$pg = $0; $pg =~ s,^.*/([^/]*)$,$1,;
($version, $date) = ($id =~ m@,v\s+([0-9.]+)\s+([0-9/]+)@);
$script_name = $ENV{'SCRIPT_NAME'};
$server_name = $ENV{'SERVER_NAME'};
$request_method = $ENV{'REQUEST_METHOD'};
$prefix = $script_name . "?"; # prefix for HREF= entries
if ($request_method ne 'GET') {
die "REQUEST_MODE 'GET' expected - got '$request_method'\n";
}
print "ARGV: ", join('+', @ARGV), "
\n" if $DEBUG;
if ($#ARGV == -1) {
$nodename = "(DIR)";
} else {
$nodename = join('+', @ARGV);
$nodename = &DeEscape($nodename);
}
print "nodename: ", $nodename, "
\n" if $DEBUG;
&info2html($nodename);
if ($DOCREF) {
print
"
\n",
"automatically generated by ",
"$pg",
" version $version\n";
} else {
print
"
\n",
"automatically generated by ",
"$pg",
" version $version\n";
}
exit(0);
#----------------- SUBROUTINES -------------------------------------------------
#------------------------------------------------------------
# ToPattern
#------------------------------------------------------------
# This procedure transforms a string in a search pattern,
# escaping the non standard characters.
#------------------------------------------------------------
sub ToPattern{
local($Tag) = @_;
local(@Temp);
@Temp = split(/([^a-zA-Z0-9])/,$Tag);
$Tag = "";
for $x (@Temp){
$x = ($x =~ /[^a-zA-Z0-9]/) ? '\\'.$x : $x;
$Tag .= $x;
}
$Tag;
}
#---------------------------------------------------------
# Escape
#---------------------------------------------------------
# This procedures escapes some special characeters. The
# escape sequence follows the WWW guide for escaped
# characters in URLs
#---------------------------------------------------------
sub Escape{
local($Tag) = @_;
$Tag =~ s/%/%25/g; # %
$Tag =~ s/[ \n]+/%20/g; # space(s) and/or newline(s)
$Tag =~ s/\+/%2B/g; # +
return $Tag;
}
#----------------------------------------------------------
# DeEscape
#----------------------------------------------------------
sub DeEscape{
local($Tag) = @_;
$Tag =~ s/\\([][(){}|?*\\])/$1/g;
return $Tag;
}
#---------------------------------------------------------------------------
#
# info2html
#
#---------------------------------------------------------------------------
sub info2html {
local($nodename) = @_;
local($next_img, $prev_img, $up_img);
local($cachefound);
# Nodename looks like one of these:
# (file)label - Both file and label of the Info node given
# (file) - Label defaults to "Top"
# - File defaults to "DIR", Label defaults to "Top"
$matches = 0;
$blank = 0;
if ($nodename =~ /^\(([^\)]*)\)(.+)$/) {
($file, $node) = ($1, $2);
} elsif ($nodename =~ /^\(([^\)]*)\)$/) {
($file, $node) = ($1, "Top");
} elsif (!$nodename) {
($file, $node) = ("DIR", "Top");
} else {
print "Malformed node name: $nodename\n";
return(0);
}
$target = $node;
$target =~ y/A-Z/a-z/;
$target =~ s/%20/ /g;
$target =~ s/<\;//g;
$target = &ToPattern($target);
$file =~ s/<\;//g;
print "nodename: $nodename\nfile: $file\ntarget: $target\n" if $DEBUG;
$info_img = "
" if $INFO_ICON;
$next_img = "
" if $NEXT_ICON;
$prev_img = "
" if $PREV_ICON;
$up_img = "
" if $UP_ICON;
$nfiles = 0;
$cachefound = 0;
if ($CACHE) {
$cachefound = &TryCache("($file)$target");
}
if (!$cachefound) {
print "
FindFile...\n" if $DEBUG;
($directory, $basefile) = &FindFile($file);
if (!$directory) {
&error("Couldn't find Info file \"$file\".");
return(0);
}
&OpenFile($basefile) || return(0);
}
$active = 0;
$seenMenu = 0;
$indirect = 0;
$inentry = 0;
$lastblank = 0;
FileLoop:
for (; $nfiles > 0; ) {
local($handle) = "FH_$nfiles";
print "
--now reading from $handle--\n" if $DEBUG;
if ($basefile) {
$h_file = $basefile;
} elsif ($realfile{$handle}) {
$h_file = $realfile{$handle};
$h_file =~ s,.*/([^/])$,$1,;
$h_file =~ s,.*/(.*)-[0-9]+$,$1,;
}
while (<$handle>) {
chop;
s/&/&\;/g;
s/<\;/g;
s/>/>\;/g;
#study; # Doesn't seem to help or hurt!
/^[\037\f]/ && do {
&EndMenu();
&EndListing();
if ($active) {
close($handle);
print "
Closed file $handle\n" if $DEBUG;
return(1);
}
$active = 0;
$seenMenu = 0;
$indirect = 0;
$inentry = 0 if $inentry;
$inentry++;
$pos = tell - length($_) - 1;
next;
};
next if ($inentry == 0);
$lastblank = $blank; $blank = 0;
/^$/ && do {
if ($active) {
print "\n";
} elsif ($menu == 0) {
print;
}
$blank = 1;
next;
};
($inentry == 1) && do {
# top line:
# File: info, Node: Add, Up: Top, Prev: Expert, Next: Menus
/^tag table:/i && do {
# we don't use the tag table
$inentry = 0;
next;
};
/^indirect:/i && do {
# this entry is a list of filenames to include:
#
# gcc.info-1: 1131
# gcc.info-2: 49880
# gcc.info-3: 99426
$inentry++;
$indirect++;
next;
};
#
# Parse the header line. If one of the fields
# Node: Up: Next: Previous: File:
# is found, then a variable 'h_node' is set for
# the field 'node:', 'h_next' for 'next:', etc.
#
undef $h_node;
undef $h_file;
undef $h_next;
undef $h_prev;
undef $h_up;
/\bfile: *([^ ,\t]*)/i && do {
$h_file = $1;
};
/\bnode: *([^,\t]*)/i && do {
$h_node = $1;
$h_node =~ s/\s+$//; # delete trailing spaces
};
/\bup: *([^,\t]*)/i && do {
$h_up = $1;
$h_up =~ s/\s+$//; # delete trailing spaces
};
/\bprevious: *([^,\t]*)/i && do {
$h_prev = $1;
$h_prev =~ s/\s+$//; # delete trailing spaces
};
/\bprev: *([^,\t]*)/i && do {
$h_prev = $1;
$h_prev =~ s/\s+$//; # delete trailing spaces
};
/\bnext: *([^,\t]*)/i && do {
$h_next = $1;
$h_next =~ s/\s+$//; # delete trailing spaces
};
print "--h_node: $h_node--\n" if $DEBUG;
$n = 0;
if ($h_node =~ m/^$target$/i) {
$active = 1;
$matches++;
if ($CACHE && !$cachefound) {
&UpdateCache("($file)$target",
$pos, $realfile{$handle});
}
print
"
",
"Info Node: ($h_file)$h_node",
"\n",
"$info_img($h_file)$h_node
\n",
"
\n";
if (defined $h_next) {
print
"Next: ",
"",
&make_anchor($h_next, "$next_img$h_next"),
" ";
$n++;
}
if (defined $h_prev) {
print
"Prev: ",
"",
&make_anchor($h_prev, "$prev_img$h_prev"),
" ";
$n++;
}
if (defined $h_up) {
print
"Up: ",
"", &make_anchor($h_up, "$up_img$h_up"),
" ";
$n++;
}
}
print "\n
\n" if $n;
$inentry++;
&StartListing();
next;
};
($inentry == 2) && $indirect && do {
# each line of this entry consists of two fields,
# a filename and an offset, separated by a colon.
# For example:
# texinfo-1: 1077
local(@F) = split(/:/);
print "#include $F[0]\n" if $DEBUG;
# should save: $inentry $indirect
$save_inentry[$nfiles] = $inentry;
$save_indirect[$nfiles] = $indirect;
$inentry = 0;
$indirect = 0;
&OpenFile($F[0]) || return(0);
next FileLoop;
};
next if $active == 0;
if (($end) = /^\*\s+Menu:(.*)$/) {
# start of a menu:
$seenMenu = 1;
&EndListing();
print "$end";
&StartMenu();
next;
};
/^\*/ && do {
#---- SAMPLE LINES: -----------------------------------------
# * Sample::. Sample info.
#
# * Info: (info). Documentation browsing system.
#
# * Bison: (bison/bison)
# A Parser generator in the same style as yacc.
# * Random: (Random) Random Random Number Generator
#------------------------------------------------------------
if ($menu == 0 && $seenMenu) { &EndListing(); &StartMenu(); };
# * foo::
/^\*\s+([^:]+)::/ && do {
$rest_of_line = $';
print
"
", &make_anchor($1, $1, $MENU_ICON),
"";
$rest_of_line =~ s/^[\s\.]+//;
print $rest_of_line, "\n";
next;
};
# * foo: (bar)beer OR (bar)
/^\*\s+([^:]+):\s+\(([^\) \t\n]+)\)([^\t\n\.,]*)/ && do {
$rest_of_line = $';
print
"", &make_anchor("($2)$3",$1, $MENU_ICON),
"";
$rest_of_line =~ s/^[\s\.]+//;
print $rest_of_line, "\n";
next;
};
# * foo: beer.
/^\*\s+([^:]+):\s+([^\t,\n\.]+)/ && do {
$rest_of_line = $';
print
"", &make_anchor($2, $1, $MENU_ICON),
"", $2, ". ";
$rest_of_line =~ s/^[\s\.]+//;
print $rest_of_line, "\n";
next;
};
# no match: ignore silently
};
$menu && $lastblank && do {
&EndMenu();
&StartListing();
};
$menu && do {
s/^\s+//;
};
/\*note/i && do {
# cross reference entry:
# "*note nodename::."
# "*note Cross-reference-name: nodename."
local($n) = 0;
while (1) {
# *note \nfoo... (reference split over newline)
if (/\*note\s*$/i) {
$_ .= "\n" . <$handle>; # Merge with next line
chop;
}
# *note foo\nbar... (reference split over newline)
if (/\*note\s+[^:\.]+$/i) {
$_ .= "\n" . <$handle>; # Merge with next line
chop;
}
# *note foo: bar\nbleh... (reference split over newline)
if (/\*note\s+[^:\.]+:\s+[^:\.\t]+$/i) {
$_ .= "\n" . <$handle>; # Merge with next line
chop;
}
# *note foo:
if (/\*note(\s+)([^:\.]+)::/i) {
s//@@@NOTE@@@/; # insert unique (I hope) marker
local($spc, $ref, $lbl) = ($1, $2, $2);
local($note) = "Note:$spc";
$note .= &make_anchor($ref, $lbl);
s/@@@NOTE@@@/$note/;
$n++;
next;
}
# * foo: (bar)beer OR (bar)
if (/\*note(\s+)([^:]+):\s+\(([^\) \t\n]+)\)([^\t\.,]*)(.?)/i) {
s//@@@NOTE@@@/; # insert unique (I hope) marker
local($spc, $ref, $lbl) = ($1, "($3)$4", "$2$5");
local($nl) = ($ref =~ /\n/) ? "\n" : "";
local($note) = "Note:$spc";
$note .= &make_anchor($ref, $lbl);
s/@@@NOTE@@@/$note$nl/;
$n++;
next;
}
# * foo: beer.
if (/\*note(\s+)([^:]+):\s+([^\t,\.]+)(.?)/i) {
s//@@@NOTE@@@/; # insert unique (I hope) marker
local($spc, $ref, $lbl) = ($1, $3, "$2$4");
local($nl) = ($ref =~ /\n/) ? "\n" : "";
local($note) = "Note:$spc";
$note .= &make_anchor($ref, $lbl);
s/@@@NOTE@@@/$note$nl/;
$n++;
next;
}
last;
}
# if ($n > 0) {
# local($l) = $listing;
# &EndListing() if $l;
# print "$_\n";
# &StartListing() if $l;
# next;
# }
};
print "$_\n";
}
&EndMenu();
# clear status variables;
$active = 0;
$seenMenu = 0;
$indirect = 0;
$inentry = 0;
$lastblank = 0;
print "--end of file $handle--\n" if $DEBUG;
close($handle);
print "
Closed file $handle\n" if $DEBUG;
$nfiles--;
$inentry = $save_inentry[$nfiles];
$indirect = $save_indirect[$nfiles];
print "--inentry: $inentry--indirect: $indirect--
\n" if $DEBUG;
last if $matches;
}
if (!$matches) {
&error("Couldn't find target: \"$target\" in file \"$file\".");
if ($cachefound) {
&UpdateCache("($file)$target");
}
}
return $matches;
}
#---------------------------------------------------------------------------
sub make_anchor {
local($ref, $label, $icon) = @_;
local($node_file, $node_name, $img, $href);
print "--make_anchor($ref, $label)
\n" if $DEBUG;
# (foo)bar
if ($ref =~ m/\(([^\)]+)\)\s*([^\t,\.]*)/) {
$node_file = $1;
$node_name = $2;
} elsif ($file =~ /^dir$/i) {
print "--(DIR) node - Menu \"@_\" means \"($ref)\"
\n" if $DEBUG;
$node_file = $ref;
$node_name = "";
} else {
$node_file = $h_file;
$node_name = $ref;
}
$node_name =~ s/[ ]*$//;
if ($node_name ne "") {
$href = &Escape("$prefix($node_file)$node_name");
} else {
$href = &Escape("$prefix($node_file)");
}
if ($icon) {
$img = "
";
}
return "$img$label";
}
sub StartMenu {
print "\n
" if $active;
$menu = 1;
}
sub EndMenu {
if ($menu) {
print "
\n" if $active;
$menu = 0;
}
}
sub StartListing {
print "\n" if $active;
$listing++;
}
sub EndListing {
if ($listing) {
print "\n" if $active;
$listing--;
}
}
sub FindFile {
local($filename) = @_;
local($dir, $fil);
print "
", "FindFile: '$filename'\n" if $DEBUG;
($dir, $fil) = &FindFileNoAlias($filename);
if ($dir) {
return $dir, $fil;
}
# Try a possible alias...
$fil = $filename;
$fil =~ s/[-\.]info$//;
$fil =~ tr/A-Z/a-z/;
$filename = $ALIAS{$fil};
print "
", "\$", "ALIAS{", $fil, "} = ", $filename, "\n" if $DEBUG;
if ($filename) {
print "
Trying with the alias \"$filename\"...\n" if $DEBUG;
return &FindFileNoAlias($filename);
} else {
# Bummer - no alias
return;
}
}
sub FindFileNoAlias {
local($filename) = @_;
local($altfilename) = $filename;
local(@filelist) = ();
local($dir, $fil);
local($regex, $altregex);
if ($filename =~ /\.info$/) {
$altfilename =~ s/\.info$//;
} elsif ($filename =~ /-info$/) {
$altfilename =~ s/-info$/.info/;
} else {
$altfilename =~ s/$/.info/;
}
print "
FindFileNoAlias: '$filename', Alt='$altfilename'\n" if $DEBUG;
$regex = &ToPattern($filename);
$altregex = &ToPattern($altfilename);
# Try absolute match for $filename...
if ($filename =~ /\//) {
($dir, $fil) = ($filename =~ m,(.*)/([^/]*),);
if ($ALLOWPATH || grep($_ eq $dir, @INFOPATH)) {
print "
Trying absolute match for \"$filename\"...\n" if $DEBUG;
if (-e "$filename") {
return $dir, $fil;
}
print "
Trying absolute match for \"$altfilename\"...\n"
if $DEBUG;
if (-e "$altfilename") {
($dir, $fil) = ($altfilename =~ m,(.*)/([^/]*),);
return $dir, $fil;
}
$file =~ s,^.*/([^/]*)$,$1,;
$filename =~ s,^.*/([^/]*)$,$1,;
$altfilename =~ s,^.*/([^/]*)$,$1,;
print "
Stripped path from filename: $filename\n" if $DEBUG;
} elsif (!$ALLOWPATH) {
print "
Warning: Absolute path-names not allowed!\n" if $DEBUG;
$file =~ s,^.*/([^/]*)$,$1,;
$filename =~ s,^.*/([^/]*)$,$1,;
$altfilename =~ s,^.*/([^/]*)$,$1,;
print "
Stripped path from filename: $filename\n" if $DEBUG;
}
}
# Try exact match for $filename in all directories...
print "
Trying exact match for \"$filename\"...\n" if $DEBUG;
foreach (@INFOPATH) {
if (-e "$_/$filename") {
return $_, $filename;
}
}
# Try exact match for $altfilename in all directories...
print "
Trying exact match for \"$altfilename\"...\n" if $DEBUG;
foreach (@INFOPATH) {
if (-e "$_/$altfilename") {
return $_, $altfilename;
}
}
# Try caseless match for $filename in all directories...
print "
Trying caseless match for \"$filename\"...\n" if $DEBUG;
@filelist = ();
foreach (@INFOPATH) {
$dir = $_;
opendir(DIR, $dir);
push (@filelist,
sort grep(s/^/$dir\//, grep(/^$regex$/i, readdir(DIR))));
closedir(DIR);
}
if ($#filelist > 0) {
# Multiple matches...present list or just return one item?
($dir, $fil) = ($filelist[0] =~ m,(.*)/([^/]*),);
return $dir, $fil;
} elsif ($#filelist == 0) {
($dir, $fil) = ($filelist[0] =~ m,(.*)/([^/]*),);
return $dir, $fil;
}
# Try caseless match for $altfilename in all directories...
print "
Trying caseless match for \"$altfilename\"...\n" if $DEBUG;
@filelist = ();
foreach (@INFOPATH) {
$dir = $_;
opendir(DIR, $dir);
push (@filelist,
sort grep(s/^/$dir\//, grep(/^$altregex$/i, readdir(DIR))));
closedir(DIR);
}
if ($#filelist > 0) {
# Multiple matches...present list or just return one item?
($dir, $fil) = ($filelist[0] =~ m,(.*)/([^/]*),);
return $dir, $fil;
} elsif ($#filelist == 0) {
($dir, $fil) = ($filelist[0] =~ m,(.*)/([^/]*),);
return $dir, $fil;
}
# Bummer - no matches at all
return;
}
sub OpenFile {
local($filename) = @_;
local($alternate, $handle);
$nfiles++;
$handle = "FH_$nfiles";
if ($filename =~ /\//) {
($directory, $filename) = ($filename =~ m,(.*)/([^/]*),);
}
$realfile{$handle} = "$directory/$filename";
$success = 0;
print
"Trying to open file ",
"\"$filename\" in directory \"$directory\" ...\n" if $DEBUG;
if (open($handle, "$directory/$filename")) {
print "
Opened file \"$directory/$filename\"\n" if $DEBUG;
return(1);
} else {
print "
Could not open file",
"\"$filename\" in directory \"$directory\".\n" if "$DEBUG";
return(0);
}
}
sub TryCache {
local($cachekey) = @_;
local($handle, $line, $h_node);
local($cachevalue, $cachepos, $cachefile, $cachedir, $newkey);
print "
Trying cached entry for \"$cachekey\"...\n" if $DEBUG;
if ($CACHE && &LockCache()) {
if (dbmopen(%cache, $CACHE, 0644)) {
$cachevalue = $cache{$cachekey};
dbmclose(%cache);
&UnLockCache();
} else {
$CACHE = "";
&UnLockCache();
return(0);
}
} else {
$CACHE = "";
return(0);
}
if (!$cachevalue) {
if ($cachekey =~ m,\(.*/.*\).*,) {
$newkey = $cachekey;
$newkey =~ s,^\(.*/([^/\)]*)\),($1),;
return(&TryCache($newkey));
} else {
return(0);
}
}
print "
Cached entry found: " if $DEBUG;
($cachepos, $cachefile) = split("\0", $cachevalue);
print "$cachepos in \"$cachefile\"\n" if $DEBUG;
if ($cachefile =~ /\//) {
$cachedir = $cachefile;
$cachedir =~ s,(.*)/[^/]*$,$1,;
if (!$ALLOWPATH && !grep($_ eq $cachedir, @INFOPATH)) {
print "
Warning: Absolute path-names not allowed!\n" if $DEBUG;
&UpdateCache($cachekey);
return(0);
}
}
if (!&OpenFile($cachefile)) {
&UpdateCache($cachekey);
return(0);
}
$handle = "FH_$nfiles";
print "
--now reading from $handle--\n" if $DEBUG;
if (!seek($handle, $cachepos, 0)) {
close($handle);
&UpdateCache($cachekey);
return(0);
}
print "
Position: $cachepos\n" if $DEBUG;
if ($line = <$handle>) {
chop($line);
$line =~ s/&/&\;/g;
$line =~ s/<\;/g;
$line =~ s/>/>\;/g;
print("
line: <", $line, ">\n") if $DEBUG;
if ($line =~ /^[\037\f]/) {
print "
Found node-start\n" if $DEBUG;
if ($line = <$handle>) {
chop($line);
$line =~ s/&/&\;/g;
$line =~ s/<\;/g;
$line =~ s/>/>\;/g;
print("
line: <", $line, ">\n") if $DEBUG;
if ($line =~ /\bnode: *([^,\t]*)/i) {
$h_node = $1;
$h_node =~ s/\s+$//; # delete trailing spaces
if ($h_node =~ m/^$target$/i) {
print "
Found the node!\n" if $DEBUG;
seek($handle, $cachepos, 0);
print("
", tell, "\n") if $DEBUG;
return(1);
}
}
}
}
}
&UpdateCache($cachekey);
close($handle);
return(0);
}
sub UpdateCache {
local($key, $pos, $file) = @_;
local($value);
if ($CACHE && &LockCache()) {
if (dbmopen(%cache, $CACHE, 0644)) {
if ($pos && $file) {
$cache{$key} = join("\0", $pos, $file);
print "
cache{$key} set to: $pos in \"$file\"\n" if $DEBUG;
} else {
delete $cache{$key};
print "
cache{$key} deleted\n" if $DEBUG;
}
dbmclose(%cache);
&UnLockCache();
return(1);
} else {
$CACHE = "";
&UnLockCache();
return(0);
}
} else {
$CACHE = "";
return(0);
}
}
sub LockCache {
local($file) = $CACHE . ".lock";
if (!open(LOCKFILE, ">$file")) {
print "
Couldn't open CACHE lockfile \"$file\"\n" if $DEBUG;
print "
Reason: $!\n" if $DEBUG;
return(0);
}
if (!flock(LOCKFILE, $LOCK_EX)) {
print "
Couldn't lock CACHE lockfile \"$file\"\n" if $DEBUG;
print "
Reason: $!\n" if $DEBUG;
close(LOCKFILE);
return(0);
}
print "
Locked CACHE lockfile \"$file\"\n" if $DEBUG;
return(1);
}
sub UnLockCache {
local($file) = $CACHE . ".lock";
if (!flock(LOCKFILE, $LOCK_UN)) {
print "
Couldn't unlock CACHE lockfile \"$file\"\n" if $DEBUG;
print "
Reason: $!\n" if $DEBUG;
close(LOCKFILE);
return(0);
}
close(LOCKFILE);
print "
Unlocked CACHE lockfile \"$file\"\n" if $DEBUG;
return(1);
}
sub error {
local($reason) = @_;
print
"
Lookup Error
Lookup Error
Can't retrieve your request - $reason\n";
return(0);
}
#---------------------------------------------------------------------------