/* readline.c - From Jon C. Snader: Effective TCP/IP Programming * Addison-Wesley 2000 * For better understanding, read the excellent Snader book. */ #include "etcp.h" /* readline - read a '\n' terminated line from socket fd into buffer bufptr of size len. The line in the buffer is terminated with '\0'. It returns -1 in case of error or if the capacity of the buffer is exceeded. It returns 0 if EOF is encountered before reading '\n'. */ int readline( SOCKET fd, char *bufptr, size_t len ) { /* Note that this function is very tricky. It uses the static variables bp, cnt, and b to establish a local buffer. The recv call requests large chunks of data (the size of the buffer). Then if the recv call reads more than one line, the overflow remains in the buffer and it is made available to the next call to readline. Notice also that this routine reads up to '\n' and overwrites it with '\0'. Thus if the line is really terminated with "\r\n", the '\r' will remain unchanged. */ char *bufx = bufptr; static char *bp; static int cnt = 0; static char b[ 1500 ]; char c; while ( --len > 0 ) { if ( --cnt <= 0 ) { cnt = recv( fd, b, sizeof( b ), 0 ); if ( cnt < 0 ) { if ( errno == EINTR ) { len++; /* the while will decrement */ continue; } return -1; } if ( cnt == 0 ) return 0; bp = b; } c = *bp++; *bufptr++ = c; if ( c == '\n' ) { *bufptr = '\0'; return bufptr - bufx; } } set_errno( EMSGSIZE ); return -1; }