#!/bin/perl
# Gopher-nnrp Gateway version 2.0 rewrite by: Chad Adams (
[email protected])
# 28-May-1993 version 2.0 Chad Adams
# add newgroups database.
# add multi level newsgroup menus. [each .part. of newsgroup automaticly
# gets it's own menu instead of putting all (like all of comp) in one
# menu. {now menus like comp.sys, comp.lang, comp.sources, ect..}]
# convert to use xhdr instead of tin's xindex. If not used with INN using
# overview files to speed up xhdr it may be slow.
#
# Gopher-NNTP Gateway version 1.0
# Author: Daniel Schales (
[email protected])
# Major rewrite, socket support: Doug Schales (
[email protected])
#
# Set the 4 following variables for your setup. the 2 port variables
# are set to the standard, be sure to set gopherhost and nntphost to
# your respective hosts.
$gopherhost="news.ecn.bgu.edu";
$gopherport=2008;
# $nntpprt='gopher-nntp';
$nntpprt='nntp';
$nntphost="news.ecn.bgu.edu";
@INC=("/usr/local/lib/perl");
require 'sys/socket.ph';
dump QUICKSTART if @ARGV[0] eq '-dump';
QUICKSTART:
$SIG{'ALRM'} = 'stuck';
$option=shift;
$option = '-h' if $option eq '-t';
while ($option eq '-f') {
$copyright = shift;
$option = shift;
open(CR, $copyright);
$title = <CR>;
close(CR);
chop($title);
print "0$title\t$copyright\t$gopherhost\t$gopherport\r\n";
}
$item=shift;
if ($option eq '-X') {
@arts = @ARGV;
} else {
$lookup=shift;
}
# set an alarm 5 minutes from now, if it goes off we must be stuck
alarm(300);
open(LOG,">>/tmp/nntplog");
$date=`date`;chop($date);
print LOG $date," ",$option," ",$item," ",$lookup,"\n";
close(LOG);
$sockaddr = 'S n a4 x8';
($name, $aliases, $proto) = getprotobyname('tcp');
($name, $aliases, $nntpport) = getservbyname($nntpprt, 'tcp');
($name, $aliases, $type, $len, $nntpaddr) = gethostbyname($nntphost);
$rsockaddr = pack($sockaddr, &AF_INET, $nntpport, $nntpaddr);
socket(NNTPSOCK, &PF_INET, &SOCK_STREAM, $proto) || die "socket: $!";
connect(NNTPSOCK, $rsockaddr) || die "connect: $!";
select(NNTPSOCK); $|= 1; select(stdout);
$_ = <NNTPSOCK>;
if ($option eq '-g') {
dbmopen(newsgroups, '/usr/lib/newsgroups', 0444);
print NNTPSOCK "LIST\n";
$_ = <NNTPSOCK>;
chop; chop;
while($_ ne "."){
if($_ =~ "^$item"){
($group) = split;
push(@out,"1$group - $newsgroups{$group}\texec:-h $group:".
"/bin/gonnrp\t$gopherhost\t$gopherport\r\n");
}
$_ = <NNTPSOCK>;
chop; chop;
}
print sort(@out);
print ".\r\n";
} elsif ($option eq '-G') {
dbmopen(newsgroups, '/usr/lib/newsgroups', 0444);
print NNTPSOCK "LIST\n";
$_ = <NNTPSOCK>;
chop; chop;
$itemlen = length($item) + 1;
@grouplist = ();
while($_ ne "."){
if($_ =~ "^$item"){
($group) = split;
push(@grouplist, $group);
}
$_ = <NNTPSOCK>;
chop; chop;
}
@grouplist = sort(@grouplist);
for ($i = 0; $i <= $#grouplist; $i++) {
$group = @grouplist[$i];
if ($group eq $item) {
$grp = $group;
print "1$newsgroups{$group}\texec:-T $group:".
"/bin/gonnrp\t$gopherhost\t$gopherport\r\n";
} else {
$grp = substr($group,$itemlen,40);
if (index($grp,'.') != -1) {
@grppart = split(/\./,$grp);
if (@grppart[0] eq $oldgrp) {
next;
}
$oldgrp = @grppart[0];
$grp = @grppart[0];
print "1$grp - ".$newsgroups{"$item.$grp.all"}.
"\texec:-G $item.$grp".
":/bin/gonnrp\t$gopherhost\t$gopherport\r\n";
} else {
if ($group eq substr(@grouplist[$i+1],0,length($group))) {
print "1$grp - ".$newsgroups{"$item.$grp.all"}.
"\texec:-G $group:".
"/bin/gonnrp\t$gopherhost\t$gopherport\r\n";
$oldgrp = $grp;
} else {
print "1$grp - $newsgroups{$group}\texec:-T $group:".
"/bin/gonnrp\t$gopherhost\t$gopherport\r\n";
}
}
}
}
print ".\r\n";
} elsif($option eq '-X') {
# $item = newsgroup
# @arts = articles in this thread
# or
# @arts = 0 low high if list would be too long
($code) = &group($item);
# build arts array if we were passed range
@arts = split(' ', &buildidx(@arts[1], @arts[2])) if @arts[0] == 0;
foreach $art (@arts) { $goodart{$art} = 1; }
&xhdr('from', @arts[0], @arts[$#arts]);
while (<NNTPSOCK>) {
last if substr($_,0,1) eq '.';
chop; chop;
($art, $from) = split(/ /,$_,2);
print "0$from\texec:-a ${item} $art:/bin/gonnrp\t".
"$gopherhost\t$gopherport\r\n" if $goodart{$art};
}
print ".\r\n";
} elsif($option eq '-T') {
($code, $cnt, $low, $high) = &group($item);
&buildidx($low, $high);
@keys = sort(keys %idx);
foreach $key (@keys) {
@arts = split(' ',$idx{$key});
if ($#arts == 0) { # single article
print "0$key\texec:-a ${item} @arts[0]:".
"/bin/gonnrp\t$gopherhost\t$gopherport\r\n";
} else { # thread
if (length($idx{$key}) < 80) { # send article list
print "1$key\texec:-X $item$idx{$key}:".
"/bin/gonnrp\t$gopherhost\t$gopherport\r\n";
} else { # give range
print "1$key\texec:".
"-X $item 0 @arts[0] @arts[$#arts]:".
"/bin/gonnrp\t$gopherhost\t$gopherport\r\n";
}
}
}
print ".\r\n";
} elsif($option eq '-l'){
($code, $count, $start, $end) = &group($item);
if($count ne "0"){
print NNTPSOCK "ARTICLE $end\n";
$body=0;
$_ = <NNTPSOCK>;
chop; chop;
while($_ ne "."){
if ($body) {
print "$_\r\n";
} elsif ($_ =~ "^220 " || $_ =~ "^222 ") {
$body = 1;
}
}
$_ = <NNTPSOCK>;
chop; chop;
}
}
# rwp 20Aug92 Add ability to fetch last article.
elsif($option eq '-h' || $option eq '-b' || $option eq '-s'){
($code, $count, $start, $end) = &group($item);
if($count ne "0"){
&xhdr('subject', $start, $end);
$_ = <NNTPSOCK>;
chop; chop;
while($_ ne '.'){
($num,$desc) = split (/ /,$_,2);
if ($option eq '-h' ) {
print "0$desc\texec:-a ${item} ${num}:".
"/bin/gonnrp\t$gopherhost\t$gopherport\r\n";
} elsif ($option eq '-b') {
print "0$desc\texec:-a ${item} ${num} body".
":/bin/gonnrp\t$gopherhost\t$gopherport\r\n";
} elsif ($option eq '-s') {
$desc1="\L$desc\E";
$lookup1 ="\L$lookup\E";
if ($desc1 =~ $lookup1 ) {
print "0$desc\texec:-a ${item} ${num}:".
"/bin/gonnrp\t$gopherhost\t$gopherport\t\r\n";
}
}
$_ = <NNTPSOCK>;
chop; chop;
}
}
print ".\r\n";
} elsif($option eq '-a'){
$num = $lookup;
$part = shift;
($code) = &group($item);
if($part eq "body") {
print NNTPSOCK "BODY $num\n";
($code) = split(/ /,($_ = <NNTPSOCK>));
&checkcode($code,222);
} else {
print NNTPSOCK "ARTICLE $num\n";
($code) = split(/ /,($_ = <NNTPSOCK>));
&checkcode($code,220);
}
$_ = <NNTPSOCK>;
chop; chop;
while($_ ne "."){
print "$_\r\n";
$_ = <NNTPSOCK>;
chop; chop;
}
}
print NNTPSOCK "QUIT\n";
shutdown(NNTPSOCK, 2);
exit(0);
sub stuck {
open(LOG,">>/tmp/nntplog");
$date=`date`;chop($date);
print LOG $date," hung on ",$option," ",$item," ",$lookup,"\n";
close(LOG);
exit;
}
# Chad Adams 28-May-1993 tin's xindex to xhdr conversion
sub checkcode { # return error when nntp command failes
local($code, $goodcode) = @_;
if ($code != $goodcode) {
print "0$_\t\t\t\r\n";
print ".\r\n";
exit;
}
}
sub buildidx { # build subject threads
local ($low, $high) = @_;
local ($first, $fsubj, $re, $subj);
$first = 1;
&xhdr('subject', $low, $high);
$cnt = 0;
while (<NNTPSOCK>) {
last if substr($_,0,1) eq '.';
chop; chop;
($art, $subj) = split(/ /,$_,2);
while (1) { # remove Re:
$re = substr($subj,0,2);
$re =~ tr/A-Z/a-z/;
if ($re eq 're') {
$subj = substr($subj,2);
next;
} elsif (substr($subj,0,1) eq ':') {
$subj = substr($subj,1);
next;
} elsif (substr($subj,0,1) eq ' ') {
$subj = substr($subj,1);
next;
}
last;
}
if ($first) {
$fsubj = $subj;
$first = 0;
}
$idx{$subj} .= " $art";
$cnt++;
}
return $idx{$fsubj};
}
sub group { # (code, count, low, high) = &group(newsgroup)
local(@rtn);
print NNTPSOCK "group @_[0]\n";
@rtn = split(/ /,($_ = <NNTPSOCK>), 5);
&checkcode(@rtn[0],211);
return @rtn;
}
sub xhdr { # &xhdr(header,low,high)
local($code);
print NNTPSOCK "xhdr @_[0] ".@_[1].'-'.@_[2]."\n";
($code) = split(/ /,($_ = <NNTPSOCK>));
&checkcode($code,221);
}