Re: Newscheck for nntp servers?

Mark Warren (mwarren@us.oracle.com)
Tue, 22 Dec 92 15:06:14 -0800

"Steve Kinzler" writes:
> Written Fri Dec 18 00:44:36 1992 by faces@stard.Eng.Sun.COM in mail:
>
> Why doesn't the regular newscheck.faces program work for you? It doesn't
> read the spool but runs "rn -c" or "nncheck -t" which should work across
> nntp, too. Maybe it should run "rrn" instead of "rn"?

This would probably work fine, alas, rn nor rrn are installed on my
workstation. (I'm using gnus)

> +---------- "Newscheck for nntp servers?" ----------
> | There is no local spool for news articles on my workstation, instead,
> | I get news from our company's nntp server. Has anyone written a
> | "newscheck" to open and properly query/parse an nntp server?
>

Lots of things were close, but nothing seemed to be precisely correct.
So I put together the following perl script from newcheck.faces
(from the faces distribution) and nntptap (from ftp.uu.net). This is
my first attempt at perl programming (ok, ok, so I'm a ways behind the
times...) and I'd love to hear about bugs and/or improvements.

Mark

Mark Warren 300 Oracle Parkway, office #423, mail #659304
warren@us.oracle.com Redwood Shores, CA 94065
(415) 506-4639 Voice or -7292 Fax Friends don't let friends run DOS

--------------------------->8 Cut Here 8<---------------------------

#!/home/mwarren/bin/perl
#
# run with the command line:
# faces -e nntpnewscheck.perl -f /home/mwarren/src2/faces/news -g +0+60
#

$cols = 2; $rows = 6;
$ZERO = $0;
$format = "%s\t%s\t%s\t%s\t%s\t%s\n";
$max = $cols * $rows;

sub usage {
die join("\n",@_) .
"\nusage: $ZERO [-h newshost] [-f check file]\n";
}

do 'getopt.pl' || die "Cannot do getopts.pl ($!)";

&Getopt('hf');

&usage("extra arguments: @ARGV") if $#ARGV > -1;

## defaults:
chop($thishost = `hostname`);
$fromhost = defined $opt_h ? $opt_h : 'oracle';
$checkfile = defined $opt_f ? $opt_f : '.newsrc-oracle';

$sockaddr = 'S n a4 x8';
@x = getprotobyname('tcp'); $proto = $x[2];
@x = getservbyname('nntp','tcp'); $port = $x[2];

sub hosttoaddr {
local($hostname) = @_;
local(@x);
if ($hostname =~ /^(\d+)+\.(\d+)\.(\d+)\.(\d+)$/) {
pack('C4', $1, $2, $3, $4);
} else {
@x = gethostbyname($hostname);
die "gethostbyname: $hostname ($!)" if $#x < 0;
$x[4];
}
}

$fromaddr = &hosttoaddr($fromhost);
$thisaddr = &hosttoaddr($thishost);

$thisproc = pack($sockaddr, 2, 0, $thisaddr);
$fromnntp = pack($sockaddr, 2, $port, $fromaddr);

$| = 1;

$FH = "nntp";

socket($FH, 2, 1, $proto) || die "$FH socket: $!";
bind($FH, $thisproc) || die "$FH bind: $!";
connect($FH, $fromnntp) || die "$FH connect: $!";
$oldfh = select($FH); $| = 1; select($oldfh);
(($_ = &get($FH)) =~ /^2/) || die "got $_ during greeting $FH";

sub put {
local($FH) = shift;
local($what) = shift;
print $FH "$what\n";
print "$FH >>> $what\n" if $verbose >= 3;
$what;
}

sub get {
local($FH) = shift;
local($what);
$what = <$FH>;
$what =~ s/\015//;
chop $what;
print "$FH >> $what\n" if $verbose >= 3;
$what;
}

#########################################################################
# Most of the new stuff is in the next two loops.
#
# Get latest article numbers for all news groups from the nntp server

&put($FH,"LIST");
while( $_ = &get($FH)){
last if /^\.$/;
next if /^2/;
($group, $high, $low, $posting) = split;
$news{$group}= $high;
}

# Get subscribed articles from $checkfile (format is assumed to be
# .newsrc format).

open checkfile;
while(<checkfile>){
($group, $articles) = split;
next if /!/; # skip unsubscribed groups
chop $group; # get rid of trailing `:' or `!'
@lastread = split(/[-,]/,$articles);

# Estimate unread articles by subtracting the last read article listed
# in $checkfile from the latest article number at the nntp server.
# Ignores intermediates.
$num = $news{$group} - $lastread[$#lastread];

$tarts += $num;
if (($n+1 < $max) && ($num > 0)) {
$n++;
$host = $abbr = $group;
$host = join('.', reverse split(/\./, $host));
$abbr =~ s/([^.])[^.]+\./$1./g;
$list .= sprintf($format, 'unknown', $host,
"$num $abbr", '', $group, '');
}
}
#
#
##########################################################################

if ($list) {
printf $format, 'news', "$fromhost", "$tarts/$n", '', '', '';
printf "Cols=%d Rows=%d\n", &lesser($n, $cols),
&lesser(($n - 1) / $cols + 1, $rows);
print $list;
} else {
printf $format, 'nonews', '', "0/0", '', '', '';
print "Cols=1 Rows=1\n";
printf $format, 'nonews', '', 'No news', '', 'No news', '';
}

sub lesser {
local($a, $b) = @_;
($a < $b) ? $a : $b;
}

exit 0;