#!/usr/bin/perl
# 
# $Id: post_faq.pl.base,v 1.42 1994/11/01 17:36:25 tkoenig Exp $
# 
# Copyright (c) 1991 Jonathan I. Kamens.  See the GNU Public License
# (any version) for terms of distribution.

push(@INC, "/usr/lib");

require 'faqfile.pl';

$SIG{'PIPE'} = 'sigpipe';

# These variables can be overridden by command-line options.

open(SERVER, "< /etc/news/server") || die "Opening /etc/news/server to read: $!.\n";
$server = <SERVER>;
chop $server;			# News server to which to connect, if NNTP
close SERVER;

$default_inews = "/usr/bin/inews";	# Inews program to use

open(IDHOST, "< /etc/mailname") || die "Opening /etc/mailname to read: $!.\n";
$idhost = <IDHOST>;
chop $idhost;			# News server to which to connect, if NNTP
close IDHOST;

$configfile = undef;
$faqfile'file_version = 2;
$expire_search = undef;

# These can be overridden by each FAQ.

$faqfile'default_interval = 0;	# Default interval to wait between postings
$faqfile'default_sigfile = "none";	# Signature file to append to posting
$faqfile'default_force = 0;		# Force posting of this FAQ?

# These can't be overridden at all without editing the script.

@months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
	   'Sep', 'Oct', 'Nov', 'Dec');

# This controls the number of days added to _twice_ the posting
# interval in order to determine how many days into the future the
# "Expires" header date should be set. I've picked a value of 7, which
# means that I'm assuming that an article will make it to the entire
# USENET within the interval plus 7 days of when it is posted.
$expire_slop = 7;

%faqs = ();
%only = ();
%omit = ();
$quiet = 0;
$newstamp = time;

$usage = "Usage: $0 -config file-name [ -interval days ]
	[ -inewscmd command ] [ -server nntp-server ] [ -idhost host-name ]
	[ -sigfile file-name ] [ -quiet number ] [ -omit id-list ]
	[ -only id-list ] [ -force ] [ -expire_search ] [ -debug ]";

# Parse command line arguments

