1139804Simp/*- 248391Speter * Copyright (c) 1990, 1993 348391Speter * The Regents of the University of California. All rights reserved. 448391Speter * 548391Speter * This code is derived from software contributed to Berkeley by 648391Speter * Chris Torek. 748391Speter * 848391Speter * Redistribution and use in source and binary forms, with or without 948391Speter * modification, are permitted provided that the following conditions 1048391Speter * are met: 1148391Speter * 1. Redistributions of source code must retain the above copyright 1248391Speter * notice, this list of conditions and the following disclaimer. 1348391Speter * 2. Redistributions in binary form must reproduce the above copyright 1448391Speter * notice, this list of conditions and the following disclaimer in the 1548391Speter * documentation and/or other materials provided with the distribution. 1648391Speter * 3. Neither the name of the University nor the names of its contributors 1748391Speter * may be used to endorse or promote products derived from this software 1848391Speter * without specific prior written permission. 1948391Speter * 2048391Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2148391Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2248391Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2348391Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2448391Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2548391Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2648391Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27116182Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28116182Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29116182Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3048391Speter * SUCH DAMAGE. 3148391Speter */ 3248391Speter 3370317Sjake#if defined(LIBC_SCCS) && !defined(lint) 3474927Sjhbstatic char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94"; 3574927Sjhb#endif /* LIBC_SCCS and not lint */ 3655722Simp#include <sys/cdefs.h> 3755539Sluoqi__FBSDID("$FreeBSD$"); 3874927Sjhb 3948391Speter#include "namespace.h" 4048391Speter#include <stdio.h> 41166188Sjeff#include <stdlib.h> 42173004Sjulian#include <string.h> 43173004Sjulian#include "un-namespace.h" 4448391Speter#include "libc_private.h" 4548391Speter#include "local.h" 4648391Speter 4748391Speter/* 4848391Speter * Expand the line buffer. Return -1 on error. 4948391Speter#ifdef notdef 5048391Speter * The `new size' does not account for a terminating '\0', 5148391Speter * so we add 1 here. 5248391Speter#endif 5348391Speter */ 5448391Speterint 5548391Speter__slbexpand(FILE *fp, size_t newsize) 5648391Speter{ 5748391Speter void *p; 5848391Speter 5948391Speter#ifdef notdef 6048391Speter ++newsize; 61172836Sjulian#endif 62104354Sscottl if (fp->_lb._size >= newsize) 6348391Speter return (0); 6448391Speter if ((p = realloc(fp->_lb._base, newsize)) == NULL) 6548391Speter return (-1); 6648391Speter fp->_lb._base = p; 6748391Speter fp->_lb._size = newsize; 6865557Sjasone return (0); 6948391Speter} 7065557Sjasone 7165557Sjasone/* 7265557Sjasone * Get an input line. The returned pointer often (but not always) 7365557Sjasone * points into a stdio buffer. Fgetln does not alter the text of 7465557Sjasone * the returned line (which is thus not a C string because it will 7565557Sjasone * not necessarily end with '\0'), but does allow callers to modify 7648391Speter * it if they wish. Thus, we set __SMOD in case the caller does. 7748391Speter */ 78172836Sjulianchar * 79104354Sscottlfgetln(FILE *fp, size_t *lenp) 8048391Speter{ 8148391Speter unsigned char *p; 8248391Speter size_t len; 83103216Sjulian size_t off; 8448391Speter 8548391Speter FLOCKFILE(fp); 86114434Sdes ORIENT(fp, -1); 87172836Sjulian /* make sure there is input */ 8865557Sjasone if (fp->_r <= 0 && __srefill(fp)) { 8990375Speter *lenp = 0; 90104354Sscottl FUNLOCKFILE(fp); 9148391Speter return (NULL); 9248391Speter } 9348391Speter 9448391Speter /* look for a newline in the input */ 9548391Speter if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) { 9648391Speter char *ret; 9748391Speter 9848391Speter /* 9971559Sjhb * Found one. Flag buffer as modified to keep fseek from 100173004Sjulian * `optimising' a backward seek, in case the user stomps on 10171559Sjhb * the text. 102173004Sjulian */ 103114983Sjhb p++; /* advance over it */ 104114983Sjhb ret = (char *)fp->_p; 105114983Sjhb *lenp = len = p - fp->_p; 10671559Sjhb fp->_flags |= __SMOD; 10748391Speter fp->_r -= len; 10848391Speter fp->_p = p; 10948391Speter FUNLOCKFILE(fp); 11048391Speter return (ret); 11148391Speter } 112173004Sjulian 113173004Sjulian /* 114173004Sjulian * We have to copy the current buffered data to the line buffer. 115173004Sjulian * As a bonus, though, we can leave off the __SMOD. 11648391Speter * 11748391Speter * OPTIMISTIC is length that we (optimistically) expect will 118103216Sjulian * accommodate the `rest' of the string, on each trip through the 119103216Sjulian * loop below. 12048391Speter */ 12169657Sjhb#define OPTIMISTIC 80 12269657Sjhb 123170307Sjeff for (len = fp->_r, off = 0;; len += fp->_r) { 124166188Sjeff size_t diff; 125170307Sjeff 12669657Sjhb /* 12769657Sjhb * Make sure there is room for more bytes. Copy data from 12848391Speter * file buffer to line buffer, refill file and look for 12948391Speter * newline. The loop stops only when we find a newline. 13048391Speter */ 13148391Speter if (__slbexpand(fp, len + OPTIMISTIC)) 132172836Sjulian goto error; 13348391Speter (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, 13486293Speter len - off); 13586293Speter off = len; 13670317Sjake if (__srefill(fp)) 13786293Speter break; /* EOF or error: return partial line */ 13886293Speter if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL) 139155400Sjhb continue; 140155400Sjhb 141155400Sjhb /* got it: finish up the line (like code above) */ 142155400Sjhb p++; 143155400Sjhb diff = p - fp->_p; 14474927Sjhb len += diff; 14586292Sdillon if (__slbexpand(fp, len)) 14686292Sdillon goto error; 14786292Sdillon (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, 14874927Sjhb diff); 149155400Sjhb fp->_r -= diff; 150155400Sjhb fp->_p = p; 151155400Sjhb break; 152155400Sjhb } 153155400Sjhb *lenp = len; 154155400Sjhb#ifdef notdef 155155400Sjhb fp->_lb._base[len] = 0; 15686293Speter#endif 15748391Speter FUNLOCKFILE(fp); 15848391Speter return ((char *)fp->_lb._base); 15955539Sluoqi 16055539Sluoqierror: 16155539Sluoqi *lenp = 0; /* ??? */ 16255539Sluoqi FUNLOCKFILE(fp); 16355539Sluoqi return (NULL); /* ??? */ 164172836Sjulian} 16555539Sluoqi