Metropoli BBS
VIEWER: emsi.c MODE: TEXT (ASCII)
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                                                                          */
/*      ------------         Bit-Bucket Software, Co.                       */
/*      \ 10001101 /         Writers and Distributors of                    */
/*       \ 011110 /          Freely Available<tm> Software.                 */
/*        \ 1011 /                                                          */
/*         ------                                                           */
/*                                                                          */
/*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
/*                                                                          */
/*              This module was written by Tobias Burchhardt                */
/*                                                                          */
/*                   BinkleyTerm EMSI-Handshake Processor                   */
/*                                                                          */
/*                                                                          */
/*    For complete  details  of the licensing restrictions, please refer    */
/*    to the License  agreement,  which  is published in its entirety in    */
/*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
/*                                                                          */
/*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
/*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
/*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
/*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
/*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
/*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
/*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
/*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
/*                                                                          */
/*                                                                          */
/* You can contact Bit Bucket Software Co. at any one of the following      */
/* addresses:                                                               */
/*                                                                          */
/* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
/* P.O. Box 460398                AlterNet 7:42/1491                        */
/* Aurora, CO 80046               BBS-Net  86:2030/1                        */
/*                                Internet f491.n343.z1.fidonet.org         */
/*                                                                          */
/* Please feel free to contact us at any time to share your comments about  */
/* our software and/or licensing policies.                                  */
/*                                                                          */
/*--------------------------------------------------------------------------*/

/* Include this file before any other includes or defines! */

#include "includes.h"

static int LOCALFUNC Send_EMSI_Packet (int);
static int LOCALFUNC Recv_EMSI_Packet (int);
static int LOCALFUNC get_emsi (char *);
static char *LOCALFUNC b7strcat (char *, char *);
static int LOCALFUNC recode_from_b7 (char *, int);
static int LOCALFUNC match_aka (ADDRP);
static char *LOCALFUNC get_bracket (char *);
static char *LOCALFUNC cat_bracket (char *, char *);
static int LOCALFUNC get_level (ADDRP addr, ADDRP myaka);
static int LOCALFUNC Encode_EMSI_Header (char *, int);
static int LOCALFUNC Decode_EMSI_Header (char *, int, int);

static int highest_level, hl_aka;	/* Used for passwording */

/*--------------------------------------------------------------------------*/
/* EMSI SENDER    (used when I am the CALLING system)                       */
/*--------------------------------------------------------------------------*/

int 
EMSI_Sender (void)
{
	char *sptr;

	highest_level = hl_aka = num_rakas = 0;
	sptr = NULL;

	if (un_attended && fullscreen)
	{
		sb_move (filewin, 2, 2);
		sb_puts (filewin, MSG_TXT (M_EMXMIT));
		sb_show ();
	}
	else
	{
		set_xy (MSG_TXT (M_EMSEND));
	}

	/*--------------------------------------------------------------------*/
	/* Clean up any mess that may be around                               */
	/*--------------------------------------------------------------------*/
	CLEAR_INBOUND ();
	XON_DISABLE ();

	if (!Send_EMSI_Packet (1))
	{
		sptr = MSG_TXT (M_HE_HUNG_UP);
		status_line (sptr);
		return (0);
	}

	if (un_attended && fullscreen)
	{
		sb_move (filewin, 2, 2);
		sb_puts (filewin, MSG_TXT (M_EMWAIT));
		sb_show ();
	}
	else
	{
		set_xy (MSG_TXT (M_EMRECV));
	}

	return Recv_EMSI_Packet (1);
}

/*--------------------------------------------------------------------------*/
/* EMSI RECEIVER  (Used when I am the CALLED system)                        */
/*--------------------------------------------------------------------------*/

int 
EMSI_Receiver (void)
{
	int i;

	highest_level = hl_aka = num_rakas = 0;
	if (un_attended && fullscreen)
	{
		sb_move (filewin, 2, 2);
		sb_puts (filewin, MSG_TXT (M_EMWAIT));
		sb_show ();
	}
	else
	{
		set_xy (MSG_TXT (M_EMRECV));
	}

	/*--------------------------------------------------------------------*/
	/* Clean up any mess that may be around                               */
	/*--------------------------------------------------------------------*/
	CLEAR_OUTBOUND ();
	XON_DISABLE ();

	if (Recv_EMSI_Packet (0) == 0)
		return (0);

	if (un_attended && fullscreen)
	{
		sb_move (filewin, 2, 2);
		sb_puts (filewin, MSG_TXT (M_EMXMIT));
		sb_show ();
	}
	else
	{
		set_xy (MSG_TXT (M_EMSEND));
	}

	if ((i = Send_EMSI_Packet (0)) == 0)
		b_init ();
	return (i);
}								/* EMSI Receiver */

