/***************************************************************************/
/*  Module:      $Id: client.c,v 1.3 1995/03/17 04:12:38 maf Exp $
/*  Description: Client mode functions of sendpage
/*  Author:      maf
/*
/* Copyright (c) 1995 Mark Fullmer and The Ohio State University
/***************************************************************************/

/*
$Log: client.c,v $
 * Revision 1.3  1995/03/17  04:12:38  maf
 * STATUS_EXPANDED should not have been set for the max messages limit
 *
 * Revision 1.2  1995/03/15  04:40:30  maf
 * *** empty log message ***
 *
 * Revision 1.1  1995/01/10  01:34:02  maf
 * Initial revision
 *
*/


#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <fcntl.h>
#include <syslog.h>
#include <stdlib.h>
#include <unistd.h>
#include <db.h>
#include "report.h"
#include "sendpage.h"

#ifdef NEED_MALLOC_H
#include <malloc.h>
#endif

/*********************************************************************/
/* Function: BeAClient
/*	high level sendpage client function.
/*
/*	args:
/*		argc			command line
/*		argv			""
/*		optind			from getopt
/*		skiptoblank		if true, skips all messages until blank line
/*						-- for interfacing with sendmail
/*		sender			the sender's e-mail address
/*		sendnow			try to signal the daemon to send the message now?
/*		maxmsgs			maximum # of messages to accept
/*						-- to prevent sendmail accidents (page floods)
/*		nomail			if true, don't setup for mail response.
/*
/* Returns: EX_OK		good --	messages accepted, daemon notified.
/* 			EX_OK		good -- messages accepted, daemon not notified
/*			EX_SOFTWARE	bad -- some unrecoverable error, message is printed
/*			EX_NOINPUT	bad -- no messages or too many messages
/*
/*********************************************************************/
BeAClient(argc, argv, optind, skiptoblank, sender, sendnow, maxmsgs, nomail)
int argc, optind, sendnow, skiptoblank, maxmsgs, nomail;
char **argv, *sender;
{

	struct msglist msglist;
	struct linebuf linebuf;
	struct messagequeue entry;
	char *p, *qfname;
	extern int debug;
	int i, j, err, nrecipients, x, ret;
	unsigned int pid;
	FILE *FP;
	char nullbyte;

	bzero(&msglist, sizeof(msglist));
	bzero(&linebuf, sizeof(linebuf));
	bzero(&entry, sizeof(entry));
	err = EX_NOINPUT;	/* fatal */
	nullbyte = 0;
	pid = 0;

	/* calculate # of recipients  */
	nrecipients = argc - optind;

	/* can't send pages without recipients... */
	if (!nrecipients) {
		fprintf(stderr, "No valid recipients.\n");
		goto BeAClientout;
	}

	while (1) {

		if ((ret = GetLine(STDIN_FILENO, &linebuf)) == -1) {
			fprintf(stderr, "GetLine() failed\n");
			goto BeAClientout;
		}

		/* skip to a blank line ?? */
		if (skiptoblank) {
			if (linebuf.len2)
				goto skip1;
			else {
				skiptoblank = 0;
				goto skip1;
			}
		}

		/* add non blank lines to list */
		if (linebuf.len2) 
			if (AddMessage(&msglist, linebuf.len2, linebuf.buf)) {
				fprintf(stderr, "AddMessage() failed\n");
				goto BeAClientout;
			}
			
skip1:
		/* exit loop on EOF */
		if (ret == 1)
			break;
		
	} /* while 1 */
#ifdef DEBUG
	if (debug > 2) {
		fprintf(stderr, "Message list: (%d messages)\n", msglist.nmessages);
		for (x = 0; x < msglist.nmessages; ++x)
			fprintf(stderr, "  %s\n", msglist.messages[x]);
	} /* debug > 2*/
#endif /* DEBUG */

	if (!msglist.nmessages) {
		fprintf(stderr, "Request rejected: No valid messages.\n");
		err = EX_NOINPUT;
		goto BeAClientout;
	}


	/* Got reciepient(s), got message(s), queue them */

	/* sender and len is same for all */
	entry.senderlen = (sender) ? strlen(sender) : 0;

	/* for each recipient */
	for (i = 0; i < nrecipients; ++i) {
		/* for each message */
		for (j = 0; j < msglist.nmessages; ++j) {

			/* mark for mail reply? */
			entry.status = (nomail) ? STATUS_NOMAIL : STATUS_NONE;

			/*
			/* handle too many messages.  The message that hits the "too many"
			/* mark is tagged with STATUS_MSGTRUNCATE which (may) generate
			/* an e-mail reply saying this and any any other messages that
			/* may have been sent have been dropped due to an administrative
			/* threshold.
			*/
			if (maxmsgs && (j >= maxmsgs)) 
				entry.status |= STATUS_MSGTRUNCATE;

			/* timestamp it */
			if ((entry.queuetime = time((time_t*)0L)) == ((time_t)-1))
				report (LOG_ERR, "clock is dead!"); 

			/* set rest of the lengths */
			entry.recipientlen = strlen(argv[optind + i]);
			entry.messagelen = strlen(msglist.messages[j]);
			entry.recipient2len = 0;

			/* queue it */
			if (AddMessageQueue(&entry, sender, argv[optind + i],
				&nullbyte, msglist.messages[j], &qfname)) {
				fprintf(stderr, "AddMessageQueue() failed\n");
				goto BeAClientout;
			}

			if (!(entry.status & STATUS_MSGTRUNCATE))
				printf("Entry queued for delivery\n");
			else
				break;

		} /* for j */
	} /* for i */

	err = EX_OK; /* good */

	/* signal the daemon to send now? */
	if (sendnow) {

		if ((FP = fopen(PATH_SENDPAGE_PIDFILE, "r"))) {
			fscanf(FP, "%u", &pid);
			fclose(FP);
		}

		/* only signal if there were recipients and pid is !0 */
		if (nrecipients && pid) 
			if (kill ((int)pid, SIGUSR1)) 
				fprintf(stderr, "Can't alert daemon pid (%u) to message\n",
					pid);

	} /* sendnow */

BeAClientout:

	for (i = 0; i < msglist.nmessages; ++i) 
		if (msglist.messages[i])
			free (msglist.messages[i]);
	free (msglist.messages);

	if (linebuf.buf)
		free (linebuf.buf);

	return err;

} /* BeAClient */

