/*
                BSMTP -- batch SMTP mails as BSMTP file

 	Genesis     : Mon Feb 24 13:29:33 1992
 	Last Change : Mon Feb 24 13:29:34 1992

	Developed and debugged with SAS/C Compiler V5.10a
	running under Kickstart 34.5, Workbench 34.20 and ARP 39.1
	on an european PAL-Amiga 2000 B Rev 4.3 with 3MB RAM.

	                        ___  _______
	Ralf S. Engelschall,    /__)(_  /_              rse@angle.muc.sub.org
	 Weblinger Weg 28,     / \____)(___           rse@cyvaned.muc.sub.org
	  8060 Dachau,        /
	   West Germany          ...!smurf.sub.org!brumuc!{angle,cyvaned}!rse
																			*/

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>

#include "sup.h"

#include "dos_lib.h"
#include "lbio_lib.h"
#include "str_lib.h"

#include "cus.h"
#include "defines.h"
#include "bsmtp.h"

#define SMTPROOTDIR "uumail:"
#define LSYSFILE "uulib:l.sys"
#define CONFIGFILE "uulib:config"
#define BATCHSIZE 49152
#define PREFIX "s"

static char *cpaFromFiles[RANGE_10BIT];
static char caFromFiles[RANGE_14BIT];
static char caTmp[1024];
static char caFrom[1024];
static char caTo[1024];
static char caNodename[50];
static char caDomainname[50];
static char caHostAddr[100];
static char caSmtpMailDir[RANGE_8BIT];

