1 /* @(#)fgetaline.c 1.5 15/05/09 Copyright 2011-2015 J. Schilling */
2 /*
3 * Copyright (c) 2011-2015 J. Schilling
4 *
5 */
6 /*
7 * The contents of this file are subject to the terms of the
8 * Common Development and Distribution License, Version 1.0 only
9 * (the "License"). You may not use this file except in compliance
10 * with the License.
11 *
12 * See the file CDDL.Schily.txt in this distribution for details.
13 * A copy of the CDDL is also available via the Internet at
14 * http://www.opensource.org/licenses/cddl1.txt
15 *
16 * When distributing Covered Code, include this CDDL HEADER in each
17 * file and include the License file CDDL.Schily.txt from this distribution.
18 */
19
20 #include "schilyio.h"
21 #include <schily/stdlib.h>
22 #include <schily/string.h>
23
24 EXPORT ssize_t fgetaline __PR((FILE *, char **, size_t *));
25 EXPORT ssize_t getaline __PR((char **, size_t *));
26
27 #define DEF_LINE_SIZE 128
28
29 EXPORT ssize_t
fgetaline(f,bufp,lenp)30 fgetaline(f, bufp, lenp)
31 register FILE *f;
32 char **bufp;
33 register size_t *lenp;
34 {
35 #if defined(HAVE_GETDELIM) || !defined(USE_FGETS_FOR_FGETALINE)
36 return (getdelim(bufp, lenp, '\n', f));
37 #else
38 /*
39 * WARNING: fgets() cannot signal that the read line-buffer
40 * WARNING: has embedded nul bytes. We cannot distinguish
41 * WARNING: read nul bytes from the inserted nul past '\n'
42 * WARNING: without knowing file positions before and after.
43 */
44 int eof;
45 register size_t used = 0;
46 register size_t line_size;
47 register char *line;
48
49 if (bufp == NULL || lenp == NULL) {
50 seterrno(EINVAL);
51 return (-1);
52 }
53
54 line_size = *lenp;
55 line = *bufp;
56 if (line == NULL || line_size == 0) {
57 if (line_size == 0)
58 line_size = DEF_LINE_SIZE;
59 if (line == NULL)
60 line = (char *) malloc(line_size);
61 if (line == NULL)
62 return (-1);
63 }
64 /* read until EOF or newline encountered */
65 line[0] = '\0';
66 do {
67 line[line_size - 1] = '\t'; /* arbitrary non-zero char */
68 line[line_size - 2] = ' '; /* arbitrary non-newline char */
69 if (!(eof = (fgets(line+used,
70 line_size-used,
71 f) == NULL))) {
72
73 if (line[line_size - 1] != '\0' ||
74 line[line_size - 2] == '\n')
75 break;
76
77 used = line_size - 1;
78
79 line_size += DEF_LINE_SIZE;
80 line = (char *) realloc(line, line_size);
81 if (line == NULL)
82 return (-1);
83 }
84 } while (!eof);
85 used += strlen(&line[used]);
86 *bufp = line;
87 *lenp = line_size;
88 if (eof && (used == 0))
89 return (-1);
90 return (used);
91 #endif
92 }
93
94 EXPORT ssize_t
getaline(bufp,lenp)95 getaline(bufp, lenp)
96 char **bufp;
97 size_t *lenp;
98 {
99 return (fgetaline(stdin, bufp, lenp));
100 }
101