while ($_ = $ARGV[0], /^-/) {
    shift;
    if (/^-interval$/) {
	((@ARGV > 0) || die "Missing argument to \"-interval\" option.\n")
	    && ($faqfile'default_interval = shift) && next;
    }
    elsif (/^-inewscmd$/) {
	((@ARGV > 0) || die "Missing argument to \"-inewscmd\" option.\n")
	    && ($inews = shift) && next;
    }
    elsif (/^-server$/) {
	((@ARGV > 0) || die "Missing argument to \"-server\" option.\n")
	    && ($server = shift) && next;
    }
    elsif (/^-idhost$/) {
	((@ARGV > 0) || die "Missing argument to \"-idhost\" option.\n")
	    && ($idhost = shift) && next;
    }
    elsif (/^-sigfile$/) {
	((@ARGV > 0) || die "Missing argument to \"-sigfile\" option.\n")
	    && ($faqfile'default_sigfile = shift) && next;
    }
    elsif (/^-config$/) {
	((@ARGV > 0) || die "Missing argument to \"-config\" option.\n")
	    && ($configfile = shift) && next;
    }
    elsif (/^-quiet$/) {
	((@ARGV > 0) || die "Missing argument to \"-quiet\" option.\n");
	$quiet = shift;
	next;
    }
    elsif (/^-omit$/) {
	if (@ARGV > 0) {
	    foreach $i (split(/,/, shift)) {
		$omit{$i}++;
	    }
	    next;
	}
	else {
	    die "Missing argument to \"-omit\" option.\n";
	}
    }
    elsif (/^-only$/) {
	if (@ARGV > 0) {
	    foreach $i (split(/,/, shift)) {
		$only{$i}++;
	    }
	    next;
	}
	else {
	    die "Missing argument to \"-only\" option.\n";
	}
    }
    elsif (/^-force$/) {
	($faqfile'default_force = 2) && next;
    }
    elsif (/^-debug$/) {
	++$debug && next;
    }
    elsif (/^-expire_search$/) {
	++$expire_search && next;
    }
    die "Unknown option \"$_\".\n$usage\n";
}

die "No config file specified!\n$usage\n" if (! $configfile);

($faqfile'default_sigfile = undef) if ($faqfile'default_sigfile eq "none");

if (! defined($inews)) {
    if ($debug) {
	$inews = "cat";
    }
    else {
	$inews = $default_inews . " -h";
    }
}

$ENV{'NNTPSERVER'} = $server;

if ($debug) {
    $configin = $configfile;
    $configout = "/dev/null";
    print "Not modifying config file, because -debug specified.\n"
	if ($quiet < 1);
}
else {
    if (-z $configfile) {
	die "Configuration file is zero size.... aborting!\n";
    }
    $configin = "$configfile.old";
    $configout = $configfile;
    rename($configout, $configin) || 
	die "Renaming $configout: $!.\n";
}
open(CONFIG, "$configin") || die "Opening $configin to read: $!.\n";
open(CONFIGOUT, ">$configout") || die "Opening $configout to write: $!.\n";

while (<CONFIG>) {
    chop;
    local($idname, $file, $oldstamp, $interval, $sigfile, $force, $parent) =
	&faqfile'parse_faq($_);
    ($sigfile = $faqfile'default_sigfile) if (! $sigfile);

    if (! $idname) {
	print CONFIGOUT $_, "\n" ||
	    die "Writing to $configout: $!.\n";
	next;
    }

    if (%only) {
	if (!$only{$idname}) {
	    print "Skipping $idname because of -only.\n"
		if ($quiet < 1);
	    goto nextone;
	}
    }
    elsif (%omit) {
	if ($omit{$idname}) {
	    print "Skipping $idname because of -omit.\n"
		if ($quiet < 1);
	    goto nextone;
	}
    }

    ($timeout, $reason) = &faqfile'should_post($idname);

    if (! $timeout) {
	print("Skipping $idname ($reason).\n") if ($quiet < 1);
	goto nextone;
    }
    else {
	print "Posting $idname ($reason).\n" if ($quiet < 1);
	$inews_pid = open(INEWS, "|$inews");
	open(FAQ, $file) || 
	    (warn("Opening $file (for $idname): $!.\n"), goto nextone);
	printf(INEWS "Message-ID: %s\n", 
	       &message_id($idname, $newstamp, $idhost)) ||
		   (warn("Printing to $inews pipe: $!.\n"), goto nextone);
	if ($oldstamp) {
	    printf(INEWS "Supersedes: %s\n",
		   &message_id($idname, $oldstamp, $idhost)) ||
		       (warn("Printing to $inews pipe: $!.\n"), goto nextone);
	}
	$expire_time = undef;
	if ($interval =~ /^[0-9]+$/) {
	    if ($interval > 0) {
		$expire_time = $newstamp + (2 * $interval + $expire_slop) *
		    (60 * 60 * 24);
	    }
	}
	elsif ($expire_search) {
	    $expire_time = &faqfile'expire_search($idname, $newstamp) +
		$expire_slop * (60 * 60 * 24);
	}
	if ($expire_time) {
	    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
		gmtime($expire_time);
	    $year += 1900;
	    printf(INEWS "Expires: %d %s %d %02d:%02d:%02d GMT\n",
		   $mday, $months[$mon], $year, $hour, $min, $sec) ||
		       (warn("Printing to $inews pipe: $!.\n"), goto nextone);
	}
	if ($parent) {
	    printf(INEWS "References: %s\n", 
		   &message_id($parent, &faqfile'timestamp($parent), 
			       $idhost)) ||
				   (warn("Printing to $inews pipe: $!.\n"),
				    goto nextone);
	}
	while (<FAQ>) {
	    while (/\@message-id +([^ \@]+) *\@/i) {
		local($newid) = &message_id($1, $newstamp, $idhost);
		$_ = $` . $newid . $'; #`
	    }
	    while (/\@old-id +([^ \@]+) *\@/i) {
		local($time) = &faqfile'timestamp($1);
		local($newid);
		if ($time) {
		    $newid = &message_id($1, $time, $idhost);
		}
		else {
		    warn "$idname requests Message ID of unknown posting $1.\n";
		    $newid = "<unknown>";
		}
		$_ = $` . $newid . $'; #`
	    }
	    print INEWS $_ || 
		(warn("Printing to $inews pipe: $!.\n"), goto nextone);
	}
	if ($sigfile && ($sigfile ne "none")) {
	    if (! open(SIGFILE, $sigfile)) {
		warn "Opening \"$sigfile\": $!.\nSignature will not be included on $idname.\n";
	    }
	    else {
		print INEWS "-- \n" || 
		    (warn("Printing to $inews pipe: $!.\n"), goto nextone);
		while (<SIGFILE>) {
		    print INEWS $_ ||
			(warn("Printing to $inews pipe: $!.\n"), goto nextone);
		}
	    }
	}

	close(INEWS);
	$inews_pid = undef;
	if ($?) {
	    warn "$inews exited with non-zero status posting $idname.\n";
	    goto nextone;
	}
	close(FAQ);
	printf("Article %s posted successfully.\n",
	       &message_id($idname, $newstamp, $idhost))
	    if ($quiet < 2);
	if ($force == 1) {
	    &faqfile'set_force($idname, undef);
	    print "Force disabled on $idname.\n"
		if ($quiet < 2);
	}
	elsif ($force == 3) {
	    &faqfile'set_force($idname, -2);
	    print "Force replaced with suspend on $idname.\n"
		if ($quiet < 2);
	}
	&faqfile'set_posted($idname);
	&faqfile'set_timestamp($idname, $newstamp);
    }
nextone:
    kill('TERM', $inews_pid) if ($inews_pid);
    print CONFIGOUT &faqfile'configline($idname), "\n" ||
	die "Writing to $configout: $!.\n";
}

close(CONFIG);
close(CONFIGOUT) || die "Closing $configout: $!.\n";

sub message_id {
    # Takes three arguments -- an ID name, a time, and a host name --
    # and returns the message ID to use.  If you want to do custom
    # message ID's for some or all of your FAQs, this is the routine
    # to modify.
    # 
    # Beware that this routine is used to generate message IDs of
    # parent articles as well as message IDs of articles currently
    # being posted, so don't put in any implicit dependencies that
    # won't work.

    local($idname, $time, $host) = @_;

    "<${idname}_${time}\@${host}>";
}

sub sigpipe {
    # Don't do anything; we'll notice it because $? will be non-zero
    # when the file handle is closed.
}
