1276415Sdelphij/*	$NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp $	*/
2226048Sobrien
3226048Sobrien/*-
4226048Sobrien * Copyright (c) 2011 The NetBSD Foundation, Inc.
5226048Sobrien * All rights reserved.
6226048Sobrien *
7226048Sobrien * This code is derived from software contributed to The NetBSD Foundation
8226048Sobrien * by Christos Zoulas.
9226048Sobrien *
10226048Sobrien * Redistribution and use in source and binary forms, with or without
11226048Sobrien * modification, are permitted provided that the following conditions
12226048Sobrien * are met:
13226048Sobrien * 1. Redistributions of source code must retain the above copyright
14226048Sobrien *    notice, this list of conditions and the following disclaimer.
15226048Sobrien * 2. Redistributions in binary form must reproduce the above copyright
16226048Sobrien *    notice, this list of conditions and the following disclaimer in the
17226048Sobrien *    documentation and/or other materials provided with the distribution.
18226048Sobrien *
19226048Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20226048Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21226048Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22226048Sobrien * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23226048Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24226048Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25226048Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26226048Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27226048Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28226048Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29226048Sobrien * POSSIBILITY OF SUCH DAMAGE.
30226048Sobrien */
31226048Sobrien
32226048Sobrien#include "file.h"
33226048Sobrien#if !HAVE_GETLINE
34226048Sobrien#include <stdlib.h>
35226048Sobrien#include <stdio.h>
36226048Sobrien#include <unistd.h>
37226048Sobrien#include <errno.h>
38226048Sobrien#include <string.h>
39226048Sobrien
40267843Sdelphijpublic ssize_t
41226048Sobriengetdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
42226048Sobrien{
43226048Sobrien	char *ptr, *eptr;
44226048Sobrien
45226048Sobrien
46226048Sobrien	if (*buf == NULL || *bufsiz == 0) {
47226048Sobrien		*bufsiz = BUFSIZ;
48226048Sobrien		if ((*buf = malloc(*bufsiz)) == NULL)
49226048Sobrien			return -1;
50226048Sobrien	}
51226048Sobrien
52226048Sobrien	for (ptr = *buf, eptr = *buf + *bufsiz;;) {
53226048Sobrien		int c = fgetc(fp);
54226048Sobrien		if (c == -1) {
55276415Sdelphij			if (feof(fp)) {
56276415Sdelphij				ssize_t diff = (ssize_t)(ptr - *buf);
57276415Sdelphij				if (diff != 0) {
58276415Sdelphij					*ptr = '\0';
59276415Sdelphij					return diff;
60276415Sdelphij				}
61276415Sdelphij			}
62276415Sdelphij			return -1;
63226048Sobrien		}
64226048Sobrien		*ptr++ = c;
65226048Sobrien		if (c == delimiter) {
66226048Sobrien			*ptr = '\0';
67226048Sobrien			return ptr - *buf;
68226048Sobrien		}
69226048Sobrien		if (ptr + 2 >= eptr) {
70226048Sobrien			char *nbuf;
71226048Sobrien			size_t nbufsiz = *bufsiz * 2;
72226048Sobrien			ssize_t d = ptr - *buf;
73226048Sobrien			if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
74226048Sobrien				return -1;
75226048Sobrien			*buf = nbuf;
76226048Sobrien			*bufsiz = nbufsiz;
77226048Sobrien			eptr = nbuf + nbufsiz;
78226048Sobrien			ptr = nbuf + d;
79226048Sobrien		}
80226048Sobrien	}
81226048Sobrien}
82226048Sobrien
83277592Sdelphijpublic ssize_t
84226048Sobriengetline(char **buf, size_t *bufsiz, FILE *fp)
85226048Sobrien{
86226048Sobrien	return getdelim(buf, bufsiz, '\n', fp);
87226048Sobrien}
88226048Sobrien
89226048Sobrien#endif
90226048Sobrien
91226048Sobrien#ifdef TEST
92226048Sobrienint
93226048Sobrienmain(int argc, char *argv[])
94226048Sobrien{
95226048Sobrien	char *p = NULL;
96226048Sobrien	ssize_t len;
97226048Sobrien	size_t n = 0;
98226048Sobrien
99226048Sobrien	while ((len = getline(&p, &n, stdin)) != -1)
100276415Sdelphij		(void)printf("%" SIZE_T_FORMAT "d %s", len, p);
101226048Sobrien	free(p);
102226048Sobrien	return 0;
103226048Sobrien}
104226048Sobrien#endif
105