/* Copyright 2002, Red Hat Inc. - all rights reserved */ /* FUNCTION <>---read a line up to a specified line delimiter INDEX getdelim SYNOPSIS #include int getdelim(char **<[bufptr]>, size_t *<[n]>, int <[delim]>, FILE *<[fp]>); DESCRIPTION <> reads a file <[fp]> up to and possibly including a specified delimiter <[delim]>. The line is read into a buffer pointed to by <[bufptr]> and designated with size *<[n]>. If the buffer is not large enough, it will be dynamically grown by <>. As the buffer is grown, the pointer to the size <[n]> will be updated. RETURNS <> returns <<-1>> if no characters were successfully read; otherwise, it returns the number of bytes successfully read. At end of file, the result is nonzero. PORTABILITY <> is a glibc extension. No supporting OS subroutines are directly required. */ #include <_ansi.h> #include #include #include #include "local.h" #define MIN_LINE_SIZE 4 #define DEFAULT_LINE_SIZE 128 ssize_t __getdelim (char **bufptr, size_t *n, int delim, FILE *fp) { char *buf; char *ptr; size_t newsize, numbytes; int pos; int ch; int cont; if (fp == NULL || bufptr == NULL || n == NULL) { errno = EINVAL; return -1; } buf = *bufptr; if (buf == NULL || *n < MIN_LINE_SIZE) { buf = (char *)realloc (*bufptr, DEFAULT_LINE_SIZE); if (buf == NULL) { return -1; } *bufptr = buf; *n = DEFAULT_LINE_SIZE; } CHECK_INIT (_REENT, fp); _newlib_flockfile_start (fp); numbytes = *n; ptr = buf; cont = 1; while (cont) { /* fill buffer - leaving room for nul-terminator */ while (--numbytes > 0) { if ((ch = getc_unlocked (fp)) == EOF) { cont = 0; break; } else { *ptr++ = ch; if (ch == delim) { cont = 0; break; } } } if (cont) { /* Buffer is too small so reallocate a larger buffer. */ pos = ptr - buf; newsize = (*n << 1); buf = realloc (buf, newsize); if (buf == NULL) { cont = 0; break; } /* After reallocating, continue in new buffer */ *bufptr = buf; *n = newsize; ptr = buf + pos; numbytes = newsize - pos; } } _newlib_flockfile_end (fp); /* if no input data, return failure */ if (ptr == buf) return -1; /* otherwise, nul-terminate and return number of bytes read */ *ptr = '\0'; return (ssize_t)(ptr - buf); }