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