/*--------------------------------------------------------------------------*/
/* SEND EMSI PACKET                                                         */
/*--------------------------------------------------------------------------*/

static int LOCALFUNC 
Send_EMSI_Packet (int Sender)
{
	int i;
	char *sptr;
	long T1, T2;
	word crc, len;
	word tries = 0;
	char *junkbuff, *uni;

/*
 * Txbuf is (8192+16) in length
 * junkbuff wants to be 4096
 * uni wants to be 256
 * We reserve the last 1024+16 for lower level functions
 *
 * If you change this way of doing things, you have to change
 * Encode_EMSI_Header as well!!!
 */

	junkbuff = (char *) Txbuf;
	uni = &junkbuff[4096];

	/*--------------------------------------------------------------------*/
	/* Setup EMSI structure                                               */
	/*--------------------------------------------------------------------*/
	len = Encode_EMSI_Header (junkbuff, Sender);

	/*--------------------------------------------------------------------*/
	/* Disable handshaking and ^C/^K handling                             */
	/*--------------------------------------------------------------------*/
	XON_DISABLE ();

	/*--------------------------------------------------------------------*/
	/* Send the packet.                                                   */
	/* Load outbound buffer quickly, and get modem busy sending.          */
	/*--------------------------------------------------------------------*/

	tries = 0;
	T1 = timerset (6000);

xmit_packet:

	sprintf (uni, "%s%04X", &(emsistr[EMSI_DAT][2]), len);
	crc = crc_block ((unsigned char *) uni, strlen (uni));
	SENDCHARS ("**", 2, 1);
	SENDCHARS (uni, strlen (uni), 1);
	SENDCHARS (junkbuff, len, 1);

	/*--------------------------------------------------------------------*/
	/* Calculate CRC while modem is sending its buffer                    */
	/*--------------------------------------------------------------------*/
	for (i = 0; i < (int) len; i++)
		crc = xcrc (crc, junkbuff[i]);

	CLEAR_INBOUND ();
	sprintf (uni, "%04X\r", crc);
	SENDCHARS (uni, strlen (uni), 1);
	if (tries++ > 6)
	{
		(void) sprintf (uni, "!%s", MSG_TXT (M_TIMEOUT));
		sptr = uni;
		goto no_response;
	}

	/* wait_response: */

	T2 = timerset (2000);

	while (!timeup (T1) && CARRIER)
	{
		if (timeup (T2))
			goto xmit_packet;

		if (!CHAR_AVAIL ())
		{
			if (got_ESC ())
			{
				LOWER_DTR ();
				sptr = MSG_TXT (M_KBD_MSG);
				goto no_response;
			}
			time_release ();
			continue;
		}

		switch (i = TIMED_READ (0))
		{
		case '*':
			strcpy (uni, "*");
			if (!get_emsi (uni))
				break;
			if (!stricmp (uni, emsistr[EMSI_REQ]))
				continue;
			if (!stricmp (uni, emsistr[EMSI_ACK]))
				return (1);
			goto xmit_packet;

		default:
			if (i <= 0)			/* MB *//* Could just be line noise if > 0*/
				time_release ();/*PLF Sun  12-01-1991  04:21:14 */
			break;
		}
	}

	if (!CARRIER)
		sptr = MSG_TXT (M_NO_CARRIER);
	else
	{
		(void) sprintf (uni, "!%s", MSG_TXT (M_TIMEOUT));
		sptr = uni;
	}

no_response:

	status_line (sptr);
	return (0);

}								/* Send EMSI */

/*--------------------------------------------------------------------------*/
/* RECEIVE EMSI PACKET                                                      */
/*--------------------------------------------------------------------------*/

