blob: 30194b6d036363b1dd285989a228749f19e36921 [file] [log] [blame]
Jari Aalto31859422009-01-12 13:36:28 +00001/* zgetline - read a line of input from a specified file descriptor and return
2 a pointer to a newly-allocated buffer containing the data. */
3
4/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bash. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include <config.h>
23
24#include <sys/types.h>
25
26#if defined (HAVE_UNISTD_H)
27# include <unistd.h>
28#endif
29
30#include <errno.h>
31#include "xmalloc.h"
32
33#if !defined (errno)
Ricardo Cerqueiraa02fbff2013-07-25 22:35:34 +010034#include <errno.h>
Jari Aalto31859422009-01-12 13:36:28 +000035#endif
36
37extern ssize_t zread __P((int, char *, size_t));
38extern ssize_t zreadc __P((int, char *));
Jari Aalto17345e52009-02-19 22:21:29 +000039extern ssize_t zreadintr __P((int, char *, size_t));
40extern ssize_t zreadcintr __P((int, char *));
41
42typedef ssize_t breadfunc_t __P((int, char *, size_t));
43typedef ssize_t creadfunc_t __P((int, char *));
Jari Aalto31859422009-01-12 13:36:28 +000044
45/* Initial memory allocation for automatic growing buffer in zreadlinec */
46#define GET_LINE_INITIAL_ALLOCATION 16
47
48/* Derived from GNU libc's getline.
49 The behavior is almost the same as getline. See man getline.
50 The differences are
51 (1) using file descriptor instead of FILE *,
52 (2) the order of arguments; the file descriptor comes the first, and
Chet Rameyac50fba2014-02-26 09:36:43 -050053 (3) the addition of third argument, UNBUFFERED_READ; this argument
Jari Aalto31859422009-01-12 13:36:28 +000054 controls whether get_line uses buffering or not to get a byte data
55 from FD. get_line uses zreadc if UNBUFFERED_READ is zero; and
56 uses zread if UNBUFFERED_READ is non-zero.
57
58 Returns number of bytes read or -1 on error. */
59
60ssize_t
61zgetline (fd, lineptr, n, unbuffered_read)
62 int fd;
63 char **lineptr;
64 size_t *n;
65 int unbuffered_read;
66{
67 int nr, retval;
68 char *line, c;
69
70 if (lineptr == 0 || n == 0 || (*lineptr == 0 && *n != 0))
71 return -1;
72
73 nr = 0;
74 line = *lineptr;
75
76 while (1)
77 {
78 retval = unbuffered_read ? zread (fd, &c, 1) : zreadc(fd, &c);
79
80 if (retval <= 0)
81 {
Jari Aalto17345e52009-02-19 22:21:29 +000082 if (line && nr > 0)
83 line[nr] = '\0';
Jari Aalto31859422009-01-12 13:36:28 +000084 break;
85 }
86
87 if (nr + 2 >= *n)
88 {
Jari Aalto17345e52009-02-19 22:21:29 +000089 size_t new_size;
Jari Aalto31859422009-01-12 13:36:28 +000090
Jari Aalto17345e52009-02-19 22:21:29 +000091 new_size = (*n == 0) ? GET_LINE_INITIAL_ALLOCATION : *n * 2;
92 line = (*n >= new_size) ? NULL : xrealloc (*lineptr, new_size);
Jari Aalto31859422009-01-12 13:36:28 +000093
Jari Aalto17345e52009-02-19 22:21:29 +000094 if (line)
95 {
96 *lineptr = line;
97 *n = new_size;
98 }
99 else
100 {
101 if (*n > 0)
102 {
103 (*lineptr)[*n - 1] = '\0';
104 nr = *n - 2;
105 }
106 break;
107 }
Jari Aalto31859422009-01-12 13:36:28 +0000108 }
109
110 line[nr] = c;
111 nr++;
112
113 if (c == '\n')
114 {
115 line[nr] = '\0';
116 break;
117 }
118 }
119
120 return nr - 1;
121}