101abeacded873dd835d2115d7c9a9b0b47e75254Elliott Hughes/* $OpenBSD: fgetln.c,v 1.13 2015/01/05 21:58:52 millert Exp $ */ 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*- 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1990, 1993 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * The Regents of the University of California. All rights reserved. 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * This code is derived from software contributed to Berkeley by 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Chris Torek. 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * documentation and/or other materials provided with the distribution. 17b2e1abda0503874a5bb097e0b55ad4f8ce211a8dElliott Hughes * 3. Neither the name of the University nor the names of its contributors 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * may be used to endorse or promote products derived from this software 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * without specific prior written permission. 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h> 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h> 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h> 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "local.h" 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Expand the line buffer. Return -1 on error. 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 42f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughesstatic int 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__slbexpand(FILE *fp, size_t newsize) 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project void *p; 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 476b05c8e28017518fae04a3a601d0d245916561d2Elliott Hughes if (fp->_lb._size >= newsize) 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if ((p = realloc(fp->_lb._base, newsize)) == NULL) 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (-1); 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fp->_lb._base = p; 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fp->_lb._size = newsize; 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (0); 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Get an input line. The returned pointer often (but not always) 580133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes * points into a stdio buffer. Fgetline does not alter the text of 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the returned line (which is thus not a C string because it will 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * not necessarily end with '\0'), but does allow callers to modify 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * it if they wish. Thus, we set __SMOD in case the caller does. 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectchar * 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectfgetln(FILE *fp, size_t *lenp) 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned char *p; 670133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes char *ret; 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t len; 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t off; 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 71f582340a6a48588aa50da17e1620e8f91b146941Kenny Root FLOCKFILE(fp); 720133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes _SET_ORIENTATION(fp, -1); 730133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* make sure there is input */ 750133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes if (fp->_r <= 0 && __srefill(fp)) 760133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes goto error; 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* look for a newline in the input */ 790133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) { 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Found one. Flag buffer as modified to keep fseek from 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * `optimising' a backward seek, in case the user stomps on 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the text. 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p++; /* advance over it */ 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ret = (char *)fp->_p; 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *lenp = len = p - fp->_p; 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fp->_flags |= __SMOD; 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fp->_r -= len; 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fp->_p = p; 91f582340a6a48588aa50da17e1620e8f91b146941Kenny Root FUNLOCKFILE(fp); 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return (ret); 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * We have to copy the current buffered data to the line buffer. 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * As a bonus, though, we can leave off the __SMOD. 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OPTIMISTIC is length that we (optimistically) expect will 100b2e1abda0503874a5bb097e0b55ad4f8ce211a8dElliott Hughes * accommodate the `rest' of the string, on each trip through the 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * loop below. 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define OPTIMISTIC 80 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (len = fp->_r, off = 0;; len += fp->_r) { 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project size_t diff; 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* 1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Make sure there is room for more bytes. Copy data from 1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * file buffer to line buffer, refill file and look for 1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * newline. The loop stops only when we find a newline. 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (__slbexpand(fp, len + OPTIMISTIC)) 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto error; 1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project len - off); 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project off = len; 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (__srefill(fp)) 1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; /* EOF or error: return partial line */ 1200133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL) 1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project continue; 1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* got it: finish up the line (like code above) */ 1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project p++; 1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project diff = p - fp->_p; 1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project len += diff; 1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (__slbexpand(fp, len)) 1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project goto error; 1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, 1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project diff); 1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fp->_r -= diff; 1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project fp->_p = p; 1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *lenp = len; 1360133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes ret = (char *)fp->_lb._base; 137f582340a6a48588aa50da17e1620e8f91b146941Kenny Root FUNLOCKFILE(fp); 1380133944b09d1c0a35041f7a41eb6bfb660144f4fElliott Hughes return (ret); 1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecterror: 141f582340a6a48588aa50da17e1620e8f91b146941Kenny Root FUNLOCKFILE(fp); 14201abeacded873dd835d2115d7c9a9b0b47e75254Elliott Hughes *lenp = 0; 14301abeacded873dd835d2115d7c9a9b0b47e75254Elliott Hughes return (NULL); 1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 145