11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*-
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1990, 1993
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	The Regents of the University of California.  All rights reserved.
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * This code is derived from software contributed to Berkeley by
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Chris Torek.
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    documentation and/or other materials provided with the distribution.
16b2e1abda0503874a5bb097e0b55ad4f8ce211a8dElliott Hughes * 3. Neither the name of the University nor the names of its contributors
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    may be used to endorse or promote products derived from this software
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    without specific prior written permission.
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE.
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
336b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes#if defined(LIBC_SCCS) && !defined(lint)
346b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughesstatic char sccsid[] = "@(#)fgetln.c	8.2 (Berkeley) 1/2/94";
356b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes#endif /* LIBC_SCCS and not lint */
366b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes#include <sys/cdefs.h>
376b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes__FBSDID("$FreeBSD$");
386b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes
396b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes#include "namespace.h"
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
436b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes#include "un-namespace.h"
446b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes#include "libc_private.h"
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "local.h"
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Expand the line buffer.  Return -1 on error.
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef notdef
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The `new size' does not account for a terminating '\0',
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * so we add 1 here.
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
546b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughesint
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__slbexpand(FILE *fp, size_t newsize)
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	void *p;
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef notdef
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	++newsize;
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
626b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes	if (fp->_lb._size >= newsize)
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((p = realloc(fp->_lb._base, newsize)) == NULL)
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (-1);
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fp->_lb._base = p;
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fp->_lb._size = newsize;
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (0);
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Get an input line.  The returned pointer often (but not always)
736b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes * points into a stdio buffer.  Fgetln does not alter the text of
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the returned line (which is thus not a C string because it will
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * not necessarily end with '\0'), but does allow callers to modify
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * it if they wish.  Thus, we set __SMOD in case the caller does.
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectchar *
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfgetln(FILE *fp, size_t *lenp)
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	unsigned char *p;
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t len;
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t off;
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
85f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	FLOCKFILE(fp);
866b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes	ORIENT(fp, -1);
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* make sure there is input */
886b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes	if (fp->_r <= 0 && __srefill(fp)) {
896b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes		*lenp = 0;
906b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes		FUNLOCKFILE(fp);
916b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes		return (NULL);
926b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes	}
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* look for a newline in the input */
956b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes	if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) {
966b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes		char *ret;
976b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Found one.  Flag buffer as modified to keep fseek from
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * `optimising' a backward seek, in case the user stomps on
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * the text.
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		p++;		/* advance over it */
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ret = (char *)fp->_p;
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*lenp = len = p - fp->_p;
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fp->_flags |= __SMOD;
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fp->_r -= len;
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fp->_p = p;
109f582340a6a48588aa50da17e1620e8f91b146941Kenny Root		FUNLOCKFILE(fp);
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (ret);
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * We have to copy the current buffered data to the line buffer.
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * As a bonus, though, we can leave off the __SMOD.
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 *
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * OPTIMISTIC is length that we (optimistically) expect will
118b2e1abda0503874a5bb097e0b55ad4f8ce211a8dElliott Hughes	 * accommodate the `rest' of the string, on each trip through the
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * loop below.
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define OPTIMISTIC 80
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (len = fp->_r, off = 0;; len += fp->_r) {
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		size_t diff;
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Make sure there is room for more bytes.  Copy data from
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * file buffer to line buffer, refill file and look for
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * newline.  The loop stops only when we find a newline.
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (__slbexpand(fp, len + OPTIMISTIC))
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto error;
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    len - off);
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		off = len;
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (__srefill(fp))
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;	/* EOF or error: return partial line */
1386b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes		if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL)
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* got it: finish up the line (like code above) */
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		p++;
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		diff = p - fp->_p;
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		len += diff;
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (__slbexpand(fp, len))
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto error;
1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    diff);
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fp->_r -= diff;
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fp->_p = p;
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*lenp = len;
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef notdef
1556b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes	fp->_lb._base[len] = 0;
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
157f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	FUNLOCKFILE(fp);
1586b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes	return ((char *)fp->_lb._base);
1591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecterror:
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*lenp = 0;		/* ??? */
162f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	FUNLOCKFILE(fp);
1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (NULL);		/* ??? */
1641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
165