1#include "syshdrs.h"
2#ifdef PRAGMA_HDRSTOP
3#	pragma hdrstop
4#endif
5
6void
7FlushSReadlineInfo(SReadlineInfo *srl)
8{
9	if (srl == NULL) {
10		errno = EINVAL;
11		return;
12	}
13
14	/* Discards any input left in the current buffer,
15	 * and resets the buffer and its pointer.
16	 */
17	memset(srl->buf, 0, srl->bufSizeMax);
18	srl->bufSize = 0;		/* Nothing buffered yet. */
19	srl->bufLim = srl->buf + srl->bufSize;
20
21	/* This line sets the buffer pointer
22	 * so that the first thing to do is reset and fill the buffer
23	 * using real I/O.
24	 */
25	srl->bufPtr = srl->bufLim;
26}	/* FlushSReadlineInfo */
27
28
29
30
31int
32InitSReadlineInfo(SReadlineInfo *srl, int fd, char *buf, size_t bsize, int tlen, int requireEOLN)
33{
34	if ((srl == NULL) || (fd < 0) || (tlen <= 0)) {
35		errno = EINVAL;
36		return (-1);
37	}
38
39	if (buf == NULL) {
40		if (bsize < 512)
41			bsize = 512;	/* Pointless, otherwise. */
42		buf = (char *) malloc(bsize);
43		if (buf == NULL)
44			return (-1);
45		srl->malloc = 1;
46	} else {
47		srl->malloc = 0;
48	}
49	memset(buf, 0, bsize);
50	srl->buf = buf;
51	srl->bufSizeMax = bsize;
52	srl->bufSize = 0;			/* Nothing buffered yet. */
53	srl->bufLim = srl->buf + srl->bufSize;
54	srl->fd = fd;
55	srl->timeoutLen = tlen;
56	srl->requireEOLN = requireEOLN;
57
58	/* This line sets the buffer pointer
59	 * so that the first thing to do is reset and fill the buffer
60	 * using real I/O.
61	 */
62	srl->bufPtr = srl->bufLim;
63	return (0);
64}	/* InitSReadlineInfo */
65
66
67
68
69void
70DisposeSReadlineInfo(SReadlineInfo *srl)
71{
72	memset(srl->buf, 0, srl->bufSizeMax);
73	if (srl->malloc != 0)
74		free(srl->buf);
75	memset(srl, 0, sizeof(SReadlineInfo));
76
77	/* Note: it does not close(srl->fd). */
78}	/* DisposeSReadlineInfo */
79
80
81
82
83/* Returns the number of bytes read, including the newline which is
84 * also appended to the buffer.  If you don't want that newline,
85 * set buf[nread - 1] = '\0', if nread > 0.
86 */
87
88int
89SReadline(SReadlineInfo *srl, char *const linebuf, size_t linebufsize)
90{
91	int err;
92	char *src;
93	char *dst;
94	char *dstlim;
95	int len;
96	int nr;
97	int requireEOLN;
98	int illegals;
99
100	if ((srl == NULL) || (linebuf == NULL) || (linebufsize < 2)) {
101		errno = EINVAL;
102		return (-1);
103	}
104
105	illegals = 0;
106	err = 0;
107	dst = linebuf;
108	dstlim = dst + linebufsize - 1;		       /* Leave room for NUL. */
109	src = srl->bufPtr;
110	requireEOLN = srl->requireEOLN;
111
112	forever {
113		if ((requireEOLN == 0) && (dst >= dstlim))
114			break;
115		if (src >= srl->bufLim) {
116			/* Fill the buffer. */
117			if (illegals > 1) {
118				/* Probable DOS -- return now and give you an
119				 * opportunity to handle bogus input.
120				 */
121				goto done;
122			}
123			nr = SRead(srl->fd, srl->buf, srl->bufSizeMax, srl->timeoutLen, 0);
124			if (nr == 0) {
125				/* EOF. */
126				goto done;
127			} else if (nr < 0) {
128				/* Error. */
129				err = nr;
130				goto done;
131			}
132			srl->bufPtr = src = srl->buf;
133			srl->bufLim = srl->buf + nr;
134			srl->bufSize = (size_t) nr;
135		}
136		if (*src == '\0') {
137			++src;
138			illegals++;
139		} else if (*src == '\r') {
140			++src;
141			/* If the next character is a \n that is valid,
142			 * otherwise treat a stray \r as an illegal character.
143			 */
144			if ((src < srl->bufLim) && (*src != '\n'))
145				illegals++;
146		} else {
147			if (*src == '\n') {
148				if (dst < dstlim)
149					*dst++ = *src++;
150				else
151					src++;
152				goto done;
153			}
154			if (dst < dstlim)
155				*dst++ = *src++;
156			else
157				src++;
158		}
159	}
160
161done:
162	srl->bufPtr = src;
163	if ((requireEOLN != 0) && (dst == linebuf) && (illegals > 0))
164		*dst++ = '\n';
165	*dst = '\0';
166	len = (int) (dst - linebuf);
167	if (err < 0)
168		return (err);
169	return (len);
170}						       /* SReadline */
171