1stMud4.5.3/
1stMud4.5.3/backup/
1stMud4.5.3/bin/
1stMud4.5.3/bin/extras/
1stMud4.5.3/data/i3/
1stMud4.5.3/doc/1stMud/
1stMud4.5.3/doc/Diku/
1stMud4.5.3/doc/MPDocs/
1stMud4.5.3/doc/Rom/
1stMud4.5.3/notes/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*          1stMud ROM Derivative (c) 2001-2004 by Markanth                *
*            http://www.firstmud.com/  <markanth@firstmud.com>            *
*         By using this code you have agreed to follow the term of        *
*             the 1stMud license in ../doc/1stMud/LICENSE                 *
***************************************************************************/

#ifndef __DESCRIPTOR_H_
#define __DESCRIPTOR_H_  1

int d_print(Descriptor * d, const char *txt)
{
	int length;

	if (!d || NullStr(txt))
		return 0;

	length = strlen(txt);

	if (d->outtop == 0)
	{
		if (!d->fcommand)
		{
			d->outbuf[d->outtop++] = '\n';
			d->outbuf[d->outtop++] = '\r';
		}
		if (d->fPrompt)
		{
			d->outbuf[d->outtop++] = '\n';
			d->outbuf[d->outtop++] = '\r';
			d->fPrompt = false;
		}
	}

	while (d->outtop + length >= d->outsize)
	{
		char *tmpbuf;

		if (d->outsize >= 32000)
		{
			bug("Buffer overflow. Closing.");
			close_socket(d);
			return -1;
		}
		d->outsize *= 2;
		alloc_mem(tmpbuf, char, d->outsize);
		strncpy(tmpbuf, d->outbuf, d->outtop);
		free_mem(d->outbuf);
		d->outbuf = tmpbuf;
	}

	strncpy(d->outbuf + d->outtop, txt, length);
	d->outtop += length;
	return length;
}

int d_println(Descriptor * d, const char *txt)
{
	if (!d)
		return 0;

	return (d_print(d, txt) + d_print(d, NEWLINE));
}

int d_printf(Descriptor * d, const char *txt, ...)
{
	va_list args;
	char buf[MPL];

	if (!d || NullStr(txt))
		return 0;

	va_start(args, txt);
	vsnprintf(buf, sizeof(buf), txt, args);
	va_end(args);

	return d_print(d, buf);
}

int d_printlnf(Descriptor * d, const char *txt, ...)
{
	char buf[MPL];

	if (!d)
		return 0;

	buf[0] = NUL;
	if (!NullStr(txt))
	{
		va_list args;

		va_start(args, txt);
		vsnprintf(buf, sizeof(buf), txt, args);
		va_end(args);
	}
	return d_println(d, buf);
}

int write_to_socket(SOCKET desc, const char *txt, int length)
{
	int iStart, nWrite = 0, nBlock;

	if (length <= 0)
	{
		length = strlen(txt);
	}

	for (iStart = 0; iStart < length; iStart += nWrite)
	{
		nBlock = Min(length - iStart, 4096);
		nWrite = send(desc, txt + iStart, nBlock, 0);
		if (nWrite < 0)
		{
#ifdef WIN32
			if (WSAGetLastError() == WSAEWOULDBLOCK)
				break;
#else
#ifndef EAGAIN
#define        	EAGAIN        	11
#endif
#ifndef ENOSR
#define        	ENOSR        	63
#endif

			if (errno == EAGAIN || errno == ENOSR)
				break;
#endif

			socket_error("write_to_socket()");
			return -1;
		}
	}
	return iStart + Min(0, nWrite);
}

int d_write(Descriptor * d, const char *txt, int length)
{
	if (!d)
		return 0;

	if (length <= 0)
		length = strlen(txt);

	d->bytes_normal += length;
	mud_info.bytes_normal += length;
#ifndef DISABLE_MCCP

	if (d->out_compress)
	{
		z_stream *s = d->out_compress;
		int bad_write_loop = 0, totalwritten = 0, written = 0, len;

		s->next_in = (unsigned char *) txt;
		s->avail_in = length;
		while (s->avail_in && bad_write_loop < 5)
		{
			s->avail_out =
				COMPRESS_BUF_SIZE - (s->next_out - d->out_compress_buf);

			if (s->avail_out)
			{
				if (deflate(s, Z_SYNC_FLUSH) != Z_OK)
				{
					logf("d_write() - compression error.");
					return -1;
				}
			}

			len = d->out_compress->next_out - d->out_compress_buf;
			written =
				write_to_socket(d->descriptor, (char *) d->out_compress_buf,
								len);
			if (written > 0)
			{
				d->bytes_compressed += written;
				mud_info.bytes_compressed += written;
				if (written < len)
				{
					memmove(d->out_compress_buf,
							d->out_compress_buf + written, len - written);
				}
				d->out_compress->next_out =
					d->out_compress_buf + len - written;
				totalwritten += written;
			}
			else
			{
				bad_write_loop++;
			}
		}
		if (bad_write_loop == 5)
		{

			if (totalwritten)
			{

				return totalwritten;
			}
			return -1;
		}

		return length;
	}
	else
#endif

		return write_to_socket(d->descriptor, txt, length);
}

