1 /* MIT License
2 *
3 * Copyright (c) 1998 Massachusetts Institute of Technology
4 * Copyright (c) The c-ares project and its contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * SPDX-License-Identifier: MIT
26 */
27
28 #include "ares_setup.h"
29
30 #include "ares.h"
31 #include "ares_private.h"
32
33 /* This is an internal function. Its contract is to read a line from
34 * a file into a dynamically allocated buffer, zeroing the trailing
35 * newline if there is one. The calling routine may call
36 * ares__read_line multiple times with the same buf and bufsize
37 * pointers; *buf will be reallocated and *bufsize adjusted as
38 * appropriate. The initial value of *buf should be NULL. After the
39 * calling routine is done reading lines, it should free *buf.
40 */
ares__read_line(FILE * fp,char ** buf,size_t * bufsize)41 ares_status_t ares__read_line(FILE *fp, char **buf, size_t *bufsize)
42 {
43 char *newbuf;
44 size_t offset = 0;
45 size_t len;
46
47 if (*buf == NULL) {
48 *buf = ares_malloc(128);
49 if (!*buf) {
50 return ARES_ENOMEM;
51 }
52 *bufsize = 128;
53 }
54
55 for (;;) {
56 int bytestoread = (int)(*bufsize - offset);
57
58 if (!fgets(*buf + offset, bytestoread, fp)) {
59 return (offset != 0) ? 0 : (ferror(fp)) ? ARES_EFILE : ARES_EOF;
60 }
61 len = offset + ares_strlen(*buf + offset);
62
63 /* Probably means there was an embedded NULL as the first character in
64 * the line, throw away line */
65 if (len == 0) {
66 offset = 0;
67 continue;
68 }
69
70 if ((*buf)[len - 1] == '\n') {
71 (*buf)[len - 1] = 0;
72 break;
73 }
74 offset = len;
75 if (len < *bufsize - 1) {
76 continue;
77 }
78
79 /* Allocate more space. */
80 newbuf = ares_realloc(*buf, *bufsize * 2);
81 if (!newbuf) {
82 ares_free(*buf);
83 *buf = NULL;
84 return ARES_ENOMEM;
85 }
86 *buf = newbuf;
87 *bufsize *= 2;
88 }
89 return ARES_SUCCESS;
90 }
91