1/*
2 * Copyright (c) 2009-2010 Todd C. Miller <Todd.Miller@courtesan.com>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <config.h>
18
19#include <sys/types.h>
20
21#include <stdio.h>
22#ifdef STDC_HEADERS
23# include <stdlib.h>
24# include <stddef.h>
25#else
26# ifdef HAVE_STDLIB_H
27#  include <stdlib.h>
28# endif
29#endif /* STDC_HEADERS */
30#ifdef HAVE_STRING_H
31# include <string.h>
32#endif /* HAVE_STRING_H */
33#ifdef HAVE_STRINGS_H
34# include <strings.h>
35#endif /* HAVE_STRINGS_H */
36#include <limits.h>
37
38#include "missing.h"
39#include "alloc.h"
40
41#ifndef LINE_MAX
42# define LINE_MAX 2048
43#endif
44
45#ifdef HAVE_FGETLN
46ssize_t
47getline(bufp, bufsizep, fp)
48    char **bufp;
49    size_t *bufsizep;
50    FILE *fp;
51{
52    char *buf;
53    size_t bufsize;
54    size_t len;
55
56    buf = fgetln(fp, &len);
57    if (buf) {
58	bufsize = *bufp ? *bufsizep : 0;
59	if (bufsize == 0 || bufsize < len + 1) {
60	    bufsize = len + 1;
61	    *bufp = erealloc(*bufp, bufsize);
62	    *bufsizep = bufsize;
63	}
64	memcpy(*bufp, buf, len);
65	(*bufp)[len] = '\0';
66    }
67    return buf ? len : -1;
68}
69#else
70ssize_t
71getline(bufp, bufsizep, fp)
72    char **bufp;
73    size_t *bufsizep;
74    FILE *fp;
75{
76    char *buf;
77    size_t bufsize;
78    ssize_t len = 0;
79
80    buf = *bufp;
81    bufsize = *bufsizep;
82    if (buf == NULL || bufsize == 0) {
83	bufsize = LINE_MAX;
84	buf = erealloc(buf, LINE_MAX);
85    }
86
87    for (;;) {
88	if (fgets(buf + len, bufsize - len, fp) == NULL) {
89	    len = -1;
90	    break;
91	}
92	len = strlen(buf);
93	if (!len || buf[len - 1] == '\n' || feof(fp))
94	    break;
95	bufsize *= 2;
96	buf = erealloc(buf, bufsize);
97    }
98    *bufp = buf;
99    *bufsizep = bufsize;
100    return len;
101}
102#endif
103