static int LOCALFUNC 
Recv_EMSI_Packet (int Sender)
{
	int i;
	int c;
	int len;
	char *sptr;
	byte tries = 0;
	word crc, crc2;
	long T1, T2, T3;
	char *junkbuff, *uni, *help;

/*
 * Txbuf is (8192+16) in length
 * junkbuff wants to be 4096
 * uni wants to be 256
 * help wants to be 256
 * tmpstr wants to be 256
 * We reserve the last 1024+16 for lower level functions
 *
 * If you change this way of doing things, you have to change
 * Decode_EMSI_Header as well!!!
 */

	junkbuff = (char *) Txbuf;
	uni = &junkbuff[4096];
	help = &uni[256];
	/* tmpstr = &help[256]; */

	/* strcpy (remote_sysop, "Sysop"); */
	remote_password = NULL;

	/*--------------------------------------------------------------------*/
	/* Get the EMSI structure                                             */
	/*--------------------------------------------------------------------*/

	if (un_attended && fullscreen)
	{
		sb_move (filewin, 2, 2);
		sb_puts (filewin, MSG_TXT (M_EMWAIT));
		sb_show ();
	}
	else
	{
		set_xy (MSG_TXT (M_EMRECV));
	}

	remote_pickup = 2;			/* Pickup for all akas */
	T1 = timerset (2000);
	T2 = timerset (6000);
	sptr = NULL;

request_it:

	if (tries++ > 6)
		goto timeout;

	if (!Sender)
	{
		sprintf (uni, "%s\r", emsistr[EMSI_REQ]);	/* EMSI_REQ if he called me  */
	}
	else if (tries > 1)
	{
		sprintf (uni, "%s\r", emsistr[EMSI_NAK]);	/* EMSI_NAK anytime after 1st*/
	}
	else
		goto watch_for_header;

	SENDCHARS (uni, strlen (uni), 1);	/* Kick the other guy.       */

new_timer:

	T1 = timerset (2000);

watch_for_header:

	while (!timeup (T2) && CARRIER)
	{
		if (sptr)
		{
			status_line (sptr);
			sptr = NULL;
		}

		if (timeup (T1))
			goto request_it;

		if (!CHAR_AVAIL ())
		{
			if (got_ESC ())
			{
				LOWER_DTR ();
				sptr = MSG_TXT (M_KBD_MSG);
				goto receive_failed;
			}
			time_release ();
			continue;
		}

		switch (i = TIMED_READ (0))
		{
		case '*':
			strcpy (uni, "*");
			if (!get_emsi (uni))
				break;
			if (!stricmp (uni, emsistr[EMSI_HBT]))
				goto new_timer;
			if (!stricmp (uni, emsistr[EMSI_DAT]))
				goto receive_packet;
			break;

		default:
			if (i <= 0)			/* MB *//* Could just be line noise if > 0 */
				time_release ();/*PLF Sun  12-01-1991  04:21:14 */
			break;
		}
	}

	if (timeup (T2))
		goto timeout;

	if (!CARRIER)
	{
		sptr = MSG_TXT (M_NO_CARRIER);
		goto receive_failed;
	}

receive_packet:

	if (un_attended && fullscreen)
	{
		sb_move (filewin, 2, 2);
		sb_puts (filewin, MSG_TXT (M_EMRCPT));
		sb_show ();
	}
	T3 = timerset (6000);
	if (((int) (uni[0] = (char) TIMED_READ (3)) < 0) ||
		((int) (uni[1] = (char) TIMED_READ (3)) < 0) ||
		((int) (uni[2] = (char) TIMED_READ (3)) < 0) ||
		((int) (uni[3] = (char) TIMED_READ (3)) < 0))
	{
		sptr = MSG_TXT (M_EMSHORT);
		goto emsi_error;
	}

	if (!CARRIER)
	{
		sptr = MSG_TXT (M_NO_CARRIER);
		goto receive_failed;
	}
	uni[4] = '\0';
	sscanf (uni, "%x", &len);
	sprintf (help, "%s%s", &(emsistr[EMSI_DAT][2]), uni);
	crc = crc_block ((unsigned char *) help, strlen (help));
	sptr = junkbuff;
	memset (junkbuff, 0, 4096);

	for (i = 0; i < len; i++)
	{
		while (PEEKBYTE () < 0)
		{
			if (timeup (T2) || timeup (T3))
				goto timeout;

			if (got_ESC ())
			{
				sptr = MSG_TXT (M_KBD_MSG);
				goto receive_failed;
			}

			if (!CARRIER)
			{
				sptr = MSG_TXT (M_NO_CARRIER);
				goto receive_failed;
			}

			time_release ();
		}

		c = TIMED_READ (0);
		*sptr++ = (char) c;
		crc = xcrc (crc, (byte) c);
	}

	if (((int) (uni[0] = (char) TIMED_READ (3)) < 0) ||
		((int) (uni[1] = (char) TIMED_READ (3)) < 0) ||
		((int) (uni[2] = (char) TIMED_READ (3)) < 0) ||
		((int) (uni[3] = (char) TIMED_READ (3)) < 0))
	{
		sptr = MSG_TXT (M_EMSHORT);
		goto emsi_error;
	}

	TIMED_READ (1);				/* What am I throwing away here? */

	if (!CARRIER)
	{
		sptr = MSG_TXT (M_NO_CARRIER);
		goto receive_failed;
	}

	uni[4] = '\0';
	sscanf (uni, "%hx", &crc2);
	if (crc == crc2)
		goto process_packet;

	(void) sprintf (junkbuff, "!%s", MSG_TXT (M_CRC_MSG));
	sptr = junkbuff;

emsi_error:

	if (timeup (T2))
		goto timeout;

	CLEAR_INBOUND ();
	goto request_it;

process_packet:

	if (strnicmp (junkbuff, "{EMSI}", 6))
	{
		sptr = MSG_TXT (M_EMSTART);
		goto emsi_error;
	}

	if (!Decode_EMSI_Header (junkbuff, len, Sender))
		goto receive_failed;

	(void) n_getpassword (&remote_akas[hl_aka]);	/* Updated 'assumed', 'CURRENT' to match remote */

	CLEAR_INBOUND ();
	CLEAR_OUTBOUND ();

	sprintf (uni, "%s\r", emsistr[EMSI_ACK]);
	SENDCHARS (uni, strlen (uni), 1);	/* Let the other system know */
	SENDCHARS (uni, strlen (uni), 1);	/* we got it !               */
	T3 = timerset (1000);
	while (!OUT_EMPTY ())		/* Flush the buffer          */
	{
		if (timeup (T3))
			goto timeout;
		if (!CARRIER)
			goto receive_failed;
		time_release ();
	}

	return (1);

timeout:

	(void) sprintf (uni, "!%s", MSG_TXT (M_TIMEOUT));
	sptr = uni;

receive_failed:

	status_line (sptr);
	b_init ();
	return (0);
}								/* Recv EMSI */

