1e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/***************************************************************************
2e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *                                  _   _ ____  _
3e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *  Project                     ___| | | |  _ \| |
4e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *                             / __| | | | |_) | |
5e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *                            | (__| |_| |  _ <| |___
6e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *                             \___|\___/|_| \_\_____|
7e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
8e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
9e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
10e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is licensed as described in the file COPYING, which
11e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * you should have received as part of this distribution. The terms
128f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html.
13e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
14e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * copies of the Software, and permit persons to whom the Software is
16e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * furnished to do so, under the terms of the COPYING file.
17e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
18e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * KIND, either express or implied.
20e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET *
21e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ***************************************************************************/
22e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_setup.h"
23e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
24e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#define ENABLE_CURLX_PRINTF
25e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* use our own printf() functions */
26e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curlx.h"
27e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
28e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_cfgable.h"
29e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_getparam.h"
30e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_helpers.h"
31e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_homedir.h"
32e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_msgs.h"
33e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "tool_parsecfg.h"
34e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
35e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "memdebug.h" /* keep this as LAST include */
36e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
37e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#define CURLRC DOT_CHAR "curlrc"
38e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
39e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* only acknowledge colon or equals as separators if the option was not
40e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET   specified with an initial dash! */
41e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#define ISSEP(x,dash) (!dash && (((x) == '=') || ((x) == ':')))
42e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
43e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic const char *unslashquote(const char *line, char *param);
44e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic char *my_get_line(FILE *fp);
45e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
46e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* return 0 on everything-is-fine, and non-zero otherwise */
47e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETint parseconfig(const char *filename, struct GlobalConfig *global)
48e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{
49e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  int res;
50e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  FILE *file;
51e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  char filebuffer[512];
52e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  bool usedarg;
53e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  char *home;
54e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  int rc = 0;
55e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  struct OperationConfig *operation = global->first;
56e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
57e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(!filename || !*filename) {
58e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    /* NULL or no file name attempts to load .curlrc from the homedir! */
59e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
60e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifndef __AMIGA__
61e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    filename = CURLRC;   /* sensible default */
62e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    home = homedir();    /* portable homedir finder */
63e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(home) {
64e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(strlen(home) < (sizeof(filebuffer) - strlen(CURLRC))) {
65e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        snprintf(filebuffer, sizeof(filebuffer),
66e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                 "%s%s%s", home, DIR_CHAR, CURLRC);
67e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
68e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef WIN32
69e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        /* Check if the file exists - if not, try CURLRC in the same
70e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET         * directory as our executable
71e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET         */
72e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        file = fopen(filebuffer, FOPEN_READTEXT);
73e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        if(file != NULL) {
74e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          fclose(file);
75e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          filename = filebuffer;
76e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        }
77e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        else {
78e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          /* Get the filename of our executable. GetModuleFileName is
79e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET           * already declared via inclusions done in setup header file.
80e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET           * We assume that we are using the ASCII version here.
81e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET           */
82e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          int n = GetModuleFileName(0, filebuffer, sizeof(filebuffer));
83e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          if(n > 0 && n < (int)sizeof(filebuffer)) {
84e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            /* We got a valid filename - get the directory part */
85e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            char *lastdirchar = strrchr(filebuffer, '\\');
86e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            if(lastdirchar) {
87e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              size_t remaining;
88e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              *lastdirchar = 0;
89e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              /* If we have enough space, build the RC filename */
90e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              remaining = sizeof(filebuffer) - strlen(filebuffer);
91e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              if(strlen(CURLRC) < remaining - 1) {
92e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                snprintf(lastdirchar, remaining,
93e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                         "%s%s", DIR_CHAR, CURLRC);
94e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                /* Don't bother checking if it exists - we do
95e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                 * that later
96e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                 */
97e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                filename = filebuffer;
98e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET              }
99e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            }
100e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          }
101e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        }
102e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#else /* WIN32 */
103e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        filename = filebuffer;
104e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif /* WIN32 */
105e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
106e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      Curl_safefree(home); /* we've used it, now free it */
107e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    }
108e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
109e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET# else /* __AMIGA__ */
110e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    /* On AmigaOS all the config files are into env:
111e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET     */
112e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    filename = "ENV:" CURLRC;
113e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
114e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif
115e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  }
116e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
117e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(strcmp(filename, "-"))
118e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    file = fopen(filename, FOPEN_READTEXT);
119e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  else
120e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    file = stdin;
121e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
122e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(file) {
123e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    char *line;
124e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    char *aline;
125e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    char *option;
126e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    char *param;
127e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    int lineno = 0;
128e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    bool alloced_param;
129e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    bool dashed_option;
130e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
131e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    while(NULL != (aline = my_get_line(file))) {
132e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      lineno++;
133e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      line = aline;
134e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      alloced_param=FALSE;
135e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
136e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      /* line with # in the first non-blank column is a comment! */
137e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      while(*line && ISSPACE(*line))
138e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        line++;
139e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
140e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      switch(*line) {
141e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case '#':
142e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case '/':
143e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case '\r':
144e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case '\n':
145e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case '*':
146e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case '\0':
147e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        Curl_safefree(aline);
148e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        continue;
149e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
150e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
151e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      /* the option keywords starts here */
152e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      option = line;
153e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
154e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      /* the option starts with a dash? */
155e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      dashed_option = option[0]=='-'?TRUE:FALSE;
156e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
157e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      while(*line && !ISSPACE(*line) && !ISSEP(*line, dashed_option))
158e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        line++;
159e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      /* ... and has ended here */
160e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
161e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(*line)
162e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        *line++ = '\0'; /* zero terminate, we have a local copy of the data */
163e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
164e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef DEBUG_CONFIG
165e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      fprintf(stderr, "GOT: %s\n", option);
166e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif
167e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
168e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      /* pass spaces and separator(s) */
169e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      while(*line && (ISSPACE(*line) || ISSEP(*line, dashed_option)))
170e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        line++;
171e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
172e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      /* the parameter starts here (unless quoted) */
173e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(*line == '\"') {
174e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        /* quoted parameter, do the quote dance */
175e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        line++;
176e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        param = malloc(strlen(line) + 1); /* parameter */
177e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        if(!param) {
178e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          /* out of memory */
179e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          Curl_safefree(aline);
180e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          rc = 1;
181e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          break;
182e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        }
183e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        alloced_param = TRUE;
184e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        (void)unslashquote(line, param);
185e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
186e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      else {
187e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        param = line; /* parameter starts here */
188e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        while(*line && !ISSPACE(*line))
189e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          line++;
190e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
191e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        if(*line) {
192e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          *line = '\0'; /* zero terminate */
193e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
194e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          /* to detect mistakes better, see if there's data following */
195e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          line++;
196e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          /* pass all spaces */
197e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          while(*line && ISSPACE(*line))
198e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            line++;
199e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
200e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          switch(*line) {
201e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          case '\0':
202e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          case '\r':
203e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          case '\n':
204e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          case '#': /* comment */
205e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            break;
206e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          default:
207e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            warnf(operation->global, "%s:%d: warning: '%s' uses unquoted "
208e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                  "white space in the line that may cause side-effects!\n",
209e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                  filename, lineno, option);
210e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          }
211e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        }
212e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
213e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
214e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(!*param) {
215e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        /* do this so getparameter can check for required parameters.
216e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET           Otherwise it always thinks there's a parameter. */
217e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        if(alloced_param)
218e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          Curl_safefree(param);
219e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        param = NULL;
220e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
221e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
222e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef DEBUG_CONFIG
223e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      fprintf(stderr, "PARAM: \"%s\"\n",(param ? param : "(null)"));
224e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif
225e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      res = getparameter(option, param, &usedarg, global, operation);
226e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
227e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(param && *param && !usedarg)
228e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        /* we passed in a parameter that wasn't used! */
229e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        res = PARAM_GOT_EXTRA_PARAMETER;
230e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
231e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(res == PARAM_NEXT_OPERATION) {
232e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        if(operation->url_list && operation->url_list->url) {
233e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          /* Allocate the next config */
234e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          operation->next = malloc(sizeof(struct OperationConfig));
235e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          if(operation->next) {
236e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            /* Initialise the newly created config */
237e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            config_init(operation->next);
238e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
239e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            /* Copy the easy handle */
240e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            operation->next->easy = global->easy;
241e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
242e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            /* Set the global config pointer */
243e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            operation->next->global = global;
244e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
245e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            /* Update the last operation pointer */
246e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            global->last = operation->next;
247e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
248e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            /* Move onto the new config */
249e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            operation->next->prev = operation;
250e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            operation = operation->next;
251e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          }
252e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          else
253e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET            res = PARAM_NO_MEM;
254e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        }
255e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
256e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
257e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(res != PARAM_OK && res != PARAM_NEXT_OPERATION) {
258e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        /* the help request isn't really an error */
259e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        if(!strcmp(filename, "-")) {
260e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          filename = (char *)"<stdin>";
261e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        }
262e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        if(res != PARAM_HELP_REQUESTED &&
263e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET           res != PARAM_MANUAL_REQUESTED &&
264e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET           res != PARAM_VERSION_INFO_REQUESTED &&
265e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET           res != PARAM_ENGINES_REQUESTED) {
266e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          const char *reason = param2text(res);
267e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET          warnf(operation->global, "%s:%d: warning: '%s' %s\n",
268e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                filename, lineno, option, reason);
269e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        }
270e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
271e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
272e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(alloced_param)
273e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        Curl_safefree(param);
274e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
275e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      Curl_safefree(aline);
276e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    }
277e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(file != stdin)
278e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      fclose(file);
279e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  }
280e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  else
281e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    rc = 1; /* couldn't open the file */
282e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
283e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  return rc;
284e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET}
285e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
286e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/*
287e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Copies the string from line to the buffer at param, unquoting
288e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * backslash-quoted characters and NUL-terminating the output string.
289e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Stops at the first non-backslash-quoted double quote character or the
290e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * end of the input string. param must be at least as long as the input
291e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * string.  Returns the pointer after the last handled input character.
292e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */
293e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic const char *unslashquote(const char *line, char *param)
294e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{
295e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  while(*line && (*line != '\"')) {
296e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(*line == '\\') {
297e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      char out;
298e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      line++;
299e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
300e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      /* default is to output the letter after the backslash */
301e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      switch(out = *line) {
302e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case '\0':
303e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        continue; /* this'll break out of the loop */
304e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case 't':
305e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        out = '\t';
306e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        break;
307e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case 'n':
308e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        out = '\n';
309e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        break;
310e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case 'r':
311e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        out = '\r';
312e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        break;
313e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      case 'v':
314e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        out = '\v';
315e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        break;
316e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
317e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      *param++ = out;
318e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      line++;
319e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    }
320e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    else
321e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      *param++ = *line++;
322e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  }
323e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  *param = '\0'; /* always zero terminate */
324e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  return line;
325e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET}
326e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
327e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/*
328e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Reads a line from the given file, ensuring is NUL terminated.
329e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * The pointer must be freed by the caller.
330e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * NULL is returned on an out of memory condition.
331e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */
332e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic char *my_get_line(FILE *fp)
333e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{
334e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  char buf[4096];
335e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  char *nl = NULL;
336e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  char *line = NULL;
337e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
338e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  do {
339e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(NULL == fgets(buf, sizeof(buf), fp))
340e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      break;
341e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(!line) {
342e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      line = strdup(buf);
343e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(!line)
344e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        return NULL;
345e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    }
346e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    else {
347e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      char *ptr;
348e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      size_t linelen = strlen(line);
349e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      ptr = realloc(line, linelen + strlen(buf) + 1);
350e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      if(!ptr) {
351e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        Curl_safefree(line);
352e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET        return NULL;
353e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      }
354e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      line = ptr;
355e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      strcpy(&line[linelen], buf);
356e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    }
357e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    nl = strchr(line, '\n');
358e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  } while(!nl);
359e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
360e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(nl)
361e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    *nl = '\0';
362e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
363e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  return line;
364e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET}
365e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
366