1c2931133SXin LI /* $NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp $ */
2b6cee71dSXin LI
3b6cee71dSXin LI /*-
4b6cee71dSXin LI * Copyright (c) 2011 The NetBSD Foundation, Inc.
5b6cee71dSXin LI * All rights reserved.
6b6cee71dSXin LI *
7b6cee71dSXin LI * This code is derived from software contributed to The NetBSD Foundation
8b6cee71dSXin LI * by Christos Zoulas.
9b6cee71dSXin LI *
10b6cee71dSXin LI * Redistribution and use in source and binary forms, with or without
11b6cee71dSXin LI * modification, are permitted provided that the following conditions
12b6cee71dSXin LI * are met:
13b6cee71dSXin LI * 1. Redistributions of source code must retain the above copyright
14b6cee71dSXin LI * notice, this list of conditions and the following disclaimer.
15b6cee71dSXin LI * 2. Redistributions in binary form must reproduce the above copyright
16b6cee71dSXin LI * notice, this list of conditions and the following disclaimer in the
17b6cee71dSXin LI * documentation and/or other materials provided with the distribution.
18b6cee71dSXin LI *
19b6cee71dSXin LI * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20b6cee71dSXin LI * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21b6cee71dSXin LI * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22b6cee71dSXin LI * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23b6cee71dSXin LI * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24b6cee71dSXin LI * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25b6cee71dSXin LI * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26b6cee71dSXin LI * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27b6cee71dSXin LI * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28b6cee71dSXin LI * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29b6cee71dSXin LI * POSSIBILITY OF SUCH DAMAGE.
30b6cee71dSXin LI */
31b6cee71dSXin LI
32b6cee71dSXin LI #include "file.h"
33b6cee71dSXin LI #if !HAVE_GETLINE
34b6cee71dSXin LI #include <stdlib.h>
35b6cee71dSXin LI #include <stdio.h>
36b6cee71dSXin LI #include <unistd.h>
37b6cee71dSXin LI #include <errno.h>
38b6cee71dSXin LI #include <string.h>
39b6cee71dSXin LI
40*898496eeSXin LI file_public ssize_t
getdelim(char ** buf,size_t * bufsiz,int delimiter,FILE * fp)41b6cee71dSXin LI getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp)
42b6cee71dSXin LI {
43b6cee71dSXin LI char *ptr, *eptr;
44b6cee71dSXin LI
45b6cee71dSXin LI
46b6cee71dSXin LI if (*buf == NULL || *bufsiz == 0) {
47b6cee71dSXin LI *bufsiz = BUFSIZ;
48b6cee71dSXin LI if ((*buf = malloc(*bufsiz)) == NULL)
49b6cee71dSXin LI return -1;
50b6cee71dSXin LI }
51b6cee71dSXin LI
52b6cee71dSXin LI for (ptr = *buf, eptr = *buf + *bufsiz;;) {
53b6cee71dSXin LI int c = fgetc(fp);
54b6cee71dSXin LI if (c == -1) {
55c2931133SXin LI if (feof(fp)) {
56c2931133SXin LI ssize_t diff = (ssize_t)(ptr - *buf);
57c2931133SXin LI if (diff != 0) {
58c2931133SXin LI *ptr = '\0';
59c2931133SXin LI return diff;
60c2931133SXin LI }
61c2931133SXin LI }
62b6cee71dSXin LI return -1;
63b6cee71dSXin LI }
64b6cee71dSXin LI *ptr++ = c;
65b6cee71dSXin LI if (c == delimiter) {
66b6cee71dSXin LI *ptr = '\0';
67b6cee71dSXin LI return ptr - *buf;
68b6cee71dSXin LI }
69b6cee71dSXin LI if (ptr + 2 >= eptr) {
70b6cee71dSXin LI char *nbuf;
71b6cee71dSXin LI size_t nbufsiz = *bufsiz * 2;
72b6cee71dSXin LI ssize_t d = ptr - *buf;
73b6cee71dSXin LI if ((nbuf = realloc(*buf, nbufsiz)) == NULL)
74b6cee71dSXin LI return -1;
75b6cee71dSXin LI *buf = nbuf;
76b6cee71dSXin LI *bufsiz = nbufsiz;
77b6cee71dSXin LI eptr = nbuf + nbufsiz;
78b6cee71dSXin LI ptr = nbuf + d;
79b6cee71dSXin LI }
80b6cee71dSXin LI }
81b6cee71dSXin LI }
82b6cee71dSXin LI
83*898496eeSXin LI file_public ssize_t
getline(char ** buf,size_t * bufsiz,FILE * fp)84b6cee71dSXin LI getline(char **buf, size_t *bufsiz, FILE *fp)
85b6cee71dSXin LI {
86b6cee71dSXin LI return getdelim(buf, bufsiz, '\n', fp);
87b6cee71dSXin LI }
88b6cee71dSXin LI
89b6cee71dSXin LI #endif
90b6cee71dSXin LI
91b6cee71dSXin LI #ifdef TEST
92b6cee71dSXin LI int
main(int argc,char * argv[])93b6cee71dSXin LI main(int argc, char *argv[])
94b6cee71dSXin LI {
95b6cee71dSXin LI char *p = NULL;
96b6cee71dSXin LI ssize_t len;
97b6cee71dSXin LI size_t n = 0;
98b6cee71dSXin LI
99b6cee71dSXin LI while ((len = getline(&p, &n, stdin)) != -1)
100c2931133SXin LI (void)printf("%" SIZE_T_FORMAT "d %s", len, p);
101b6cee71dSXin LI free(p);
102b6cee71dSXin LI return 0;
103b6cee71dSXin LI }
104b6cee71dSXin LI #endif
105