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