static int LOCALFUNC 
get_emsi (char *s)
{
	long T1;
	char *sptr, c;
	int i;

	T1 = timerset (500);
	sptr = s + 1;
	memset (sptr, 0, EMSI_LEN + 1);
	while (CARRIER)
	{
		while (PEEKBYTE () < 0)
		{
			if (timeup (T1))
				goto timeout;

			if (got_ESC ())
			{
				status_line (MSG_TXT (M_KBD_MSG));
				goto receive_failed;
			}

			if (!CARRIER)
			{
				status_line (MSG_TXT (M_NO_CARRIER));
				goto receive_failed;
			}

			time_release ();
		}

		c = (char) TIMED_READ (0);
		if (c == '\r')
		{
			status_line (">EMSI: '%s'", s);
			return (1);
		}
		*sptr++ = (char) c;
		for (i = 0; i < EMSI_MAX; i++)
		{
			if (!strnicmp (s, emsistr[i], strlen (emsistr[i])))
			{
				status_line (">EMSI: '%s'", s);
				return (1);
			}
			else
			{
				if ((int) strlen (s) > EMSI_LEN)
				{
					status_line (">EMSI: '%s'", s);
					return (1);
				}
			}
		}
	}
timeout:

	status_line ("!%s", MSG_TXT (M_TIMEOUT));

receive_failed:

	return (0);
}

static char *LOCALFUNC 
b7strcat (char *d, char *s)
{
	int i;
	int j = strlen (s);
	char uni[4], *p, *c;

	p = &d[strlen (d)];
	c = s;
	for (i = 0; i < j; c++, i++)
	{
		if (*c == '\\')
		{
			*p++ = '\\';
			*p++ = '\\';
			continue;
		}

		/*old if((*c>=0)&&(*c<=0x7F)) */

		if (!(*c & 0x80))
		{
			*p++ = *c;
			continue;
		}
		*p++ = '\\';			/* Do coding only for 8 bit chars */
		sprintf (uni, "%02X", (unsigned) *c);
		*p++ = uni[0];
		*p++ = uni[1];
		continue;
	}
	*p++ = '\0';
	return (d);
}

static LOCALFUNC 
recode_from_b7 (char *s, int len)
{
	int i, j;
	char *d, uni[4];
	unsigned c;

	d = s;
	for (j = i = 0; i < len; j++)
	{
		if (*s != '\\')
		{
			*d++ = *s++;
			i++;
			continue;
		}
		if (*++s == '\\')
		{
			*d++ = *s++;
			i += 2;
			continue;
		}
		uni[0] = *s++;
		uni[1] = *s++;
		uni[2] = '\0';
		sscanf (uni, "%hx", &c);
		*d++ = (char) c;
		i += 3;
	}
	*d++ = '\0';
	return (j);					/* New length */
}

