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 */ 158