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