diff -urN musl.orig//include/stdio.h musl/include/stdio.h --- musl.orig//include/stdio.h 2012-08-11 18:02:58.000000000 +0200 +++ musl/include/stdio.h 2012-08-11 18:07:38.522807627 +0200 @@ -92,6 +92,10 @@ char *fgets(char *, int, FILE *); char *gets(char *); +#ifdef _BSD_SOURCE +char *fgetln(FILE *, size_t *); +#endif + int fputs(const char *, FILE *); int puts(const char *); diff -urN musl.orig//src/stdio/fgetln.3 musl/src/stdio/fgetln.3 --- musl.orig//src/stdio/fgetln.3 1970-01-01 01:00:00.000000000 +0100 +++ musl/src/stdio/fgetln.3 2007-06-21 15:47:07.000000000 +0200 @@ -0,0 +1,146 @@ +.\" $OpenBSD: fgetln.3,v 1.15 2007/06/21 13:47:07 moritz Exp $ +.\" +.\" Copyright (c) 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd $Mdocdate: June 21 2007 $ +.Dt FGETLN 3 +.Os +.Sh NAME +.Nm fgetln +.Nd get a line from a stream +.Sh SYNOPSIS +.Fd #include +.Ft char * +.Fn fgetln "FILE *stream" "size_t *len" +.Sh DESCRIPTION +The +.Fn fgetln +function returns a pointer to the next line from the stream referenced by +.Fa stream . +This line is +.Em not +a C string as it does not end with a terminating +.Tn NUL +character. +The length of the line, including the final newline, +is stored in the memory location to which +.Fa len +points and is guaranteed to be greater than 0 upon successful completion. +(Note, however, that if the last line in the stream does not end in a newline, +the returned text will not contain a newline.) +.Sh RETURN VALUES +Upon successful completion a pointer is returned; +this pointer becomes invalid after the next +.Tn I/O +operation on +.Fa stream +(whether successful or not) +or as soon as the stream is closed. +Otherwise, +.Dv NULL +is returned. +.Pp +The +.Fn fgetln +function does not distinguish between end-of-file and error; the routines +.Xr feof 3 +and +.Xr ferror 3 +must be used +to determine which occurred. +If an error occurs, the global variable +.Va errno +is set to indicate the error. +The end-of-file condition is remembered, even on a terminal, and all +subsequent attempts to read will return +.Dv NULL +until the condition is +cleared with +.Xr clearerr 3 . +.Pp +The text to which the returned pointer points may be modified, +provided that no changes are made beyond the returned size. +These changes are lost as soon as the pointer becomes invalid. +.Sh ERRORS +.Bl -tag -width [EBADF] +.It Bq Er EBADF +The argument +.Fa stream +is not a stream open for reading. +.El +.Pp +The +.Fn fgetln +function may also fail and set +.Va errno +for any of the errors specified for the routines +.Xr fflush 3 , +.Xr malloc 3 , +.Xr read 2 , +.Xr stat 2 , +or +.Xr realloc 3 . +.Sh SEE ALSO +.Xr ferror 3 , +.Xr fgets 3 , +.Xr fopen 3 , +.Xr fparseln 3 , +.Xr putc 3 +.Sh HISTORY +The +.Fn fgetln +function first appeared in +.Bx 4.4 . +.Sh CAVEATS +Since the returned buffer is not a C string (it is not NUL terminated), a +common practice is to replace the newline character with +.Sq \e0 . +However, if the last line in a file does not contain a newline, +the returned text won't contain a newline either. +The following code demonstrates how to deal with this problem by allocating a +temporary buffer: +.Bd -literal + char *buf, *lbuf; + size_t len; + + lbuf = NULL; + while ((buf = fgetln(fp, &len))) { + if (buf[len - 1] == '\en') + buf[len - 1] = '\e0'; + else { + /* EOF without EOL, copy and add the NUL */ + if ((lbuf = malloc(len + 1)) == NULL) + err(1, NULL); + memcpy(lbuf, buf, len); + lbuf[len] = '\e0'; + buf = lbuf; + } + printf("%s\en", buf); + } + free(lbuf); +.Ed diff -urN musl.orig//src/stdio/fgetln.c musl/src/stdio/fgetln.c --- musl.orig//src/stdio/fgetln.c 1970-01-01 01:00:00.000000000 +0100 +++ musl/src/stdio/fgetln.c 2012-08-11 18:04:33.875929278 +0200 @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include + +char * +fgetln(stream, len) + FILE *stream; + size_t *len; +{ + static char *buffer = NULL; + static size_t buflen = 0; + + if (buflen == 0) { + buflen = 512; + if ((buffer = malloc(buflen+1)) == NULL) { + fprintf(stderr, "malloc: %s (%zu)\n", strerror(errno), + buflen+1); + exit(2); + } + } + if (fgets(buffer, buflen+1, stream) == NULL) + return NULL; + *len = strlen(buffer); + while (*len == buflen && buffer[*len-1] != '\n') { + if ((buffer = realloc(buffer, 2*buflen+1)) == NULL) { + fprintf(stderr, "realloc: %s (%zu)\n", strerror(errno), + 2*buflen+1); + exit(2); + } + if (fgets(buffer + buflen, buflen + 1, stream) == NULL) + return NULL; + *len += strlen(buffer + buflen); + buflen *= 2; + } + return buffer; +}