1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
22 #include "tool_setup.h"
26 #define ENABLE_CURLX_PRINTF
27 /* use our own printf() functions */
30 #include "tool_cfgable.h"
31 #include "tool_getparam.h"
32 #include "tool_getpass.h"
33 #include "tool_homedir.h"
34 #include "tool_msgs.h"
35 #include "tool_paramhlp.h"
37 #include "memdebug.h" /* keep this as LAST include */
39 struct getout *new_getout(struct Configurable *config)
41 struct getout *node = calloc(1, sizeof(struct getout));
42 struct getout *last = config->url_last;
44 /* append this new node last in the list */
48 config->url_list = node; /* first node */
50 /* move the last pointer */
51 config->url_last = node;
53 node->flags = config->default_node_flags;
58 ParameterError file2string(char **bufp, FILE *file)
67 while(fgets(buffer, sizeof(buffer), file)) {
68 if((ptr = strchr(buffer, '\r')) != NULL)
70 if((ptr = strchr(buffer, '\n')) != NULL)
72 buflen = strlen(buffer);
73 if((ptr = realloc(string, stringlen+buflen+1)) == NULL) {
74 Curl_safefree(string);
78 strcpy(string+stringlen, buffer);
86 ParameterError file2memory(char **bufp, size_t *size, FILE *file)
96 if(!buffer || (alloc == nused)) {
97 /* size_t overflow detection for huge files */
98 if(alloc+1 > ((size_t)-1)/2) {
99 Curl_safefree(buffer);
103 /* allocate an extra char, reserved space, for null termination */
104 if((newbuf = realloc(buffer, alloc+1)) == NULL) {
105 Curl_safefree(buffer);
110 nread = fread(buffer+nused, 1, alloc-nused, file);
113 /* null terminate the buffer in case it's used as a string later */
114 buffer[nused] = '\0';
115 /* free trailing slack space, if possible */
117 if((newbuf = realloc(buffer, nused+1)) == NULL) {
118 Curl_safefree(buffer);
123 /* discard buffer if nothing was read */
125 Curl_safefree(buffer); /* no string */
133 void cleanarg(char *str)
135 #ifdef HAVE_WRITABLE_ARGV
136 /* now that GetStr has copied the contents of nextarg, wipe the next
137 * argument out so that the username:password isn't displayed in the
138 * system process list */
140 size_t len = strlen(str);
141 memset(str, ' ', len);
149 * Parse the string and write the long in the given address. Return PARAM_OK
150 * on success, otherwise a parameter specific error enum.
152 * Since this function gets called with the 'nextarg' pointer from within the
153 * getparameter a lot, we must check it for NULL before accessing the str
157 ParameterError str2num(long *val, const char *str)
161 long num = strtol(str, &endptr, 10);
162 if((endptr != str) && (endptr == str + strlen(str))) {
164 return PARAM_OK; /* Ok */
167 return PARAM_BAD_NUMERIC; /* badness */
171 * Parse the string and write the long in the given address. Return PARAM_OK
172 * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
174 * Since this function gets called with the 'nextarg' pointer from within the
175 * getparameter a lot, we must check it for NULL before accessing the str
179 ParameterError str2unum(long *val, const char *str)
181 ParameterError result = str2num(val, str);
182 if(result != PARAM_OK)
185 return PARAM_NEGATIVE_NUMERIC;
191 * Parse the string and write the double in the given address. Return PARAM_OK
192 * on success, otherwise a parameter specific error enum.
194 * Since this function gets called with the 'nextarg' pointer from within the
195 * getparameter a lot, we must check it for NULL before accessing the str
199 ParameterError str2double(double *val, const char *str)
203 double num = strtod(str, &endptr);
204 if((endptr != str) && (endptr == str + strlen(str))) {
206 return PARAM_OK; /* Ok */
209 return PARAM_BAD_NUMERIC; /* badness */
213 * Parse the string and write the double in the given address. Return PARAM_OK
214 * on success, otherwise a parameter error enum. ONLY ACCEPTS POSITIVE NUMBERS!
216 * Since this function gets called with the 'nextarg' pointer from within the
217 * getparameter a lot, we must check it for NULL before accessing the str
221 ParameterError str2udouble(double *val, const char *str)
223 ParameterError result = str2double(val, str);
224 if(result != PARAM_OK)
227 return PARAM_NEGATIVE_NUMERIC;
233 * Parse the string and modify the long in the given address. Return
234 * non-zero on failure, zero on success.
236 * The string is a list of protocols
238 * Since this function gets called with the 'nextarg' pointer from within the
239 * getparameter a lot, we must check it for NULL before accessing the str
243 long proto2num(struct Configurable *config, long *val, const char *str)
246 const char *sep = ",";
249 static struct sprotos {
253 { "all", CURLPROTO_ALL },
254 { "http", CURLPROTO_HTTP },
255 { "https", CURLPROTO_HTTPS },
256 { "ftp", CURLPROTO_FTP },
257 { "ftps", CURLPROTO_FTPS },
258 { "scp", CURLPROTO_SCP },
259 { "sftp", CURLPROTO_SFTP },
260 { "telnet", CURLPROTO_TELNET },
261 { "ldap", CURLPROTO_LDAP },
262 { "ldaps", CURLPROTO_LDAPS },
263 { "dict", CURLPROTO_DICT },
264 { "file", CURLPROTO_FILE },
265 { "tftp", CURLPROTO_TFTP },
266 { "imap", CURLPROTO_IMAP },
267 { "imaps", CURLPROTO_IMAPS },
268 { "pop3", CURLPROTO_POP3 },
269 { "pop3s", CURLPROTO_POP3S },
270 { "smtp", CURLPROTO_SMTP },
271 { "smtps", CURLPROTO_SMTPS },
272 { "rtsp", CURLPROTO_RTSP },
273 { "gopher", CURLPROTO_GOPHER },
280 buffer = strdup(str); /* because strtok corrupts it */
284 for(token = strtok(buffer, sep);
286 token = strtok(NULL, sep)) {
287 enum e_action { allow, deny, set } action = allow;
289 struct sprotos const *pp;
291 /* Process token modifiers */
292 while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
303 default: /* Includes case of terminating NULL */
304 Curl_safefree(buffer);
309 for(pp=protos; pp->name; pp++) {
310 if(curlx_raw_equal(token, pp->name)) {
326 if(!(pp->name)) { /* unknown protocol */
327 /* If they have specified only this protocol, we say treat it as
328 if no protocols are allowed */
331 warnf(config, "unrecognized protocol '%s'\n", token);
334 Curl_safefree(buffer);
339 * Parses the given string looking for an offset (which may be a
340 * larger-than-integer value). The offset CANNOT be negative!
342 * @param val the offset to populate
343 * @param str the buffer containing the offset
344 * @return PARAM_OK if successful, a parameter specific error enum if failure.
346 ParameterError str2offset(curl_off_t *val, const char *str)
350 /* offsets aren't negative, this indicates weird input */
351 return PARAM_NEGATIVE_NUMERIC;
353 #if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
354 *val = curlx_strtoofft(str, &endptr, 0);
355 if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (ERRNO == ERANGE))
356 return PARAM_BAD_NUMERIC;
358 *val = strtol(str, &endptr, 0);
359 if((*val == LONG_MIN || *val == LONG_MAX) && ERRNO == ERANGE)
360 return PARAM_BAD_NUMERIC;
362 if((endptr != str) && (endptr == str + strlen(str)))
365 return PARAM_BAD_NUMERIC;
368 ParameterError checkpasswd(const char *kind, /* for what purpose */
369 char **userpwd) /* pointer to allocated string */
377 /* Attempt to find the password separator */
378 psep = strchr(*userpwd, ':');
380 /* Attempt to find the options separator */
381 osep = strchr(*userpwd, ';');
383 if(!psep && **userpwd != ';') {
384 /* no password present, prompt for one */
385 char passwd[256] = "";
388 size_t userlen = strlen(*userpwd);
394 /* build a nice-looking prompt */
395 curlx_msnprintf(prompt, sizeof(prompt),
396 "Enter %s password for user '%s':",
400 getpass_r(prompt, passwd, sizeof(passwd));
401 passwdlen = strlen(passwd);
406 /* extend the allocated memory area to fit the password too */
407 passptr = realloc(*userpwd,
408 passwdlen + 1 + /* an extra for the colon */
409 userlen + 1); /* an extra for the zero */
413 /* append the password separated with a colon */
414 passptr[userlen] = ':';
415 memcpy(&passptr[userlen+1], passwd, passwdlen+1);
421 ParameterError add2list(struct curl_slist **list, const char *ptr)
423 struct curl_slist *newlist = curl_slist_append(*list, ptr);
432 int ftpfilemethod(struct Configurable *config, const char *str)
434 if(curlx_raw_equal("singlecwd", str))
435 return CURLFTPMETHOD_SINGLECWD;
436 if(curlx_raw_equal("nocwd", str))
437 return CURLFTPMETHOD_NOCWD;
438 if(curlx_raw_equal("multicwd", str))
439 return CURLFTPMETHOD_MULTICWD;
440 warnf(config, "unrecognized ftp file method '%s', using default\n", str);
441 return CURLFTPMETHOD_MULTICWD;
444 int ftpcccmethod(struct Configurable *config, const char *str)
446 if(curlx_raw_equal("passive", str))
447 return CURLFTPSSL_CCC_PASSIVE;
448 if(curlx_raw_equal("active", str))
449 return CURLFTPSSL_CCC_ACTIVE;
450 warnf(config, "unrecognized ftp CCC method '%s', using default\n", str);
451 return CURLFTPSSL_CCC_PASSIVE;
454 long delegation(struct Configurable *config, char *str)
456 if(curlx_raw_equal("none", str))
457 return CURLGSSAPI_DELEGATION_NONE;
458 if(curlx_raw_equal("policy", str))
459 return CURLGSSAPI_DELEGATION_POLICY_FLAG;
460 if(curlx_raw_equal("always", str))
461 return CURLGSSAPI_DELEGATION_FLAG;
462 warnf(config, "unrecognized delegation method '%s', using none\n", str);
463 return CURLGSSAPI_DELEGATION_NONE;