#!/afs/athena/contrib/perl/perl
#
# File: nntpcheck - check nntpserver for unread news
# $Header: /afs/sipb/contrib/perl/nntp/RCS/nntpcheck,v 1.2 1992/09/17 04:22:21 ckclark Exp $
# 
# KOPYKNOT (K) 1991 Free Knoware Foundation, Ink.
# 
# This file is part of Randall's NNTP grep-n'-fetch-it utilites.
# 
# NNTP grep-n'-fetch-it is free software.  You can redistribute it and
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation or not.  That's what makes
# this a Kopyknot.  You can use this code for any purpose whatsoever.
# If you can make a dime off it, great.  I'm not out to stop you.  If
# you want to claim you wrote it, great.  It ain't up to me to blow your
# cover.  Go for it.
# 
# NNTP grep-n'-fetch-it is distributed in the hope that it will make
# Randall a famous net.personality.  It includes ABSOLUTELY NO WARRANTY.
# In fact, you should know that this code will probably fail in lots
# of different ways on lots of different machines.  If you want to fix
# the problems, great.  If you want to tell me what you changed, great.
# If you want me to fix something for you, go screw yourself.  I'm busy.
# 
# This Kopyknot was inspired by the GNU Copyleft.  I think that Richard
# Stallman is a mensch.  If I weren't so obsessed by the almighty buck,
# I'd try to get a job working for him.  If you want more information on
# the GNU General Public License, get GNU Emacs, or write to the Free
# Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
# 
# I hope you don't feel insulted by my parody, Richard.

unshift(@INC, "/afs/sipb.mit.edu/contrib/perl");
unshift(@INC, "/afs/sipb.mit.edu/contrib/perl/nntp");

require('getopts.pl');
require('nntp.pl');

sub usage
{
    die <<"EndoUsage"
usage: $0 [-<options>] [<newsgroup>] ...
    options:	-a:		check all groups (even unsubscribed)
		-g:		check groups missing from newsrc
		-G:		subscribe to missing groups
		-q:		quiet (suppress output)
		-u:		limit search to unread articles
		-U:		update the newsrc file
		-v:		verbose (print article ranges)
		-z:		list groups with zero articles
		-l <numgrps>:	limit listed groups
		-r <range>:	limit search to range
		-F <newsrc>:	use alternate newsrc file
		-S <server>:	use alternate news server
EndoUsage
    ;
}

# process command line arguments
&usage if ! &Getopts('agGquUvzl:r:F:S:');

$opt_u = 1 if $opt_U;		# -U implies -u
$opt_u = 1 if $opt_F;		# always use .newsrc if specified
$opt_F = ($ENV{"HOME"} . "/.newsrc") if ! $opt_F;

$opt_l = 999999 if ! $opt_l;	# limit is infinity if not specified

$opt_g = 1 if $opt_G;		# -G implies -g

# don't let the user specify a messy range
$opt_r = &nntp'canon_artlist($opt_r) if defined($opt_r);
$opt_r = "0-0" if (defined($opt_r) && !$opt_r);	# if range is "0"

# open a connection to the news server.  program will die if bad connection
$server = $opt_S ? &nntp'connect($opt_S) : &nntp'connect;

%groups = ();			# start with empty groups

# make a list of each group to scan
@ARGV = ( "all" ) if ! @ARGV;	# scan all groups if none specified
while ($_ = shift)
{
    foreach $ng (&nntp'list($server, $_))
    {
	$groups{$ng} = 1;
    }
}

if (! %groups)
{
    warn "No groups matched.\n";
    exit(0);
}

$exitstatus = 0;		# assume no news

$| = 1;				# flush output to pipes

# process groups in the newsrc order
if ($opt_u)
{
    foreach $ng (&nntp'newsrc_list($opt_F))
    {
	next if ! $groups{$ng};	# skip if it doesn't match news group pattern
	$old = &nntp'newsrc_get($opt_F, $ng, $opt_a);
	delete $groups{$ng};	# don't process again later
	next if ! $old;		# skip if unsubscribed
	
	@lim = &nntp'setgroup($server, $ng);
	next if ! @lim;		# this should never ever happen
	next if $lim[0] == 0 && ! $opt_z; # skip if no articles
	
	$new = "$lim[1]-$lim[2]";
	$new = &nntp'canon_isect($new, $opt_r) if $opt_r;
	$new = &nntp'newsrc_merge($opt_F, $ng, $new);
	
	# count up the old and new articles
	$cnt = 0;
	
	# add up new article ranges
	foreach $rng (&nntp'canon_expand($new))
	{
	    ($first, $last) = split(/-/, $rng);
	    $cnt += $last - $first + 1;
	}
	
	# subtract off old article ranges
	foreach $rng (&nntp'canon_expand($old))
	{
	    ($first, $last) = split(/-/, $rng);
	    $cnt -= $last - $first + 1;
	}
	
	if (!$opt_q && ($cnt > 0 || $opt_z))
	{
	    if (!$opt_v)
	    {
		print "$cnt unread articles in $ng\n" if ! $opt_U;
		print "$cnt articles updated in $ng\n" if $opt_U;
	    }
	    else
	    {
		$upd = &nntp'canon_inverse($old, $lim[1], $lim[2]);
		$upd = &nntp'canon_isect($upd, $new);
		print "$cnt unread articles in $ng: $upd\n" if ! $opt_U;
		print "$cnt articles updated in $ng: $upd\n" if $opt_U;
	    }
	}
	# stop processing if enough groups checked
	$exitstatus = 1 if $cnt > 0;
	last if ($cnt > 0) && (--$opt_l <= 0);
    }
}

# now process remaining groups not listed in newsrc file
if ((!$opt_u || $opt_g) && $opt_l > 0)
{
    foreach $ng (sort(keys(%groups)))
    {
	@lim = &nntp'setgroup($server, $ng);
	next if ! @lim;		# this should never ever happen
	
	$new = ($lim[0] > 0) ? "$lim[1]-$lim[2]" : "";
	$new = &nntp'canon_isect($new, $opt_r) if $opt_r;
	# add up new article ranges
	$cnt = 0;
	foreach $rng (&nntp'canon_expand($new))
	{
	    ($first, $last) = split(/-/, $rng);
	    $cnt += $last - $first + 1;
	}
	
	&nntp'newsrc_put($opt_F, $ng, $new);
	&nntp'newsrc_subscribe($opt_F, $ng, $opt_G);

	if (!$opt_q)
	{
	    print "adding unsubscribed newsgroup: $ng\n" if $opt_U && ! $opt_G;
	    print "adding subscribed newsgroup: $ng\n" if $opt_U && $opt_G;
	}

	if (!$opt_q && ($cnt > 0 || $opt_z))
	{
	    if (!$opt_v)
	    {
		print "$cnt unread articles in $ng\n" if ! $opt_U;
		print "$cnt articles updated in $ng\n" if $opt_U;
	    }
	    else
	    {
		print "$cnt unread articles in $ng: $new\n" if $opt_U;
		print "$cnt articles updated in $ng: $new\n" if $opt_U;
	    }
	}
	# stop processing if enough groups checked
	$exitstatus = 1 if $cnt > 0;
	last if ($cnt > 0) && (--$opt_l <= 0);
    }
}


# write out the newsrc information
&nntp'newsrc_write($opt_F) if $opt_U;

exit($exitstatus);
