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