Incorporate rosapps. 0.3.15 was branched somewhat incorrectly so rosapps is not synce...
[reactos.git] / modules / rosapps / applications / net / ncftp / sio / SReadline.c
1 #include "syshdrs.h"
2
3 void
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
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
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
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 */