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