1a7c91847Schristos /* getdelim.c --- Implementation of replacement getdelim function.
2a7c91847Schristos Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 Free
3a7c91847Schristos Software Foundation, Inc.
4a7c91847Schristos
5a7c91847Schristos This program is free software; you can redistribute it and/or
6a7c91847Schristos modify it under the terms of the GNU General Public License as
7a7c91847Schristos published by the Free Software Foundation; either version 2, or (at
8a7c91847Schristos your option) any later version.
9a7c91847Schristos
10a7c91847Schristos This program is distributed in the hope that it will be useful, but
11a7c91847Schristos WITHOUT ANY WARRANTY; without even the implied warranty of
12a7c91847Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13a7c91847Schristos General Public License for more details.
14a7c91847Schristos
15a7c91847Schristos You should have received a copy of the GNU General Public License
16a7c91847Schristos along with this program; if not, write to the Free Software
17a7c91847Schristos Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18a7c91847Schristos 02110-1301, USA. */
19*5a6c14c8Schristos #include <sys/cdefs.h>
20*5a6c14c8Schristos __RCSID("$NetBSD: getdelim.c,v 1.2 2016/05/17 14:00:09 christos Exp $");
21*5a6c14c8Schristos
22a7c91847Schristos
23a7c91847Schristos /* Ported from glibc by Simon Josefsson. */
24a7c91847Schristos
25a7c91847Schristos #ifdef HAVE_CONFIG_H
26a7c91847Schristos # include <config.h>
27a7c91847Schristos #endif
28a7c91847Schristos
29a7c91847Schristos #include <stdlib.h>
30a7c91847Schristos #include <errno.h>
31a7c91847Schristos
32a7c91847Schristos #include "getdelim.h"
33a7c91847Schristos
34a7c91847Schristos #if !HAVE_FLOCKFILE
35a7c91847Schristos # undef flockfile
36a7c91847Schristos # define flockfile(x) ((void) 0)
37a7c91847Schristos #endif
38a7c91847Schristos #if !HAVE_FUNLOCKFILE
39a7c91847Schristos # undef funlockfile
40a7c91847Schristos # define funlockfile(x) ((void) 0)
41a7c91847Schristos #endif
42a7c91847Schristos
43a7c91847Schristos /* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
44a7c91847Schristos NUL-terminate it). *LINEPTR is a pointer returned from malloc (or
45a7c91847Schristos NULL), pointing to *N characters of space. It is realloc'ed as
46a7c91847Schristos necessary. Returns the number of characters read (not including
47a7c91847Schristos the null terminator), or -1 on error or EOF. */
48a7c91847Schristos
49a7c91847Schristos ssize_t
getdelim(char ** lineptr,size_t * n,int delimiter,FILE * fp)50a7c91847Schristos getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
51a7c91847Schristos {
52a7c91847Schristos int result = 0;
53a7c91847Schristos ssize_t cur_len = 0;
54a7c91847Schristos ssize_t len;
55a7c91847Schristos
56a7c91847Schristos if (lineptr == NULL || n == NULL || fp == NULL)
57a7c91847Schristos {
58a7c91847Schristos errno = EINVAL;
59a7c91847Schristos return -1;
60a7c91847Schristos }
61a7c91847Schristos
62a7c91847Schristos flockfile (fp);
63a7c91847Schristos
64a7c91847Schristos if (*lineptr == NULL || *n == 0)
65a7c91847Schristos {
66a7c91847Schristos *n = 120;
67a7c91847Schristos *lineptr = (char *) malloc (*n);
68a7c91847Schristos if (*lineptr == NULL)
69a7c91847Schristos {
70a7c91847Schristos result = -1;
71a7c91847Schristos goto unlock_return;
72a7c91847Schristos }
73a7c91847Schristos }
74a7c91847Schristos
75a7c91847Schristos for (;;)
76a7c91847Schristos {
77a7c91847Schristos char *t;
78a7c91847Schristos int i;
79a7c91847Schristos
80a7c91847Schristos i = getc (fp);
81a7c91847Schristos if (i == EOF)
82a7c91847Schristos {
83a7c91847Schristos result = -1;
84a7c91847Schristos break;
85a7c91847Schristos }
86a7c91847Schristos
87a7c91847Schristos /* Make enough space for len+1 (for final NUL) bytes. */
88a7c91847Schristos if (cur_len + 1 >= *n)
89a7c91847Schristos {
90a7c91847Schristos size_t needed = 2 * (cur_len + 1) + 1; /* Be generous. */
91a7c91847Schristos char *new_lineptr;
92a7c91847Schristos
93a7c91847Schristos if (needed < cur_len)
94a7c91847Schristos {
95a7c91847Schristos result = -1;
96a7c91847Schristos goto unlock_return;
97a7c91847Schristos }
98a7c91847Schristos
99a7c91847Schristos new_lineptr = (char *) realloc (*lineptr, needed);
100a7c91847Schristos if (new_lineptr == NULL)
101a7c91847Schristos {
102a7c91847Schristos result = -1;
103a7c91847Schristos goto unlock_return;
104a7c91847Schristos }
105a7c91847Schristos
106a7c91847Schristos *lineptr = new_lineptr;
107a7c91847Schristos *n = needed;
108a7c91847Schristos }
109a7c91847Schristos
110a7c91847Schristos (*lineptr)[cur_len] = i;
111a7c91847Schristos cur_len++;
112a7c91847Schristos
113a7c91847Schristos if (i == delimiter)
114a7c91847Schristos break;
115a7c91847Schristos }
116a7c91847Schristos (*lineptr)[cur_len] = '\0';
117a7c91847Schristos result = cur_len ? cur_len : result;
118a7c91847Schristos
119a7c91847Schristos unlock_return:
120a7c91847Schristos funlockfile (fp);
121a7c91847Schristos return result;
122a7c91847Schristos }
123