/*************************************************************************\ * Copyright (C) Michael Kerrisk, 2018. * * * * This program is free software. You may use, modify, and redistribute it * * under the terms of the GNU Lesser General Public License as published * * by the Free Software Foundation, either version 3 or (at your option) * * any later version. This program is distributed without any warranty. * * See the files COPYING.lgpl-v3 and COPYING.gpl-v3 for details. * \*************************************************************************/ /* Listing 59-1 */ /* read_line.c Implementation of readLine(). */ #include #include #include "read_line.h" /* Declaration of readLine() */ /* Read characters from 'fd' until a newline is encountered. If a newline character is not encountered in the first (n - 1) bytes, then the excess characters are discarded. The returned string placed in 'buf' is null-terminated and includes the newline character if it was read in the first (n - 1) bytes. The function return value is the number of bytes placed in buffer (which includes the newline character if encountered, but excludes the terminating null byte). */ ssize_t readLine(int fd, void *buffer, size_t n) { ssize_t numRead; /* # of bytes fetched by last read() */ size_t totRead; /* Total bytes read so far */ char *buf; char ch; if (n <= 0 || buffer == NULL) { errno = EINVAL; return -1; } buf = buffer; /* No pointer arithmetic on "void *" */ totRead = 0; for (;;) { numRead = read(fd, &ch, 1); if (numRead == -1) { if (errno == EINTR) /* Interrupted --> restart read() */ continue; else return -1; /* Some other error */ } else if (numRead == 0) { /* EOF */ if (totRead == 0) /* No bytes read; return 0 */ return 0; else /* Some bytes read; add '\0' */ break; } else { /* 'numRead' must be 1 if we get here */ if (totRead < n - 1) { /* Discard > (n - 1) bytes */ totRead++; *buf++ = ch; } if (ch == '\n') break; } } *buf = '\0'; return totRead; }