#ifdef __cplusplus

int Descriptor::wrap(const char *buf)
{
	Descriptor *d = this;
#else
int dwrap(Descriptor * d, const char *buf)
{
#endif
	static char out[MSL * 5];
	int width;
	int pos;
	const char *p;

	if (!d)
		return 0;

	width = ScrWidth(d);

	p = erase_new_lines(buf);
	pos = 0;

	out[0] = NUL;

	do
	{
		pos = get_line_len(p, width);
		if (pos > 0)
		{
			strncat(out, p, pos);
			p += pos;
			strcat(out, NEWLINE);
		}
		else
		{
			strcat(out, p);
			break;
		}
	}
	while (true);

	return d_print(d, out);
}

int dwrapln(Descriptor * d, const char *buf)
{
	if (!d)
		return 0;

	return (dwrap(d, buf) + d_print(d, NEWLINE));
}

int dwrapf(Descriptor * d, const char *buf, ...)
{
	va_list args;
	char format[MPL];

	if (!d || NullStr(buf))
		return 0;

	va_start(args, buf);
	vsnprintf(format, sizeof(format), buf, args);
	va_end(args);

	return dwrap(d, format);
}

int dwraplnf(Descriptor * d, const char *buf, ...)
{
	char format[MPL];

	if (!d)
		return 0;

	format[0] = NUL;
	if (!NullStr(buf))
	{
		va_list args;

		va_start(args, buf);
		vsnprintf(format, sizeof(format), buf, args);
		va_end(args);
	}
	return d_println(d, format);
}

bool read_from_descriptor(Descriptor * d)
{
	unsigned int iStart, index;
	static unsigned char buf[sizeof(d->inbuf)];

	memset(buf, 0, sizeof(buf));

	if (!NullStr(d->incomm))
		return true;

	iStart = strlen(d->inbuf);
	index = 0;

	if (iStart >= sizeof(d->inbuf) - 10)
	{
		logf("%s input overflow!", d->host);
		d_write(d, NEWLINE "*** PUT A LID ON IT!!! ***" NEWLINE, 0);
		d->inbuf[sizeof(d->inbuf) - 10] = '\0';
		return true;
	}

	for (;;)
	{
		int nRead;

		if (sizeof(buf) - 10 - iStart == 0)
		{
			break;
		}

		nRead =
			recv(d->descriptor, (char *) buf + index,
				 sizeof(buf) - 10 - index, 0);
		if (nRead > 0)
		{
			index += nRead;
			if (buf[index - 1] == '\n' || buf[index - 1] == '\r')
				break;
		}
		else if (nRead == 0)
		{
			logf("EOF encountered on read.");
			return false;
		}
		else if (check_errno(EWOULDBLOCK))
			break;
		else
		{
			socket_error("Read_from_descriptor");
			return false;
		}
	}

	process_telnet(d, index, buf);

	if (d->connected == CON_GET_TERM
		&&
		(IsSet
		 (d->desc_flags,
		  DESC_TELOPT_EOR | DESC_TELOPT_ECHO | DESC_TELOPT_NAWS | DESC_MXP |
		  DESC_MSP | DESC_PUEBLO | DESC_TELOPT_TTYPE | DESC_TELOPT_BINARY |
		  DESC_PORTAL | DESC_IMP)
#ifndef DISABLE_MCCP
		 || d->out_compress
#endif
		))
	{
		SetBit(d->desc_flags, DESC_COLOR);
		d_printlnf(d, "%s{c enabled Automatically...{x",
				   Upper(colorize("color")));
		show_greeting(d);
		d->connected = CON_GET_NAME;
	}
	return true;
}

#endif