static int LOCALFUNC 
get_level (ADDRP addr, ADDRP myaka)
{
	int level = -1;

	if ((addr->Domain == myaka->Domain) || !addr->Domain || !myaka->Domain)
		level++;
	else
		return (level);

	if (addr->Zone == myaka->Zone)
		level++;
	else
		return (level);

	if (addr->Net == myaka->Net)
		level++;
	else
		return (level);

	if (addr->Node == myaka->Node)
		level++;
	return (level);
}

static int LOCALFUNC 
match_aka (ADDRP addr)
{
	int level = -1;
	int i, j;

	assumed = 0;
	for (i = 0; i < num_addrs; i++)
	{
		j = get_level (addr, &alias[i]);
		if (j > level)
		{
			assumed = i;
			level = j;
		}
	}
	return (0);
}

/*--------------------------------------------------------------------------*/
/* Find end of EMSI field                                                   */
/*--------------------------------------------------------------------------*/

static char *LOCALFUNC 
get_bracket (char *p)
{
	register char c;
	register char x = *(p - 1);	/* Save starting character */
	char *q = p;

	/* Convert starting bracket to expected ending bracket */

	if (x == '{')
		x = '}';
	else if (x == '[')
		x = ']';

	while ((c = *p++) != '\0')
	{
		/* If this is an ending bracket */

		if (c == '}' || c == ']')
		{
			/* And it's not escaped */

			if (*p != c)
			{
				/* And it's the right one, get out. */

				if (c == x)
					break;
			}
			else
			{
				/* If it is escaped, copy the end of the string over the esc */

				strcpy (q, p);
			}
		}
		q = p;
	}
	return (q);
}

static char *LOCALFUNC 
cat_bracket (char *d, char *c)		/* MB 93-11-27 */
{
	char x, *p, *q;
	q = p = (char *) &Txbuf[7168];

	while ((x = *c++) != '\0')
	{
		if (*c && (x == '}' || x == ']'))
			*p++ = x;	/* We have to escape } or ] by doing it twice */
		*p++ = x;
	}
	*p++ = '\0';
	return (b7strcat (d, q));
}