int main(int argc, char **argv)
{
	char opt;
	char *optarg;
	char *optstr;
	int optidx;

	char *cpSystem = NULL;

	char *cpSmtpRootDir = SMTPROOTDIR;
	FILE *fpFrom = NULL;
	FILE *fpTo = NULL;
	int nFromlen;
	int nFromFiles;
	char *cpFrombuf = NULL;

	int wTotalsize = 0;
	int wBatchsize = BATCHSIZE;
	int wCount = 0;
	BOOL fCompress = FALSE;

	int i;
	char *cpProgname = strlwr(argv[0]);
	int rc = DOSRC_SUCCESS;


	optidx = 1;
	optstr = "ms";
	for ( ; (optarg = argopt(argc, argv, optstr, &optidx, &opt)) != NULL; ) {
		switch(opt) {
			case 's':	wBatchsize = atoi(optarg);
						break;
			case 'c':	fCompress = TRUE;
						break;
			case 'v':	giveversioninfo(cpProgname);
						CU(DOSRC_SUCCESS);
			case '?':	giveusage(cpProgname);
						CU(DOSRC_SUCCESS);
		}
	}
	for ( ; optidx < argc; optidx++) {
		if (cpSystem == NULL) {
			cpSystem = argv[optidx];
		}
		else {
			conmsg(cpProgname, "too much arguments specified");
			giveusage(cpProgname);
			CU(DOSRC_FAIL);
		}
	}

	if (cpSystem == NULL) {
		conmsg(cpProgname, "missing system name");
		giveusage(cpProgname);
		CU(DOSRC_FAIL);
	}
	cpSystem = strlwr(cpSystem);
	if (!inlsys(LSYSFILE, cpSystem)) {
		conmsg(cpProgname, "sorry, system %s not in l.sys file %s", cpSystem, LSYSFILE);
		CU(DOSRC_FAIL);
	}

	if (wBatchsize < 2048)
		wBatchsize = 2048;

	if (getfield(CONFIGFILE, "NodeName", caNodename) == NULL) {
		conmsg(cpProgname, "cannot found Nodename in configfile %s", CONFIGFILE);
		CU(DOSRC_FAIL);
	}
	if (getfield(CONFIGFILE, "DomainName", caDomainname) == NULL) {
		conmsg(cpProgname, "cannot found Domainname in configfile %s", CONFIGFILE);
		CU(DOSRC_FAIL);
	}
	sprintf(caHostAddr, "%s%s", caNodename, caDomainname);

	sprintf(caSmtpMailDir, "%ssmtp.queue/%s/", cpSmtpRootDir, cpSystem);
	if (!exists(caSmtpMailDir)) {
		conmsg(cpProgname, "cannot found smtp mail dir %s", caSmtpMailDir);
		CU(DOSRC_FAIL);
	}
	if ((nFromFiles = getfnlst(caSmtpMailDir, caFromFiles, sizeof(caFromFiles), 1)) == -1) {
		conmsg(cpProgname, "cannot read filenames of smtp mail dir %s", caSmtpMailDir);
		CU(DOSRC_FAIL);
	}
	nFromFiles = strbplst(cpaFromFiles, sizeof(cpaFromFiles), caFromFiles);

	for (i = 1; i < nFromFiles; i++) {
		if (	strlen(cpaFromFiles[i]) != 5
			||	cpaFromFiles[i][0] != 'q'
			||	!isdigit(cpaFromFiles[i][1])
			||	!isdigit(cpaFromFiles[i][2])
			||	!isdigit(cpaFromFiles[i][3])
			||	!isdigit(cpaFromFiles[i][4])  )
			continue;

		sprintf(caFrom, "%s%s", caSmtpMailDir, cpaFromFiles[i]);

		if (!exists(caFrom)) {
			conmsg(cpProgname, "smtp mail '%s' cannot be batched because not found\n", caFrom);
			continue;
		}

		if ((fpFrom = fopen(caFrom, "r")) == NULL) {
			conmsg(cpProgname, "FAILED because cannot open smtp file '%s'\n", caFrom);
			CU(DOSRC_FAIL);
		}
		if (fseek(fpFrom, 0L, SEEK_END)) {
			conmsg(cpProgname, "FAILED because cannot seek to end of smtp mail %s\n", caFrom);
			CU(DOSRC_FAIL);
		}
		nFromlen = ftell(fpFrom);

		if ((cpFrombuf = (char *)malloc(nFromlen)) == NULL) {
			conmsg(cpProgname, "FAILED because not enough memory for %d byte smtp mail\n", nFromlen);
			CU(DOSRC_FAIL);
		}
		if (fseek(fpFrom, 0L, SEEK_SET)) {
			conmsg(cpProgname, "FAILED because cannot seek to begin of smtp mail %s\n", caFrom);
			CU(DOSRC_FAIL);
		}
		fread(cpFrombuf, nFromlen, 1, fpFrom);
		fclose(fpFrom);
		remove(caFrom);

		if ( (wTotalsize + nFromlen) > wBatchsize ||
			 ((wTotalsize == 0) && (nFromlen > wBatchsize))	) {
			if (fpTo) {
				fprintf(fpTo, "QUIT\n");
				fclose(fpTo);
				if (fCompress) {
					sprintf(caTmp, "compress %s", caTo);
					if (exec(caTmp) != 0)
						CU(DOSRC_FAIL);
					sprintf(caTmp, "uux %s.Z \"%s!rcsmtp\"", caTo, cpSystem);
					if (exec(caTmp) != 0)
						CU(DOSRC_FAIL);
					sprintf(caTmp, "%s.Z", caTo);
					remove(caTmp);
				}
				else {
					sprintf(caTmp, "uux %s \"%s!rsmtp\"", caTo, cpSystem);
					if (exec(caTmp) != 0)
						CU(DOSRC_FAIL);
					remove(caTo);
				}
			}
			wTotalsize = 0;
			fpTo = NULL;
		}
		if (fpTo == NULL) {
			sprintf(caTo, "%s%s%04d", caSmtpMailDir, PREFIX, ++wCount);
			if ((fpTo = fopen(caTo, "w")) == NULL) {
				conmsg(cpProgname, "FAILED because cannot open output %s\n", caTo);
				CU(DOSRC_FAIL);
			}
			fprintf(fpTo, "HELO %s\n", caHostAddr);
		}

		fwrite(cpFrombuf, nFromlen, 1, fpTo);
		wTotalsize += (i + nFromlen);
		free(cpFrombuf);
		cpFrombuf = NULL;
	}

	if (fpTo) {
		fprintf(fpTo, "QUIT\n");
		fclose(fpTo);
		fpTo = NULL;
		if (fCompress) {
			sprintf(caTmp, "compress %s", caTo);
			if (exec(caTmp) != 0)
				CU(DOSRC_FAIL);
			sprintf(caTmp, "uux %s.Z \"%s!rcsmtp\"", caTo, cpSystem);
			if (exec(caTmp) != 0)
				CU(DOSRC_FAIL);
			sprintf(caTmp, "%s.Z", caTo);
			remove(caTmp);
		}
		else {
			sprintf(caTmp, "uux %s \"%s!rsmtp\"", caTo, cpSystem);
			if (exec(caTmp) != 0)
				CU(DOSRC_FAIL);
			remove(caTo);
		}
	}


	CUS:
	if (cpFrombuf)
		free(cpFrombuf);
	if (fpTo)
		fclose(fpTo);
	if (fpFrom)
		fclose(fpFrom);
	return rc;
}

