#!/bin/perl # Gopher-nnrp Gateway version 2.0 rewrite by: Chad Adams (c-adams@bgu.edu) # 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 (dan@engr.latech.edu) # Major rewrite, socket support: Doug Schales (d1s8027@sc.tamu.edu) # # 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 = ; 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); $_ = ; if ($option eq '-g') { dbmopen(newsgroups, '/usr/lib/newsgroups', 0444); print NNTPSOCK "LIST\n"; $_ = ; 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"); } $_ = ; chop; chop; } print sort(@out); print ".\r\n"; } elsif ($option eq '-G') { dbmopen(newsgroups, '/usr/lib/newsgroups', 0444); print NNTPSOCK "LIST\n"; $_ = ; chop; chop; $itemlen = length($item) + 1; @grouplist = (); while($_ ne "."){ if($_ =~ "^$item"){ ($group) = split; push(@grouplist, $group); } $_ = ; 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 () { 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; $_ = ; chop; chop; while($_ ne "."){ if ($body) { print "$_\r\n"; } elsif ($_ =~ "^220 " || $_ =~ "^222 ") { $body = 1; } } $_ = ; 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); $_ = ; 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"; } } $_ = ; 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(/ /,($_ = )); &checkcode($code,222); } else { print NNTPSOCK "ARTICLE $num\n"; ($code) = split(/ /,($_ = )); &checkcode($code,220); } $_ = ; chop; chop; while($_ ne "."){ print "$_\r\n"; $_ = ; 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 () { 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(/ /,($_ = ), 5); &checkcode(@rtn[0],211); return @rtn; } sub xhdr { # &xhdr(header,low,high) local($code); print NNTPSOCK "xhdr @_[0] ".@_[1].'-'.@_[2]."\n"; ($code) = split(/ /,($_ = )); &checkcode($code,221); }