static int LOCALFUNC 
Decode_EMSI_Header (char *junkbuff, int len, int Sender)
{
	int i, akacnt = 0;
	int prodcodeT, logit = TRUE;
	int j, addonnr;
	long lmoh = 0;
	int cur = 0;
	char *tmpstr, *sptr, *p;
	char *uni, *help, *name, *loc, password[16];
	ADDR addr[ALIAS_CNT], remote;
	static char *addons[] = {"{IDENT}", "{TRX#}", "{MOH#}", NULL};

	uni = &junkbuff[4096];		/* Look at Recv_EMSI_Packet to see */
	help = &uni[256];			/* why this is OK                  */
	tmpstr = &help[256];

	recode_from_b7 (junkbuff, len);
	sptr = &junkbuff[7];
	memset (&remote_addr, 0, sizeof (remote_addr));
	akacnt = i = 0;
	while (*sptr != '}')
	{
		while (*sptr == ' ')
			sptr++;

		/* Copy the address string into temp string. */

		p = tmpstr;
		while (*sptr && *sptr != '}' && *sptr != ' ')
			*p++ = *sptr++;
		*p = '\0';
		if (p == tmpstr)
			break;
		memset (&addr[i], 0, sizeof (ADDR));
		status_line (">EMSI: parsing addr: '%s'", tmpstr);
		(void) find_address (tmpstr, &addr[i]);
		status_line (">EMSI: got addr: '%s'", Full_Addr_Str (&addr[i]));
		/*    sscanf(sptr,"%u:%u/%u.%u",&addr[i].Zone,&addr[i].Net,&addr[i].Node,&addr[i].Point); */
		if (Sender && (addr[i].Zone == called_addr.Zone) && (addr[i].Net == called_addr.Net) && (addr[i].Node == called_addr.Node) && (addr[i].Point == called_addr.Point))
			remote_addr = addr[i];
		if (i < (ALIAS_CNT - 1))
			i++;
	}
	akacnt = i;
	if (!remote_addr.Zone || !remote_addr.Net)
		remote_addr = addr[0];

	while (*sptr++ != '{')
		;
	i = 0;
	while (*sptr != '}')
		password[i++] = *sptr++;
	password[i] = '\0';
	sptr++;
	while (*sptr != '}')
	{
		i = 0;
		while ((*sptr != ',') && (*sptr != '}'))
			uni[i++] = *sptr++;
		uni[i] = '\0';
		if (*sptr != '}')
			sptr++;
		if (!stricmp (uni, "NPU"))
			remote_pickup = 0;
		else if (!stricmp (uni, "PUP"))
			remote_pickup = 1;
		else if (!stricmp (uni, "PUA"))
			remote_pickup = 2;
	}
	sptr++;
	sptr++;
	remote_capabilities = WZ_FREQ;
	while (*sptr != '}')
	{
		i = 0;
		while ((*sptr != ',') && (*sptr != '}'))
			uni[i++] = *sptr++;
		uni[i] = '\0';
		if (*sptr != '}')
			sptr++;
		if (!stricmp (uni, "JAN"))
			remote_capabilities |= DOES_IANUS;
#ifdef HAVE_HYDRA
		else if (!stricmp (uni, "HYD"))
			remote_capabilities |= DOES_HYDRA;
#endif	/* HAVE_HYDRA */
		else if (!stricmp (uni, "ZAP"))
			remote_capabilities |= ZED_ZAPPER;
		else if (!stricmp (uni, "ZMO"))
			remote_capabilities |= ZED_ZIPPER;
		else if (!stricmp (uni, "NRQ"))
			remote_capabilities &= ~WZ_FREQ;
	}
	sptr++;
	sptr++;
	sscanf (sptr, "%x", &prodcodeT);
	/*   remote_mailer=prodcode; */
	while (*sptr++ != '{')
		;
	i = 0;
	while (*sptr != '}')
		uni[i++] = *sptr++;
	sptr++;
	sptr++;
	uni[i++] = ' ';
	while (*sptr != '}')
		uni[i++] = *sptr++;
	sptr++;
	sptr++;
	uni[i++] = '/';
	while (*sptr != '}')
		uni[i++] = *sptr++;
	if (uni[--i] != '/')
		i++;
	uni[i] = '\0';
	sptr++;
	for (;;)
	{
		if (*sptr != '{')
			break;

		for (addonnr = 0; addons[addonnr] != NULL; addonnr++)
		{
			if (!strnicmp (sptr, addons[addonnr], strlen (addons[addonnr])))
				break;
		}

		if (!addons[addonnr])	/* no known addon */
			addonnr = 0;
		else
			addonnr++;

		switch (addonnr)
		{
		case 1:				/* {IDENT} system name */
			sptr += 9;
			name = sptr;
			sptr = get_bracket (sptr);
			*sptr = '\0';

			(void) sprintf (help, "*%s (%s)", name, Full_Addr_Str (&remote_addr));
			status_line ("%s", help);
			if (akacnt > 1)
			{
				strcpy (help, ":Aka: ");
				for (j = i = 0; i < akacnt; i++)
				{
					if (!memcmp (&addr[i], &remote_addr, sizeof (ADDR)))
						continue;
					strcat (help, Full_Addr_Str (&addr[i]));
					strcat (help, " ");
					if (++j == 3)
					{
						status_line ("%s", help);
						strcpy (help, ":     ");
						j = 0;
					}
				}
				if (j)
					status_line ("%s", help);
			}
			sptr += 2;
			status_line ("%s %s", MSG_TXT (M_REMOTE_USES), uni);
			loc = sptr;
			sptr = get_bracket (sptr);
			*sptr = '\0';
			*uni = '\0';
			if (loc[0])
				sprintf (uni, " from %s", loc);
			sptr += 2;
			name = sptr;
			sptr = get_bracket (sptr);
			*sptr = '\0';
			if (name[0])
			{
				status_line (":SysOp: %s%s", name, uni);
				/*             strcpy (remote_sysop,name);  */
			}

			sptr += 2;			/* phone */
			name = sptr;
			sptr = get_bracket (sptr);
			*sptr = '\0';
			sptr += 2;

			sptr = get_bracket (sptr);	/* baud */
			*sptr = '\0';

			sptr += 2;			/* flags */
			loc = sptr;
			sptr = get_bracket (sptr);
			*sptr = '\0';
			if (loc[0] && name[0] && strcmp (name, "-Unpublished-"))
			{
				status_line (" Phone: %s", name);
				status_line (" Flags: %s", loc);
			}
			while (*sptr++ != '}')
				;
			break;

		case 2:				/* {TRX#}  tranx */
			sptr += 8;
			name = sptr;
			sptr = get_bracket (sptr);
			*sptr = '\0';
#ifdef ANSI_TIME_T
			status_line (":Tranx: %08lX / %s", etm - ANSI_TIME_T_DELTA, name);
#else
			status_line (":Tranx: %08lX / %s", etm, name);
#endif
			while (*sptr++ != '}')
				;
			break;

		case 3:				/* {MOH#}  mail on hold */
			sptr += 8;
			name = sptr;
			sptr = get_bracket (sptr);
			*sptr = '\0';
			sscanf (name, "%lX", &lmoh);
			status_line (">Mail on Hold: %ldb", lmoh);
			while (*sptr++ != '}')
				;
			break;

		default:				/* any other addon */
			name = ++sptr;
			while (*sptr != '}')
				sptr++;			/* goto end of addon  string */
			*sptr++ = '\0';
			loc = ++sptr;
			sptr = get_bracket (sptr);	/* MB  new  */
			*sptr++ = '\0';
			status_line (">Unknown EMSI Addon: %s: {%s}", name, loc);
			break;
		}
	}
	remote = remote_addr;
	if (!remote_pickup)
		status_line (" Remote refused mail-pickup");
	if (Sender)
		remote_addr = called_addr;
	CURRENT = DEFAULT;

	for (i = 0; i <= akacnt; i++)
	{
		status_line (">EMSI: checking addr: '%s'", Full_Addr_Str (&remote_addr));
		if ((j = n_getpassword (&remote_addr)) > 0)
		{
			if (Sender && *remote_password && !*password && (prodcodeT == isDBRIDGE))
				j = 0;			/* work-around for a D'Bridge(tm)-Bug */
			else
				j = n_password (password, remote_password, &logit);

			status_line (">EMSI: result of pw check: '%d'", j);

			if (j == 0)
			{
				if (highest_level < 2)
				{
					highest_level = 2;
					hl_aka = num_rakas;
				}
			}
			else
			{
		 /*
          * Password doesn't match.
          *
          * Result of 1 means both of us had one.
          *
          * Result of 2 means we had one and the other side didn't.
          *
          * If we are the sender we will accept this mismatch,
          * but only on the first aka.
          *
          */
				if ((!Sender) || (num_rakas != 0))
					goto next_one;
				else
					status_line (MSG_TXT (M_PASSWORD_OVERRIDE));

				if (highest_level < 1)
				{
					highest_level = 1;
					hl_aka = num_rakas;
				}
			}
		}
		else if (j < 0)
		{
			status_line (">EMSI: addr '%s' will be curmudgeoned", Full_Addr_Str (&remote_addr));
			cur = 1;
			goto next_one;
		}

		status_line (">EMSI: checking addr '%s' for dupe", Full_Addr_Str (&remote_addr));
		for (j = 0; j < num_rakas; j++)
		{
			if (get_level (&remote_addr, &(remote_akas[j])) == 3)
				goto next_one;
		}

		status_line (">EMSI: using addr: '%s'", Full_Addr_Str (&remote_addr));
		remote_akas[num_rakas++] = remote_addr;

next_one:

		remote_addr = addr[i];
	}
	if (!num_rakas)
	{
		if (cur)
			sptr = MSG_TXT (M_NUISANCE_CALLER);
		else
			sptr = NULL;

		LOWER_DTR ();			/* He'll never get it right */
		timer (2);				/* Wait two secs */
		return (0);
	}

	remote_addr = remote;

	return (1);
}

