/*
 *	Copyright 1990 by Rayan S. Zachariassen, all rights reserved.
 *	This will be free software, but only when it is finished.
 */

/*
 * Common routine to produce a diagnostic message for the scheduler to read
 */

#include <stdio.h>
#include "hostenv.h"
#include <sysexits.h>
#include <varargs.h>
#include "mail.h"
#include "ta.h"


extern char *strdup();

char *notarybuf = NULL;

char *
notaryacct(rc,okstr)
int rc;
char *okstr;
{
	static char msgbuf[20];
	switch (rc) {
	  case EX_OK:
	      return okstr; /* "delivered" or "relayed" ..  Depends.. */
	  case EX_TEMPFAIL:
	  case EX_IOERR:
	  case EX_OSERR:
	  case EX_CANTCREAT:
	  case EX_SOFTWARE:
	      return "delayed";
	  case EX_NOUSER:
	  case EX_NOHOST:
	  case EX_UNAVAILABLE:
	      return "failed";
	  case EX_NOPERM:
	  case EX_PROTOCOL:
	  case EX_USAGE:
	  default:
	      sprintf(msgbuf,"*SW-ERROR*rc=%d*",rc);
	      return msgbuf;
	}
}

/*VARARGS*/
void
notaryreport(va_alist) /* ( notaryargs[1,2,3] ) */
	va_dcl
{
	va_list ap;
	char *fmt = "%s\001%s\001%s";
	char *arg1, *arg2, *arg3;
	int len;
	static char *A1 = NULL, *A2 = NULL, *A3 = NULL;

	va_start(ap);
	arg1 = va_arg(ap, char *);
	arg2 = va_arg(ap, char *);
	arg3 = va_arg(ap, char *);
	va_end(ap);

	if (arg1) { if (A1) free(A1); A1 = strdup(arg1); }
	if (arg2) { if (A2) free(A2); A2 = strdup(arg2); }
	if (arg3) { if (A3) free(A3); A3 = strdup(arg3); }

	len = 22; /* "(null)\001(null)\001(null)" */
	if (A1) len += strlen(A1);
	if (A2) len += strlen(A2);
	if (A3) len += strlen(A3);

	if (!notarybuf)
	  notarybuf = (char*) emalloc(len);
	else
	  notarybuf = (char*) erealloc(notarybuf,len);
	sprintf(notarybuf,fmt,A1?A1:"",A2?A2:"",A3?A3:"");
}

/*VARARGS*/
void
diagnostic(va_alist) /* (rp, rc, "fmtstr", remotemsg) */
	va_dcl
{
	struct rcpt *rp;
	char	mark, message[8192];
	register char *cp, *s, *es, *s2;
	va_list	ap;

	va_start(ap);
	rp = va_arg(ap, struct rcpt *);		/* arg1: rp */
	rp->status = va_arg(ap, int);		/* arg2: rc */

	cp = va_arg(ap, char *);		/* arg3: fmtstr */
	es = &message[sizeof message - 2];
	for (s = message; cp != NULL && *cp != '\0'; ++cp) {
		if (s >= es)
			break;
		if (*cp != '%') {
			*s++ = *cp;
			continue;
		}
		switch (*++cp) {
		case 's':	/* string */
			for (s2 = va_arg(ap, char *); *s2 != 0; ++s2) {
				*s++ = *s2;
				if (s >= es)
					break;
			}
			break;
		case 'd':	/* integer */
			if (s >= es - 10)
				break;
			sprintf(s, "%d", va_arg(ap, int));
			while (*s != '\0') ++s;
			break;
		case '%':	/* percent */
			*s++ = '%';
			break;
		case '\0':
			--cp;	/* exit soonest */
			break;
		}
	}
	*s = '\0';
	va_end(ap);

	printf("%d/%ld\t%s\t",
	       rp->desc->ctlid, rp->id, notarybuf ? notarybuf : "");
	switch (rp->status) {
	case EX_OK:
		printf("ok");
		mark = _CFTAG_OK;
		break;
	case EX_TEMPFAIL:
	case EX_IOERR:
	case EX_OSERR:
	case EX_CANTCREAT:
	case EX_SOFTWARE:
		printf("deferred");
		mark = _CFTAG_DEFER;
		break;
	case EX_NOPERM:
	case EX_PROTOCOL:
	case EX_USAGE:
		strncat(message,
			" (this is abnormal, investigate!)", es - s);
		s += strlen(s);
		/* fall through */
	case EX_NOUSER:
	case EX_NOHOST:
	case EX_UNAVAILABLE:
		printf("error");
		mark = _CFTAG_NOTOK;
		break;
	default:
		printf("error Unknown sysexits error code %d!",
		       rp->status);
		mark = _CFTAG_NOTOK;
		break;
	}
	if (message[0] != '\0')
		printf(" %s", message);
	printf("\n");
	if (!lockaddr(rp->desc->ctlfd, rp->lockoffset, _CFTAG_LOCK, mark)) {
	  /* something went wrong in unlocking it, concurrency problem? */
	}
	rp->lockoffset = 0;	/* mark this recipient unlocked */
	fflush(stdout);
}
