#!/usr/athena/bin/perl
#
# ID Responder
#
# Takes input from STDIN, looks for a line that says "path#" and will
# grab that for a response address, and then will look for a line with
# "id#" and will use that as the number of IDs to send to that person.
#
# Created by:	Derek Atkins <warlord@MIT.EDU>
#
# $Source$
# $Author$
#

$LOCKFILE = "/tmp/factorlock";
$ID_CACHE = "/factor/home/LastID";
$LOG = "/factor/home/IDlog";

$MYADDRESS = "factorid@hot-spare.mit.edu";
$MYBANNER = "Factor ID Distribution <$MYADDRESS>";
$MASTER = "warlord@MIT.EDU";
$SENDMAIL = "/usr/lib/sendmail -oi -f$MASTER";
$CC_LINE = "rsa129-request@iastate.edu";

$LOCK_SH = 1;
$LOCK_EX = 2;
$LOCK_NB = 4;
$LOCK_UN = 8;

sub lock {
    flock(LOCK,$LOCK_EX);
}

sub unlock {
    flock(LOCK,$LOCK_UN);
}

# gets the next N ID numbers from the sourcefile, and modifies
# that file to reflect the change.  Takes one argument, which is
# the number of IDs to get.  This arg must be > 0.
# returns an array of ID numbers
sub getIDs {
    local($n) = @_;
    local(@ID);

    open(ID, "$ID_CACHE");
    $FirstID = <ID>;
    chop($FirstID);
    close(ID);

    $LastID = $FirstID + $n;

    print "ID's are $FirstID - $LastID\n";

    open(ID, ">$ID_CACHE");
    print ID "$LastID\n";
    close(ID);

    $LastID--;

    if ($n > 1) {
	return("$FirstID through $LastID (inclusive)");
    }

    return("$FirstID");
}

# Opens a Sendmail connection
# PrepMail("To", "Subject")
sub PrepMail {
    local($whoto, $subj) = @_;
    
    open(MAIL, "|$SENDMAIL \'$CC_LINE\' \'$whoto\'") 
	|| die "Can't open $SENDMAIL\n";
    print MAIL "To: $whoto\n";
    print MAIL "Cc: $CC_LINE\n";
    print MAIL "From: $MYBANNER\n";
    print MAIL "Errors-To: $MASTER\n";
    print MAIL "Subject: $subj\n\n";
    print MAIL "Please make sure that each running mpqs process is\n";
    print MAIL "using a *unique* ID number.\n\n";
    print MAIL "If you have any questions, please send mail to\n";
    print MAIL "rsa129-request@iastate.edu\n\n";
}    

# Log("msg");
sub Log {
    open(LOG, ">>$LOG");

    print LOG "@_";
    print LOG "\n";
    close(LOG);
}

open(LOCK, ">>$LOCKFILE") || die "Can't open lockfile: $!";

# Aquire the lock
do lock();

# We haven't sent a response, yet.
$sent_response = 0;

# read the input
while (<>) {

    chop;
    ($item, $text) = split(/[ \t\n]+/, $_, 2);

    if ($item =~ m/^From:/) {
	$From = "$text";
    }
    if ($item =~ m/^Reply-To:/) {
	$ReplyTo = "$text";
    }
    if ($item =~ m/^path#/) {
	$Addr = "$text";
    }
    if ($item =~ m/^id#/) {
	$IDs = "$text";

	if (defined($Addr)) {
	    $Towhom = "$Addr";
	} else {
	    $Towhom = "$From";
	    $Towhom = "$ReplyTo" if defined($ReplyTo);
	}

	&PrepMail("$Towhom", "Reply from ID Responder");

	if (! defined($Addr)) {
	    print MAIL "You did not define a path to get back to you.\n";
	    print MAIL "I just replied to you.\n";
	}

	if ($IDs <= 0) {
	    print MAIL "You have asked for an invalid number of IDs.\n";
	    print MAIL "Please try again.  Sorry.\n";
	    &Log("\[From: $From\] \[Path: $Addr\] Bad ID request: $ID");

	} else {
	    $IDstr = &getIDs($IDs);

	    print MAIL "Your IDs are:\n";
	    print MAIL "$IDstr\n";
	    
	    &Log("\[From: $From\] \[Path: $Addr\] IDs: $FirstID - $LastID");
	}
	close(MAIL);
	$sent_response = 1;
    }
}

if ($sent_response == 0) {
    $Towhom = "$From";
    $Towhom = "$ReplyTo" if defined($ReplyTo);
    &PrepMail("$Towhom", "Error in ID Responder");

    print MAIL "\nYou sent a badly formatted request to the ID responder.\n";
    print MAIL "Therefore I cannot process your request.  The proper format\n";
    print MAIL "for requests is:\n\n";
    print MAIL "path# reply-address\n";
    print MAIL "id# number-of-IDs\n\n";
    print MAIL "Thank you for using the RSA129 ID Responder.\n";
    close(MAIL);
}

#release the lock
do unlock();
close(LOCK);
