reactos/modules/rosapps/applications/net/ncftp/sio/SReadline.c

158 lines
3.2 KiB
C

#include "syshdrs.h"
void
FlushSReadlineInfo(SReadlineInfo *srl)
{
/* Discards any input left in the current buffer,
* and resets the buffer and its pointer.
*/
srl->bufSize = srl->bufSizeMax;
memset(srl->buf, 0, srl->bufSize);
srl->bufLim = srl->buf + srl->bufSizeMax;
/* This line sets the buffer pointer
* so that the first thing to do is reset and fill the buffer
* using real I/O.
*/
srl->bufPtr = srl->bufLim;
} /* FlushSReadlineInfo */
int
InitSReadlineInfo(SReadlineInfo *srl, int fd, char *buf, size_t bsize, int tlen, int requireEOLN)
{
if (buf == NULL) {
if (bsize < 512)
bsize = 512; /* Pointless, otherwise. */
buf = (char *) malloc(bsize);
if (buf == NULL)
return (-1);
srl->malloc = 1;
} else {
srl->malloc = 0;
}
memset(buf, 0, bsize);
srl->buf = buf;
srl->bufSize = bsize;
srl->bufSizeMax = bsize;
srl->bufLim = srl->buf + bsize;
srl->fd = fd;
srl->timeoutLen = tlen;
srl->requireEOLN = requireEOLN;
/* This line sets the buffer pointer
* so that the first thing to do is reset and fill the buffer
* using real I/O.
*/
srl->bufPtr = srl->bufLim;
return (0);
} /* InitSReadlineInfo */
void
DisposeSReadlineInfo(SReadlineInfo *srl)
{
memset(srl->buf, 0, srl->bufSizeMax);
if (srl->malloc != 0)
free(srl->buf);
memset(srl, 0, sizeof(SReadlineInfo));
/* Note: it does not close(srl->fd). */
} /* DisposeSReadlineInfo */
/* Returns the number of bytes read, including the newline which is
* also appended to the buffer. If you don't want that newline,
* set buf[nread - 1] = '\0', if nread > 0.
*/
int
SReadline(SReadlineInfo *srl, char *const linebuf, size_t linebufsize)
{
int err;
char *src;
char *dst;
char *dstlim;
int len;
int nr;
int requireEOLN;
int illegals;
illegals = 0;
err = 0;
dst = linebuf;
dstlim = dst + linebufsize - 1; /* Leave room for NUL. */
src = srl->bufPtr;
requireEOLN = srl->requireEOLN;
if (requireEOLN)
dstlim--;
if (dstlim <= dst)
return (-1); /* Buffer too small. */
forever {
if ((requireEOLN == 0) && (dst >= dstlim))
break;
if (src >= srl->bufLim) {
/* Fill the buffer. */
if (illegals > 1) {
/* Probable DOS -- return now and give you an
* opportunity to handle bogus input.
*/
goto done;
}
nr = SRead(srl->fd, srl->buf, srl->bufSizeMax, srl->timeoutLen, 0);
if (nr == 0) {
/* EOF. */
goto done;
} else if (nr < 0) {
/* Error. */
err = nr;
goto done;
}
srl->bufPtr = src = srl->buf;
srl->bufLim = srl->buf + nr;
}
if (*src == '\0') {
++src;
illegals++;
} else if (*src == '\r') {
++src;
/* If the next character is a \n that is valid,
* otherwise treat a stray \r as an illegal character.
*/
if ((src < srl->bufLim) && (*src != '\n'))
illegals++;
} else {
if (*src == '\n') {
if (dst < dstlim)
*dst++ = *src++;
else
src++;
goto done;
}
if (dst < dstlim)
*dst++ = *src++;
else
src++;
}
}
done:
srl->bufPtr = src;
if ((requireEOLN != 0) && (dst != linebuf) && (dst[-1] != '\n'))
*dst++ = '\n';
if ((requireEOLN != 0) && (dst == linebuf) && (illegals > 0))
*dst++ = '\n';
*dst = '\0';
len = (int) (dst - linebuf);
if (err < 0)
return (err);
return (len);
} /* SReadline */