static int LOCALFUNC 
Encode_EMSI_Header (char *junkbuff, int Sender)
{
	int i, capabilities = 0;
	char *uni;

	uni = &junkbuff[4096];		/* See why this is OK in Send_EMSI_Packet */

	strcpy (junkbuff, "{EMSI}");
	b7strcat (junkbuff, "{");
	match_aka (&remote_addr);	/* Update 'assumed' */
	status_line (">Used Aka: %s", Full_Addr_Str (&alias[assumed]));

	b7strcat (junkbuff, Full_Addr_Str (&alias[assumed]));
	for (i = 0; i < num_addrs; i++)
	{
		if (i != assumed)
		{
			b7strcat (junkbuff, " ");
			b7strcat (junkbuff, Full_Addr_Str (&alias[i]));
		}
	}

	b7strcat (junkbuff, "}{");
	remote_password = NULL;
	if ((Sender && (n_getpassword (&remote_addr) > 0)) ||
		(!Sender && (n_getpassword (&remote_akas[hl_aka]) > 0)))
	{
		if (remote_password)
		{
			(void) strncpy ((char *) uni, remote_password, 8);
			uni[8] = '\0';
			b7strcat (junkbuff, uni);
		}
	}
	b7strcat (junkbuff, "}{8N1");
	if (Sender)
	{
		if (!no_pickup)
		{
			if (pickup_all)
				b7strcat (junkbuff, ",PUA");
			else
				b7strcat (junkbuff, ",PUP");
		}
		else
			b7strcat (junkbuff, ",NPU");
	}
	else
	{
		if (matrix_mask & NO_TRAFFIC)
			b7strcat (junkbuff, ",HAT");
		if (!(matrix_mask & TAKE_REQ))
			b7strcat (junkbuff, ",HRQ");
	}
	b7strcat (junkbuff, "}{");

	/* At least one ZModem protocol must be available for FSC-0056 ! */

	if (!my_capabilities & ZED_ZIPPER)
		my_capabilities |= ZED_ZIPPER;

/*
 * If we are the calling system, turn on all our capabilities.
 * If we are the called system, choose from the set that the
 * caller gave us, and only send the one we prefer.
 */
	if (!Sender)
	{
		if (remote_capabilities & my_capabilities & DOES_IANUS)
			capabilities = DOES_IANUS;
#ifdef HAVE_HYDRA
		else if (remote_capabilities & my_capabilities & DOES_HYDRA)
			capabilities = DOES_HYDRA;
#endif	/* HAVE_HYDRA */
		else if (remote_capabilities & my_capabilities & ZED_ZAPPER)
			capabilities = ZED_ZAPPER;
		else if (remote_capabilities & my_capabilities & ZED_ZIPPER)
			capabilities = ZED_ZIPPER;
	}
	else
		capabilities = my_capabilities;

#ifdef HAVE_HYDRA
	if (!capabilities & (DOES_IANUS | DOES_HYDRA | ZED_ZAPPER | ZED_ZIPPER))
#else
	if (!capabilities & (DOES_IANUS | ZED_ZAPPER | ZED_ZIPPER))
#endif	/* HAVE_HYDRA */
		b7strcat (junkbuff, "NCP,");
	else if (Sender)
	{
		if (capabilities & DOES_IANUS)
			b7strcat (junkbuff, "JAN,");
#ifdef HAVE_HYDRA
		if (capabilities & DOES_HYDRA)
			b7strcat (junkbuff, "HYD,");
#endif	/* HAVE_HYDRA */
		if (capabilities & ZED_ZAPPER)
			b7strcat (junkbuff, "ZAP,");
		if (capabilities & ZED_ZIPPER)
			b7strcat (junkbuff, "ZMO,");
	}
	else
	{
		if (capabilities & DOES_IANUS)
			b7strcat (junkbuff, "JAN,");
#ifdef HAVE_HYDRA
		else if (capabilities & DOES_HYDRA)
			b7strcat (junkbuff, "HYD,");
#endif	/* HAVE_HYDRA */
		else if (capabilities & ZED_ZAPPER)
			b7strcat (junkbuff, "ZAP,");
		else if (capabilities & ZED_ZIPPER)
			b7strcat (junkbuff, "ZMO,");
	}
	if (!(matrix_mask & TAKE_REQ) || (Sender && !on_our_nickel))
	{
		b7strcat (junkbuff, "NRQ,");
	}
	else
		capabilities |= WZ_FREQ;

	b7strcat (junkbuff, "ARC,XMA");
	b7strcat (junkbuff, ",FNC");
	b7strcat (junkbuff, "}");					/* MB 93-11-27 */
	sprintf (uni, "{%02X}", PRDCT_CODE);
	b7strcat (junkbuff, uni);
	sprintf (uni, "{%s}", PRDCT_PRTY);
	cat_bracket (junkbuff, uni);
	sprintf (uni, "{%d.%02d}",
		BINK_MAJVERSION,						/*  vvv  */ 
		BINK_MINVERSION);
	b7strcat (junkbuff, uni);
	sprintf (uni, "{%s}", ((serial == -1) ? MSG_TXT (M_UNREGISTERED) : ""));
	cat_bracket (junkbuff, uni);
	b7strcat (junkbuff, "{IDENT}{");
	sprintf (uni, "[%s]", system_name);          
	cat_bracket (junkbuff, uni);
	sprintf (uni, "[%s]", location);			/*  vvv  */ 
	cat_bracket (junkbuff, uni);
	sprintf (uni, "[%s]", sysop);
	cat_bracket (junkbuff, uni);                  
	sprintf (uni, "[%s]", myphone);
	cat_bracket (junkbuff, uni);
	sprintf (uni, "[%s]", mymaxbaud);
	cat_bracket (junkbuff, uni);
	sprintf (uni, "[%s]", myflags);
	cat_bracket (junkbuff, uni);				/* MB 93-11-27 */
	b7strcat (junkbuff, "}{TRX#}");
#ifdef ANSI_TIME_T
	sprintf (uni, "{[%08lX]}", etm - ANSI_TIME_T_DELTA);
#else
	sprintf (uni, "{[%08lX]}", etm);
#endif
	b7strcat (junkbuff, uni);
	return (strlen (junkbuff));
}

/* END OF FILE: emsi.c */
[ RETURN TO DIRECTORY ]