]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/sh/zgetline.c
bash-4.3-rc1 overlay
[thirdparty/bash.git] / lib / sh / zgetline.c
CommitLineData
2e4498b3
CR
1/* 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
012bac39 4/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
9cbcc93b
CR
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
2e4498b3
CR
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*/
9cbcc93b
CR
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)
34extern int errno;
35#endif
36
48ff5447
CR
37extern ssize_t zread __P((int, char *, size_t));
38extern ssize_t zreadc __P((int, char *));
e141c35a
CR
39extern 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 *));
48ff5447 44
9cbcc93b
CR
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
8581f42d 53 (3) the addition of third argument, UNBUFFERED_READ; this argument
9cbcc93b
CR
54 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 {
e141c35a
CR
82 if (line && nr > 0)
83 line[nr] = '\0';
9cbcc93b
CR
84 break;
85 }
86
87 if (nr + 2 >= *n)
88 {
e141c35a
CR
89 size_t new_size;
90
91 new_size = (*n == 0) ? GET_LINE_INITIAL_ALLOCATION : *n * 2;
92 line = (*n >= new_size) ? NULL : xrealloc (*lineptr, new_size);
93
94 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 }
9cbcc93b
CR
108 }
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}