/**************************************************************************
* 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