1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "tool_setup.h"
25*6236dae4SAndroid Build Coastguard Worker
26*6236dae4SAndroid Build Coastguard Worker #include "curlx.h"
27*6236dae4SAndroid Build Coastguard Worker
28*6236dae4SAndroid Build Coastguard Worker #include "tool_cfgable.h"
29*6236dae4SAndroid Build Coastguard Worker #include "tool_getparam.h"
30*6236dae4SAndroid Build Coastguard Worker #include "tool_helpers.h"
31*6236dae4SAndroid Build Coastguard Worker #include "tool_findfile.h"
32*6236dae4SAndroid Build Coastguard Worker #include "tool_msgs.h"
33*6236dae4SAndroid Build Coastguard Worker #include "tool_parsecfg.h"
34*6236dae4SAndroid Build Coastguard Worker #include "tool_util.h"
35*6236dae4SAndroid Build Coastguard Worker #include "dynbuf.h"
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h" /* keep this as LAST include */
38*6236dae4SAndroid Build Coastguard Worker
39*6236dae4SAndroid Build Coastguard Worker /* only acknowledge colon or equals as separators if the option was not
40*6236dae4SAndroid Build Coastguard Worker specified with an initial dash! */
41*6236dae4SAndroid Build Coastguard Worker #define ISSEP(x,dash) (!dash && (((x) == '=') || ((x) == ':')))
42*6236dae4SAndroid Build Coastguard Worker
43*6236dae4SAndroid Build Coastguard Worker static const char *unslashquote(const char *line, char *param);
44*6236dae4SAndroid Build Coastguard Worker
45*6236dae4SAndroid Build Coastguard Worker #define MAX_CONFIG_LINE_LENGTH (10*1024*1024)
46*6236dae4SAndroid Build Coastguard Worker static bool my_get_line(FILE *fp, struct curlx_dynbuf *, bool *error);
47*6236dae4SAndroid Build Coastguard Worker
48*6236dae4SAndroid Build Coastguard Worker
49*6236dae4SAndroid Build Coastguard Worker /* return 0 on everything-is-fine, and non-zero otherwise */
parseconfig(const char * filename,struct GlobalConfig * global)50*6236dae4SAndroid Build Coastguard Worker int parseconfig(const char *filename, struct GlobalConfig *global)
51*6236dae4SAndroid Build Coastguard Worker {
52*6236dae4SAndroid Build Coastguard Worker FILE *file = NULL;
53*6236dae4SAndroid Build Coastguard Worker bool usedarg = FALSE;
54*6236dae4SAndroid Build Coastguard Worker int rc = 0;
55*6236dae4SAndroid Build Coastguard Worker struct OperationConfig *operation = global->last;
56*6236dae4SAndroid Build Coastguard Worker char *pathalloc = NULL;
57*6236dae4SAndroid Build Coastguard Worker
58*6236dae4SAndroid Build Coastguard Worker if(!filename) {
59*6236dae4SAndroid Build Coastguard Worker /* NULL means load .curlrc from homedir! */
60*6236dae4SAndroid Build Coastguard Worker char *curlrc = findfile(".curlrc", CURLRC_DOTSCORE);
61*6236dae4SAndroid Build Coastguard Worker if(curlrc) {
62*6236dae4SAndroid Build Coastguard Worker file = fopen(curlrc, FOPEN_READTEXT);
63*6236dae4SAndroid Build Coastguard Worker if(!file) {
64*6236dae4SAndroid Build Coastguard Worker free(curlrc);
65*6236dae4SAndroid Build Coastguard Worker return 1;
66*6236dae4SAndroid Build Coastguard Worker }
67*6236dae4SAndroid Build Coastguard Worker filename = pathalloc = curlrc;
68*6236dae4SAndroid Build Coastguard Worker }
69*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32 /* Windows */
70*6236dae4SAndroid Build Coastguard Worker else {
71*6236dae4SAndroid Build Coastguard Worker char *fullp;
72*6236dae4SAndroid Build Coastguard Worker /* check for .curlrc then _curlrc in the dir of the executable */
73*6236dae4SAndroid Build Coastguard Worker file = Curl_execpath(".curlrc", &fullp);
74*6236dae4SAndroid Build Coastguard Worker if(!file)
75*6236dae4SAndroid Build Coastguard Worker file = Curl_execpath("_curlrc", &fullp);
76*6236dae4SAndroid Build Coastguard Worker if(file)
77*6236dae4SAndroid Build Coastguard Worker /* this is the filename we read from */
78*6236dae4SAndroid Build Coastguard Worker filename = fullp;
79*6236dae4SAndroid Build Coastguard Worker }
80*6236dae4SAndroid Build Coastguard Worker #endif
81*6236dae4SAndroid Build Coastguard Worker }
82*6236dae4SAndroid Build Coastguard Worker else {
83*6236dae4SAndroid Build Coastguard Worker if(strcmp(filename, "-"))
84*6236dae4SAndroid Build Coastguard Worker file = fopen(filename, FOPEN_READTEXT);
85*6236dae4SAndroid Build Coastguard Worker else
86*6236dae4SAndroid Build Coastguard Worker file = stdin;
87*6236dae4SAndroid Build Coastguard Worker }
88*6236dae4SAndroid Build Coastguard Worker
89*6236dae4SAndroid Build Coastguard Worker if(file) {
90*6236dae4SAndroid Build Coastguard Worker char *line;
91*6236dae4SAndroid Build Coastguard Worker char *option;
92*6236dae4SAndroid Build Coastguard Worker char *param;
93*6236dae4SAndroid Build Coastguard Worker int lineno = 0;
94*6236dae4SAndroid Build Coastguard Worker bool dashed_option;
95*6236dae4SAndroid Build Coastguard Worker struct curlx_dynbuf buf;
96*6236dae4SAndroid Build Coastguard Worker bool fileerror = FALSE;
97*6236dae4SAndroid Build Coastguard Worker curlx_dyn_init(&buf, MAX_CONFIG_LINE_LENGTH);
98*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(filename);
99*6236dae4SAndroid Build Coastguard Worker
100*6236dae4SAndroid Build Coastguard Worker while(!rc && my_get_line(file, &buf, &fileerror)) {
101*6236dae4SAndroid Build Coastguard Worker ParameterError res;
102*6236dae4SAndroid Build Coastguard Worker bool alloced_param = FALSE;
103*6236dae4SAndroid Build Coastguard Worker lineno++;
104*6236dae4SAndroid Build Coastguard Worker line = curlx_dyn_ptr(&buf);
105*6236dae4SAndroid Build Coastguard Worker if(!line) {
106*6236dae4SAndroid Build Coastguard Worker rc = 1; /* out of memory */
107*6236dae4SAndroid Build Coastguard Worker break;
108*6236dae4SAndroid Build Coastguard Worker }
109*6236dae4SAndroid Build Coastguard Worker
110*6236dae4SAndroid Build Coastguard Worker /* line with # in the first non-blank column is a comment! */
111*6236dae4SAndroid Build Coastguard Worker while(*line && ISSPACE(*line))
112*6236dae4SAndroid Build Coastguard Worker line++;
113*6236dae4SAndroid Build Coastguard Worker
114*6236dae4SAndroid Build Coastguard Worker switch(*line) {
115*6236dae4SAndroid Build Coastguard Worker case '#':
116*6236dae4SAndroid Build Coastguard Worker case '/':
117*6236dae4SAndroid Build Coastguard Worker case '\r':
118*6236dae4SAndroid Build Coastguard Worker case '\n':
119*6236dae4SAndroid Build Coastguard Worker case '*':
120*6236dae4SAndroid Build Coastguard Worker case '\0':
121*6236dae4SAndroid Build Coastguard Worker curlx_dyn_reset(&buf);
122*6236dae4SAndroid Build Coastguard Worker continue;
123*6236dae4SAndroid Build Coastguard Worker }
124*6236dae4SAndroid Build Coastguard Worker
125*6236dae4SAndroid Build Coastguard Worker /* the option keywords starts here */
126*6236dae4SAndroid Build Coastguard Worker option = line;
127*6236dae4SAndroid Build Coastguard Worker
128*6236dae4SAndroid Build Coastguard Worker /* the option starts with a dash? */
129*6236dae4SAndroid Build Coastguard Worker dashed_option = (option[0] == '-');
130*6236dae4SAndroid Build Coastguard Worker
131*6236dae4SAndroid Build Coastguard Worker while(*line && !ISSPACE(*line) && !ISSEP(*line, dashed_option))
132*6236dae4SAndroid Build Coastguard Worker line++;
133*6236dae4SAndroid Build Coastguard Worker /* ... and has ended here */
134*6236dae4SAndroid Build Coastguard Worker
135*6236dae4SAndroid Build Coastguard Worker if(*line)
136*6236dae4SAndroid Build Coastguard Worker *line++ = '\0'; /* null-terminate, we have a local copy of the data */
137*6236dae4SAndroid Build Coastguard Worker
138*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUG_CONFIG
139*6236dae4SAndroid Build Coastguard Worker fprintf(tool_stderr, "GOT: %s\n", option);
140*6236dae4SAndroid Build Coastguard Worker #endif
141*6236dae4SAndroid Build Coastguard Worker
142*6236dae4SAndroid Build Coastguard Worker /* pass spaces and separator(s) */
143*6236dae4SAndroid Build Coastguard Worker while(*line && (ISSPACE(*line) || ISSEP(*line, dashed_option)))
144*6236dae4SAndroid Build Coastguard Worker line++;
145*6236dae4SAndroid Build Coastguard Worker
146*6236dae4SAndroid Build Coastguard Worker /* the parameter starts here (unless quoted) */
147*6236dae4SAndroid Build Coastguard Worker if(*line == '\"') {
148*6236dae4SAndroid Build Coastguard Worker /* quoted parameter, do the quote dance */
149*6236dae4SAndroid Build Coastguard Worker line++;
150*6236dae4SAndroid Build Coastguard Worker param = malloc(strlen(line) + 1); /* parameter */
151*6236dae4SAndroid Build Coastguard Worker if(!param) {
152*6236dae4SAndroid Build Coastguard Worker /* out of memory */
153*6236dae4SAndroid Build Coastguard Worker rc = 1;
154*6236dae4SAndroid Build Coastguard Worker break;
155*6236dae4SAndroid Build Coastguard Worker }
156*6236dae4SAndroid Build Coastguard Worker alloced_param = TRUE;
157*6236dae4SAndroid Build Coastguard Worker (void)unslashquote(line, param);
158*6236dae4SAndroid Build Coastguard Worker }
159*6236dae4SAndroid Build Coastguard Worker else {
160*6236dae4SAndroid Build Coastguard Worker param = line; /* parameter starts here */
161*6236dae4SAndroid Build Coastguard Worker while(*line && !ISSPACE(*line))
162*6236dae4SAndroid Build Coastguard Worker line++;
163*6236dae4SAndroid Build Coastguard Worker
164*6236dae4SAndroid Build Coastguard Worker if(*line) {
165*6236dae4SAndroid Build Coastguard Worker *line = '\0'; /* null-terminate */
166*6236dae4SAndroid Build Coastguard Worker
167*6236dae4SAndroid Build Coastguard Worker /* to detect mistakes better, see if there is data following */
168*6236dae4SAndroid Build Coastguard Worker line++;
169*6236dae4SAndroid Build Coastguard Worker /* pass all spaces */
170*6236dae4SAndroid Build Coastguard Worker while(*line && ISSPACE(*line))
171*6236dae4SAndroid Build Coastguard Worker line++;
172*6236dae4SAndroid Build Coastguard Worker
173*6236dae4SAndroid Build Coastguard Worker switch(*line) {
174*6236dae4SAndroid Build Coastguard Worker case '\0':
175*6236dae4SAndroid Build Coastguard Worker case '\r':
176*6236dae4SAndroid Build Coastguard Worker case '\n':
177*6236dae4SAndroid Build Coastguard Worker case '#': /* comment */
178*6236dae4SAndroid Build Coastguard Worker break;
179*6236dae4SAndroid Build Coastguard Worker default:
180*6236dae4SAndroid Build Coastguard Worker warnf(operation->global, "%s:%d: warning: '%s' uses unquoted "
181*6236dae4SAndroid Build Coastguard Worker "whitespace", filename, lineno, option);
182*6236dae4SAndroid Build Coastguard Worker warnf(operation->global, "This may cause side-effects. "
183*6236dae4SAndroid Build Coastguard Worker "Consider using double quotes?");
184*6236dae4SAndroid Build Coastguard Worker }
185*6236dae4SAndroid Build Coastguard Worker }
186*6236dae4SAndroid Build Coastguard Worker if(!*param)
187*6236dae4SAndroid Build Coastguard Worker /* do this so getparameter can check for required parameters.
188*6236dae4SAndroid Build Coastguard Worker Otherwise it always thinks there is a parameter. */
189*6236dae4SAndroid Build Coastguard Worker param = NULL;
190*6236dae4SAndroid Build Coastguard Worker }
191*6236dae4SAndroid Build Coastguard Worker
192*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUG_CONFIG
193*6236dae4SAndroid Build Coastguard Worker fprintf(tool_stderr, "PARAM: \"%s\"\n",(param ? param : "(null)"));
194*6236dae4SAndroid Build Coastguard Worker #endif
195*6236dae4SAndroid Build Coastguard Worker res = getparameter(option, param, NULL, &usedarg, global, operation);
196*6236dae4SAndroid Build Coastguard Worker operation = global->last;
197*6236dae4SAndroid Build Coastguard Worker
198*6236dae4SAndroid Build Coastguard Worker if(!res && param && *param && !usedarg)
199*6236dae4SAndroid Build Coastguard Worker /* we passed in a parameter that was not used! */
200*6236dae4SAndroid Build Coastguard Worker res = PARAM_GOT_EXTRA_PARAMETER;
201*6236dae4SAndroid Build Coastguard Worker
202*6236dae4SAndroid Build Coastguard Worker if(res == PARAM_NEXT_OPERATION) {
203*6236dae4SAndroid Build Coastguard Worker if(operation->url_list && operation->url_list->url) {
204*6236dae4SAndroid Build Coastguard Worker /* Allocate the next config */
205*6236dae4SAndroid Build Coastguard Worker operation->next = malloc(sizeof(struct OperationConfig));
206*6236dae4SAndroid Build Coastguard Worker if(operation->next) {
207*6236dae4SAndroid Build Coastguard Worker /* Initialise the newly created config */
208*6236dae4SAndroid Build Coastguard Worker config_init(operation->next);
209*6236dae4SAndroid Build Coastguard Worker
210*6236dae4SAndroid Build Coastguard Worker /* Set the global config pointer */
211*6236dae4SAndroid Build Coastguard Worker operation->next->global = global;
212*6236dae4SAndroid Build Coastguard Worker
213*6236dae4SAndroid Build Coastguard Worker /* Update the last operation pointer */
214*6236dae4SAndroid Build Coastguard Worker global->last = operation->next;
215*6236dae4SAndroid Build Coastguard Worker
216*6236dae4SAndroid Build Coastguard Worker /* Move onto the new config */
217*6236dae4SAndroid Build Coastguard Worker operation->next->prev = operation;
218*6236dae4SAndroid Build Coastguard Worker operation = operation->next;
219*6236dae4SAndroid Build Coastguard Worker }
220*6236dae4SAndroid Build Coastguard Worker else
221*6236dae4SAndroid Build Coastguard Worker res = PARAM_NO_MEM;
222*6236dae4SAndroid Build Coastguard Worker }
223*6236dae4SAndroid Build Coastguard Worker }
224*6236dae4SAndroid Build Coastguard Worker
225*6236dae4SAndroid Build Coastguard Worker if(res != PARAM_OK && res != PARAM_NEXT_OPERATION) {
226*6236dae4SAndroid Build Coastguard Worker /* the help request is not really an error */
227*6236dae4SAndroid Build Coastguard Worker if(!strcmp(filename, "-")) {
228*6236dae4SAndroid Build Coastguard Worker filename = "<stdin>";
229*6236dae4SAndroid Build Coastguard Worker }
230*6236dae4SAndroid Build Coastguard Worker if(res != PARAM_HELP_REQUESTED &&
231*6236dae4SAndroid Build Coastguard Worker res != PARAM_MANUAL_REQUESTED &&
232*6236dae4SAndroid Build Coastguard Worker res != PARAM_VERSION_INFO_REQUESTED &&
233*6236dae4SAndroid Build Coastguard Worker res != PARAM_ENGINES_REQUESTED &&
234*6236dae4SAndroid Build Coastguard Worker res != PARAM_CA_EMBED_REQUESTED) {
235*6236dae4SAndroid Build Coastguard Worker const char *reason = param2text(res);
236*6236dae4SAndroid Build Coastguard Worker errorf(operation->global, "%s:%d: '%s' %s",
237*6236dae4SAndroid Build Coastguard Worker filename, lineno, option, reason);
238*6236dae4SAndroid Build Coastguard Worker rc = (int)res;
239*6236dae4SAndroid Build Coastguard Worker }
240*6236dae4SAndroid Build Coastguard Worker }
241*6236dae4SAndroid Build Coastguard Worker
242*6236dae4SAndroid Build Coastguard Worker if(alloced_param)
243*6236dae4SAndroid Build Coastguard Worker Curl_safefree(param);
244*6236dae4SAndroid Build Coastguard Worker
245*6236dae4SAndroid Build Coastguard Worker curlx_dyn_reset(&buf);
246*6236dae4SAndroid Build Coastguard Worker }
247*6236dae4SAndroid Build Coastguard Worker curlx_dyn_free(&buf);
248*6236dae4SAndroid Build Coastguard Worker if(file != stdin)
249*6236dae4SAndroid Build Coastguard Worker fclose(file);
250*6236dae4SAndroid Build Coastguard Worker if(fileerror)
251*6236dae4SAndroid Build Coastguard Worker rc = 1;
252*6236dae4SAndroid Build Coastguard Worker }
253*6236dae4SAndroid Build Coastguard Worker else
254*6236dae4SAndroid Build Coastguard Worker rc = 1; /* could not open the file */
255*6236dae4SAndroid Build Coastguard Worker
256*6236dae4SAndroid Build Coastguard Worker free(pathalloc);
257*6236dae4SAndroid Build Coastguard Worker return rc;
258*6236dae4SAndroid Build Coastguard Worker }
259*6236dae4SAndroid Build Coastguard Worker
260*6236dae4SAndroid Build Coastguard Worker /*
261*6236dae4SAndroid Build Coastguard Worker * Copies the string from line to the buffer at param, unquoting
262*6236dae4SAndroid Build Coastguard Worker * backslash-quoted characters and NUL-terminating the output string.
263*6236dae4SAndroid Build Coastguard Worker * Stops at the first non-backslash-quoted double quote character or the
264*6236dae4SAndroid Build Coastguard Worker * end of the input string. param must be at least as long as the input
265*6236dae4SAndroid Build Coastguard Worker * string. Returns the pointer after the last handled input character.
266*6236dae4SAndroid Build Coastguard Worker */
unslashquote(const char * line,char * param)267*6236dae4SAndroid Build Coastguard Worker static const char *unslashquote(const char *line, char *param)
268*6236dae4SAndroid Build Coastguard Worker {
269*6236dae4SAndroid Build Coastguard Worker while(*line && (*line != '\"')) {
270*6236dae4SAndroid Build Coastguard Worker if(*line == '\\') {
271*6236dae4SAndroid Build Coastguard Worker char out;
272*6236dae4SAndroid Build Coastguard Worker line++;
273*6236dae4SAndroid Build Coastguard Worker
274*6236dae4SAndroid Build Coastguard Worker /* default is to output the letter after the backslash */
275*6236dae4SAndroid Build Coastguard Worker switch(out = *line) {
276*6236dae4SAndroid Build Coastguard Worker case '\0':
277*6236dae4SAndroid Build Coastguard Worker continue; /* this'll break out of the loop */
278*6236dae4SAndroid Build Coastguard Worker case 't':
279*6236dae4SAndroid Build Coastguard Worker out = '\t';
280*6236dae4SAndroid Build Coastguard Worker break;
281*6236dae4SAndroid Build Coastguard Worker case 'n':
282*6236dae4SAndroid Build Coastguard Worker out = '\n';
283*6236dae4SAndroid Build Coastguard Worker break;
284*6236dae4SAndroid Build Coastguard Worker case 'r':
285*6236dae4SAndroid Build Coastguard Worker out = '\r';
286*6236dae4SAndroid Build Coastguard Worker break;
287*6236dae4SAndroid Build Coastguard Worker case 'v':
288*6236dae4SAndroid Build Coastguard Worker out = '\v';
289*6236dae4SAndroid Build Coastguard Worker break;
290*6236dae4SAndroid Build Coastguard Worker }
291*6236dae4SAndroid Build Coastguard Worker *param++ = out;
292*6236dae4SAndroid Build Coastguard Worker line++;
293*6236dae4SAndroid Build Coastguard Worker }
294*6236dae4SAndroid Build Coastguard Worker else
295*6236dae4SAndroid Build Coastguard Worker *param++ = *line++;
296*6236dae4SAndroid Build Coastguard Worker }
297*6236dae4SAndroid Build Coastguard Worker *param = '\0'; /* always null-terminate */
298*6236dae4SAndroid Build Coastguard Worker return line;
299*6236dae4SAndroid Build Coastguard Worker }
300*6236dae4SAndroid Build Coastguard Worker
301*6236dae4SAndroid Build Coastguard Worker /*
302*6236dae4SAndroid Build Coastguard Worker * Reads a line from the given file, ensuring is NUL terminated.
303*6236dae4SAndroid Build Coastguard Worker */
my_get_line(FILE * fp,struct curlx_dynbuf * db,bool * error)304*6236dae4SAndroid Build Coastguard Worker static bool my_get_line(FILE *fp, struct curlx_dynbuf *db,
305*6236dae4SAndroid Build Coastguard Worker bool *error)
306*6236dae4SAndroid Build Coastguard Worker {
307*6236dae4SAndroid Build Coastguard Worker char buf[4096];
308*6236dae4SAndroid Build Coastguard Worker *error = FALSE;
309*6236dae4SAndroid Build Coastguard Worker do {
310*6236dae4SAndroid Build Coastguard Worker /* fgets() returns s on success, and NULL on error or when end of file
311*6236dae4SAndroid Build Coastguard Worker occurs while no characters have been read. */
312*6236dae4SAndroid Build Coastguard Worker if(!fgets(buf, sizeof(buf), fp))
313*6236dae4SAndroid Build Coastguard Worker /* only if there is data in the line, return TRUE */
314*6236dae4SAndroid Build Coastguard Worker return curlx_dyn_len(db);
315*6236dae4SAndroid Build Coastguard Worker if(curlx_dyn_add(db, buf)) {
316*6236dae4SAndroid Build Coastguard Worker *error = TRUE; /* error */
317*6236dae4SAndroid Build Coastguard Worker return FALSE; /* stop reading */
318*6236dae4SAndroid Build Coastguard Worker }
319*6236dae4SAndroid Build Coastguard Worker } while(!strchr(buf, '\n'));
320*6236dae4SAndroid Build Coastguard Worker
321*6236dae4SAndroid Build Coastguard Worker return TRUE; /* continue */
322*6236dae4SAndroid Build Coastguard Worker }
323