#!/usr/local/bin/perl5 -s
#
# This file is part of SnarfNews
# Copyright (C) 1991,1992,1993,1994,1995,1996 Alec Muffett
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

require "snarf.pl";

$usage = "nntpmsgids [-debug] [-gronk] hostname[:port] [configfile]\n";

# cheap filtering
$xpostmax = $ENV{"SNARFXPOSTMAX"};

# hostname[:port] to connect to
$host = shift || die $usage;

# config files (note that config file will require :port if specified)
$configfile = shift || "$ENV{SNARFCONF}/sites/$host";
$nconfigfile = "$configfile.NEW";
$oconfigfile = "$configfile.OLD";

# open config files
unless (open(GRP, $configfile))
{
    die "nntpmsgids: open: $configfile: $!\n";
}

unless (open(NGRP, ">$nconfigfile"))
{
    die "nntpmsgids: open: $nconfigfile: $!\n";
}

# make latter unbuffered for disaster recovery
select((select(NGRP), $| = 1)[0]);

# connect
unless (&OpenNNTP($host))
{
    die "nntpmsgids: cannot open connection to $host\n";
}

# read a line to see if we got a good connection.
if (($_ = &RecvNNTP(0)) !~ /^200/o)
{
    die "nntpmsgids: service unavailable: $_";
}

# do we drive gronk directly?
if ($gronk)
{
    if ($debug)
    {
	$cmd = "gronkmsgids -debug $host 2";
    }
    else
    {
	$cmd = "gronkmsgids $host 2";
    }

    unless(open(STDOUT, "| $cmd"))
    {
	die "nntpmsgids: popen: $cmd: $!\n";
    }

    warn "nntpmsgids: opened '$cmd'\n" if ($debug);

    sleep(1);                   # let the child catch up.
}

# auto-flush on STDOUT
$| = 1;

# in case we run into an INN server
&SendNNTP("MODE reader\n");

if (($_ = &RecvNNTP(0)) !~ /^200/o)
{
    warn "nntpmsgids: server didn't like MODE command: $_";
}

# hack through the group list
while(<GRP>)                    # for each group
{
    # comment
    if (/^(\#|\s)/o)
    {
	print NGRP $_;
	next;
    }

    s/\#.*//o;                  # remove trailing comments

    ($groupname, $haveart) = split;

    # make sure the group change worked...
    &SendNNTP("GROUP $groupname\n");

    $_ = &RecvNNTP(0);

    ($retval, $numart, $firstart, $lastart) = split;

    if ($retval !~ /^211/o)
    {
	warn "nntpmsgids: bad group: $groupname: $_";
	print NGRP "$groupname $haveart\t\t\t# bad group?\n";
	next;
    }

    &ArtsViaXhdr($firstart, $lastart, $haveart);

    print NGRP "$groupname $lastart\n";
}

&SendNNTP("QUIT\n");

if (($_ = &RecvNNTP(0)) !~ /^205/o)
{
    warn "nntpmsgids: server didn't like QUIT command: $_";
}

&CloseNNTP;
close(GRP);
close(NGRP);

if ($gronk)
{
    close(STDOUT);

    if ($?)
    {
	die "nntpmsgids: skipping update: '$cmd' exit code $?\n";
    }
    else
    {
	warn "nntpmsgids: '$cmd' exit code $? (ok)\n" if ($debug);
    }
}

unlink($oconfigfile);

unless (rename($configfile, $oconfigfile))
{
    die "nntpmsgids: rename: $configfile $oconfigfile: $!\n";
}

unless (rename($nconfigfile, $configfile))
{
    die "nntpmsgids: rename: $nconfigfile $configfile: $!\n";
}

exit(0);

##################################################################
##################################################################

sub ArtsViaXhdr
{
    local($first, $last, $lwm) = @_;
    %artok = ();

    if ($first > $lwm)
    {
	$lwm = $first;          # We missed a bunch
    } else
    {
	$lwm++;                 # Try for next article
    }

    if ($lwm > $last)
    {
	return 1;
    }
    elsif ($lwm == $last)
    {
	$xrange = $lwm;
    }
    else
    {
	$xrange = "$lwm-$last";
    }

    if ($xpostmax)
    {
	&SendNNTP("XHDR Newsgroups $xrange\n");

	if (($_ = &RecvNNTP(0)) !~ /^221/o)
	{
	    warn "nntpmsgids: $groupname: XHDR failed: $_";
	    return undef;
	}

	while ($_ = &RecvNNTP(3))
	{
	    last if ($_ eq ".\n");

	    ($art, $ngline) = split;

	    $ngline =~ tr/,//cd;
	    $xpostnum = length($ngline) + 1;

	    printf(STDERR "- xhdr: article %d, %d/%d groups ",
		   $art, $xpostnum, $xpostmax) if ($debug);

	    if ($xpostnum > $xpostmax)
	    {
		warn "[dropped]\n" if ($debug);
	    }
	    else
	    {
		warn "\n" if ($debug);
		$artok{$art} = 1;
	    }
	}
    }

    &SendNNTP("XHDR Message-Id $xrange\n");

    if (($_ = &RecvNNTP(0)) !~ /^221/o)
    {
	warn "nntpmsgids: $groupname: XHDR Message-Id failed: $_";
	return undef;
    }

    while ($_ = &RecvNNTP(3))
    {
	last if ($_ eq ".\n");

	($art, $msgid) = split;

	if ($xpostmax)
	{
	    next unless $artok{$art};
	}

	print $msgid, "\n";
    }

    return 1;
}
