/* * Copyright (c) Alex Holden 2000, 2001. * * This code is public domain; you can do whatever you want with it, though I * would prefer you to contribute any bug fixes back to me if possible. * This software comes with NO WARRANTY WHATSOEVER, not even the implied * warranties of merchantability and fitness for a particular purpose. * * lineget.c: Reads data a line at a time from a file descriptor. * * Modelled after getline(), but with no dependency on the stdio library. * * ssize_t lineget(char **line, size_t *size, long *pos, long *ex, int fd); * * line is the address of the line buffer pointer. size is the address of a * value describing the length of the buffer. pos is the address of a value * describing the position after the current line in the buffer (it should be * set to 0 to start with). ex is the address of a value describing the * number of bytes following the current line which have already been read. * fd is the file descriptor to read from. lineget reads from fd into *line * until it reaches a \n character, and then returns either the number of * characters read or -1 on error. The returned string includes the \n * character, and is not null terminated (in fact, there may be null characters * within the string). If the line buffer is not big enough, lineget will * automatically reallocate it to a larger size and update the line and size * variables. If *line is NULL and *size is zero (for example on the first * call), the buffer will be newly allocated. */ #include #include #include #include #include "arch.h" #include "util.h" #include "lineget.h" ssize_t lineget(char **line, size_t *size, long *pos, long *ex, int fd) { char *p; ssize_t i; /* Move the extra text to the start of the line */ if(*pos) { if(*ex) memmove(*line, *line + *pos, *ex); *pos = 0; } /* Start off with the buffer one block in size */ if(*size != LINEGET_BUF_SIZE) { *size = LINEGET_BUF_SIZE; *line = realloc(*line, *size); } /* Make sure there is some data in the buffer to start with */ if(!*ex) { if((i = safe_read(fd, *line, *size)) == -1) return -1; else if(!i) return 0; else *ex = i; } while(1) { /* Search for end of line until we run out of data */ p = *line; while((*ex)--) if(p[(*pos)++] == '\n') return(*pos); /* If we're at the end of the buffer, grow it */ if(*pos >= *size) { *size += LINEGET_INC_SIZE; *line = realloc(*line, *size); } /* Refill the buffer */ if((i = safe_read(fd, *line + *pos, *size - *pos)) == -1) return -1; else if(!i) return *pos; else *ex = i; } /* Not reached */ return -1; }