Line data Source code
1 : /* xreadline.c - fgets replacement function
2 : * Copyright (C) 1999, 2004 Free Software Foundation, Inc.
3 : *
4 : * This file is part of GnuPG.
5 : *
6 : * This file is free software; you can redistribute it and/or modify
7 : * it under the terms of either
8 : *
9 : * - the GNU Lesser General Public License as published by the Free
10 : * Software Foundation; either version 3 of the License, or (at
11 : * your option) any later version.
12 : *
13 : * or
14 : *
15 : * - the GNU General Public License as published by the Free
16 : * Software Foundation; either version 2 of the License, or (at
17 : * your option) any later version.
18 : *
19 : * or both in parallel, as here.
20 : *
21 : * This file is distributed in the hope that it will be useful,
22 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 : * GNU General Public License for more details.
25 : *
26 : * You should have received a copy of the GNU General Public License
27 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include <config.h>
31 : #include <stdio.h>
32 : #include <stdlib.h>
33 : #include <errno.h>
34 :
35 : #include "util.h"
36 :
37 :
38 : /* Same as fgets() but if the provided buffer is too short a larger
39 : one will be allocated. This is similar to getline. A line is
40 : considered a byte stream ending in a LF.
41 :
42 : If MAX_LENGTH is not NULL, it shall point to a value with the
43 : maximum allowed allocation.
44 :
45 : Returns the length of the line. EOF is indicated by a line of
46 : length zero. A truncated line is indicated by setting the value at
47 : MAX_LENGTH to 0. If the returned value is less then 0 not enough
48 : memory was enable and ERRNO is set accordingly.
49 :
50 : If a line has been truncated, the file pointer is moved forward to
51 : the end of the line so that the next read starts with the next
52 : line. Note that MAX_LENGTH must be re-initialzied in this case.
53 :
54 : Note: The returned buffer is allocated with enough extra space to
55 : append a CR,LF,Nul
56 : */
57 : ssize_t
58 2 : read_line (FILE *fp,
59 : char **addr_of_buffer, size_t *length_of_buffer,
60 : size_t *max_length)
61 : {
62 : int c;
63 2 : char *buffer = *addr_of_buffer;
64 2 : size_t length = *length_of_buffer;
65 2 : size_t nbytes = 0;
66 2 : size_t maxlen = max_length? *max_length : 0;
67 : char *p;
68 :
69 2 : if (!buffer)
70 : { /* No buffer given - allocate a new one. */
71 1 : length = 256;
72 1 : buffer = xtrymalloc (length);
73 1 : *addr_of_buffer = buffer;
74 1 : if (!buffer)
75 : {
76 0 : *length_of_buffer = 0;
77 0 : if (max_length)
78 0 : *max_length = 0;
79 0 : return -1;
80 : }
81 1 : *length_of_buffer = length;
82 : }
83 :
84 2 : length -= 3; /* Reserve 3 bytes for CR,LF,EOL. */
85 2 : p = buffer;
86 41 : while ((c = getc (fp)) != EOF)
87 : {
88 37 : if (nbytes == length)
89 : { /* Enlarge the buffer. */
90 0 : if (maxlen && length > maxlen) /* But not beyond our limit. */
91 : {
92 : /* Skip the rest of the line. */
93 0 : while (c != '\n' && (c=getc (fp)) != EOF)
94 : ;
95 0 : *p++ = '\n'; /* Always append a LF (we reserved some space). */
96 0 : nbytes++;
97 0 : if (max_length)
98 0 : *max_length = 0; /* Indicate truncation. */
99 0 : break; /* the while loop. */
100 : }
101 0 : length += 3; /* Adjust for the reserved bytes. */
102 0 : length += length < 1024? 256 : 1024;
103 0 : *addr_of_buffer = xtryrealloc (buffer, length);
104 0 : if (!*addr_of_buffer)
105 : {
106 0 : int save_errno = errno;
107 0 : xfree (buffer);
108 0 : *length_of_buffer = 0;
109 0 : if (max_length)
110 0 : *max_length = 0;
111 0 : gpg_err_set_errno (save_errno);
112 0 : return -1;
113 : }
114 0 : buffer = *addr_of_buffer;
115 0 : *length_of_buffer = length;
116 0 : length -= 3;
117 0 : p = buffer + nbytes;
118 : }
119 37 : *p++ = c;
120 37 : nbytes++;
121 37 : if (c == '\n')
122 0 : break;
123 : }
124 2 : *p = 0; /* Make sure the line is a string. */
125 :
126 2 : return nbytes;
127 : }
|