Imported from ../bash-4.0.tar.gz.
[platform/upstream/bash.git] / lib / sh / zgetline.c
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
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)
34 extern int errno;
35 #endif
36
37 extern ssize_t zread __P((int, char *, size_t));
38 extern ssize_t zreadc __P((int, char *));
39 extern ssize_t zreadintr __P((int, char *, size_t));
40 extern ssize_t zreadcintr __P((int, char *));
41
42 typedef ssize_t breadfunc_t __P((int, char *, size_t));
43 typedef ssize_t creadfunc_t __P((int, char *));
44
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
53         (3) the addtion of thired argument, UNBUFFERED_READ; this argument
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
60 ssize_t
61 zgetline (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         {
82           if (line && nr > 0)
83             line[nr] = '\0';
84           break;
85         }
86
87       if (nr + 2 >= *n)
88         {
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             }
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 }