curl tool: code moved to tool_*.[ch] files
[platform/upstream/curl.git] / src / tool_paramhlp.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
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.
13  *
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.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 #include "setup.h"
23
24 #include <curl/curl.h>
25
26 #include "rawstr.h"
27
28 #define ENABLE_CURLX_PRINTF
29 /* use our own printf() functions */
30 #include "curlx.h"
31
32 #include "homedir.h"
33 #include "getpass.h"
34
35 #include "tool_cfgable.h"
36 #include "tool_getparam.h"
37 #include "tool_msgs.h"
38 #include "tool_paramhlp.h"
39
40 #include "memdebug.h" /* keep this as LAST include */
41
42 struct getout *new_getout(struct Configurable *config)
43 {
44   struct getout *node =malloc(sizeof(struct getout));
45   struct getout *last= config->url_last;
46   if(node) {
47     /* clear the struct */
48     memset(node, 0, sizeof(struct getout));
49
50     /* append this new node last in the list */
51     if(last)
52       last->next = node;
53     else
54       config->url_list = node; /* first node */
55
56     /* move the last pointer */
57     config->url_last = node;
58
59     node->flags = config->default_node_flags;
60   }
61   return node;
62 }
63
64 ParameterError file2string(char **bufp, FILE *file)
65 {
66   char buffer[256];
67   char *ptr;
68   char *string = NULL;
69   size_t stringlen = 0;
70   size_t buflen;
71
72   if(file) {
73     while(fgets(buffer, sizeof(buffer), file)) {
74       if((ptr = strchr(buffer, '\r')) != NULL)
75         *ptr = '\0';
76       if((ptr = strchr(buffer, '\n')) != NULL)
77         *ptr = '\0';
78       buflen = strlen(buffer);
79       if((ptr = realloc(string, stringlen+buflen+1)) == NULL) {
80         Curl_safefree(string);
81         return PARAM_NO_MEM;
82       }
83       string = ptr;
84       strcpy(string+stringlen, buffer);
85       stringlen += buflen;
86     }
87   }
88   *bufp = string;
89   return PARAM_OK;
90 }
91
92 ParameterError file2memory(char **bufp, size_t *size, FILE *file)
93 {
94   char *newbuf;
95   char *buffer = NULL;
96   size_t alloc = 512;
97   size_t nused = 0;
98   size_t nread;
99
100   if(file) {
101     do {
102       if(!buffer || (alloc == nused)) {
103         /* size_t overflow detection for huge files */
104         if(alloc+1 > ((size_t)-1)/2) {
105           Curl_safefree(buffer);
106           return PARAM_NO_MEM;
107         }
108         alloc *= 2;
109         /* allocate an extra char, reserved space, for null termination */
110         if((newbuf = realloc(buffer, alloc+1)) == NULL) {
111           Curl_safefree(buffer);
112           return PARAM_NO_MEM;
113         }
114         buffer = newbuf;
115       }
116       nread = fread(buffer+nused, 1, alloc-nused, file);
117       nused += nread;
118     } while(nread);
119     /* null terminate the buffer in case it's used as a string later */
120     buffer[nused] = '\0';
121     /* free trailing slack space, if possible */
122     if(alloc != nused) {
123       if((newbuf = realloc(buffer, nused+1)) != NULL)
124         buffer = newbuf;
125     }
126     /* discard buffer if nothing was read */
127     if(!nused) {
128       Curl_safefree(buffer); /* no string */
129     }
130   }
131   *size = nused;
132   *bufp = buffer;
133   return PARAM_OK;
134 }
135
136 void cleanarg(char *str)
137 {
138 #ifdef HAVE_WRITABLE_ARGV
139   /* now that GetStr has copied the contents of nextarg, wipe the next
140    * argument out so that the username:password isn't displayed in the
141    * system process list */
142   if(str) {
143     size_t len = strlen(str);
144     memset(str, ' ', len);
145   }
146 #else
147   (void)str;
148 #endif
149 }
150
151 /*
152  * Parse the string and write the integer in the given address. Return
153  * non-zero on failure, zero on success.
154  *
155  * The string must start with a digit to be valid.
156  *
157  * Since this function gets called with the 'nextarg' pointer from within the
158  * getparameter a lot, we must check it for NULL before accessing the str
159  * data.
160  */
161
162 int str2num(long *val, const char *str)
163 {
164   if(str && ISDIGIT(*str)) {
165     char *endptr;
166     long num = strtol(str, &endptr, 10);
167     if((endptr != str) && (endptr == str + strlen(str))) {
168       *val = num;
169       return 0;  /* Ok */
170     }
171   }
172   return 1; /* badness */
173 }
174
175 /*
176  * Parse the string and modify the long in the given address. Return
177  * non-zero on failure, zero on success.
178  *
179  * The string is a list of protocols
180  *
181  * Since this function gets called with the 'nextarg' pointer from within the
182  * getparameter a lot, we must check it for NULL before accessing the str
183  * data.
184  */
185
186 long proto2num(struct Configurable *config, long *val, const char *str)
187 {
188   char *buffer;
189   const char *sep = ",";
190   char *token;
191
192   static struct sprotos {
193     const char *name;
194     long bit;
195   } const protos[] = {
196     { "all", CURLPROTO_ALL },
197     { "http", CURLPROTO_HTTP },
198     { "https", CURLPROTO_HTTPS },
199     { "ftp", CURLPROTO_FTP },
200     { "ftps", CURLPROTO_FTPS },
201     { "scp", CURLPROTO_SCP },
202     { "sftp", CURLPROTO_SFTP },
203     { "telnet", CURLPROTO_TELNET },
204     { "ldap", CURLPROTO_LDAP },
205     { "ldaps", CURLPROTO_LDAPS },
206     { "dict", CURLPROTO_DICT },
207     { "file", CURLPROTO_FILE },
208     { "tftp", CURLPROTO_TFTP },
209     { "imap", CURLPROTO_IMAP },
210     { "imaps", CURLPROTO_IMAPS },
211     { "pop3", CURLPROTO_POP3 },
212     { "pop3s", CURLPROTO_POP3S },
213     { "smtp", CURLPROTO_SMTP },
214     { "smtps", CURLPROTO_SMTPS },
215     { "rtsp", CURLPROTO_RTSP },
216     { "gopher", CURLPROTO_GOPHER },
217     { NULL, 0 }
218   };
219
220   if(!str)
221     return 1;
222
223   buffer = strdup(str); /* because strtok corrupts it */
224
225   for(token = strtok(buffer, sep);
226       token;
227       token = strtok(NULL, sep)) {
228     enum e_action { allow, deny, set } action = allow;
229
230     struct sprotos const *pp;
231
232     /* Process token modifiers */
233     while(!ISALNUM(*token)) { /* may be NULL if token is all modifiers */
234       switch (*token++) {
235       case '=':
236         action = set;
237         break;
238       case '-':
239         action = deny;
240         break;
241       case '+':
242         action = allow;
243         break;
244       default: /* Includes case of terminating NULL */
245         Curl_safefree(buffer);
246         return 1;
247       }
248     }
249
250     for(pp=protos; pp->name; pp++) {
251       if(curlx_raw_equal(token, pp->name)) {
252         switch (action) {
253         case deny:
254           *val &= ~(pp->bit);
255           break;
256         case allow:
257           *val |= pp->bit;
258           break;
259         case set:
260           *val = pp->bit;
261           break;
262         }
263         break;
264       }
265     }
266
267     if(!(pp->name)) { /* unknown protocol */
268       /* If they have specified only this protocol, we say treat it as
269          if no protocols are allowed */
270       if(action == set)
271         *val = 0;
272       warnf(config, "unrecognized protocol '%s'\n", token);
273     }
274   }
275   Curl_safefree(buffer);
276   return 0;
277 }
278
279 /**
280  * Parses the given string looking for an offset (which may be
281  * a larger-than-integer value).
282  *
283  * @param val  the offset to populate
284  * @param str  the buffer containing the offset
285  * @return zero if successful, non-zero if failure.
286  */
287 int str2offset(curl_off_t *val, const char *str)
288 {
289 #if(CURL_SIZEOF_CURL_OFF_T > CURL_SIZEOF_LONG)
290   *val = curlx_strtoofft(str, NULL, 0);
291   if((*val == CURL_OFF_T_MAX || *val == CURL_OFF_T_MIN) && (ERRNO == ERANGE))
292     return 1;
293 #else
294   *val = strtol(str, NULL, 0);
295   if((*val == LONG_MIN || *val == LONG_MAX) && ERRNO == ERANGE)
296     return 1;
297 #endif
298   return 0;
299 }
300
301 void checkpasswd(const char *kind, /* for what purpose */
302                  char **userpwd)   /* pointer to allocated string */
303 {
304   char *ptr;
305   if(!*userpwd)
306     return;
307
308   ptr = strchr(*userpwd, ':');
309   if(!ptr) {
310     /* no password present, prompt for one */
311     char passwd[256]="";
312     char prompt[256];
313     size_t passwdlen;
314     size_t userlen = strlen(*userpwd);
315     char *passptr;
316
317     /* build a nice-looking prompt */
318     curlx_msnprintf(prompt, sizeof(prompt),
319                     "Enter %s password for user '%s':",
320                     kind, *userpwd);
321
322     /* get password */
323     getpass_r(prompt, passwd, sizeof(passwd));
324     passwdlen = strlen(passwd);
325
326     /* extend the allocated memory area to fit the password too */
327     passptr = realloc(*userpwd,
328                       passwdlen + 1 + /* an extra for the colon */
329                       userlen + 1);   /* an extra for the zero */
330
331     if(passptr) {
332       /* append the password separated with a colon */
333       passptr[userlen]=':';
334       memcpy(&passptr[userlen+1], passwd, passwdlen+1);
335       *userpwd = passptr;
336     }
337   }
338 }
339
340 ParameterError add2list(struct curl_slist **list, const char *ptr)
341 {
342   struct curl_slist *newlist = curl_slist_append(*list, ptr);
343   if(newlist)
344     *list = newlist;
345   else
346     return PARAM_NO_MEM;
347
348   return PARAM_OK;
349 }
350
351 int ftpfilemethod(struct Configurable *config, const char *str)
352 {
353   if(curlx_raw_equal("singlecwd", str))
354     return CURLFTPMETHOD_SINGLECWD;
355   if(curlx_raw_equal("nocwd", str))
356     return CURLFTPMETHOD_NOCWD;
357   if(curlx_raw_equal("multicwd", str))
358     return CURLFTPMETHOD_MULTICWD;
359   warnf(config, "unrecognized ftp file method '%s', using default\n", str);
360   return CURLFTPMETHOD_MULTICWD;
361 }
362
363 int ftpcccmethod(struct Configurable *config, const char *str)
364 {
365   if(curlx_raw_equal("passive", str))
366     return CURLFTPSSL_CCC_PASSIVE;
367   if(curlx_raw_equal("active", str))
368     return CURLFTPSSL_CCC_ACTIVE;
369   warnf(config, "unrecognized ftp CCC method '%s', using default\n", str);
370   return CURLFTPSSL_CCC_PASSIVE;
371 }
372
373 long delegation(struct Configurable *config, char *str)
374 {
375   if(curlx_raw_equal("none", str))
376     return CURLGSSAPI_DELEGATION_NONE;
377   if(curlx_raw_equal("policy", str))
378     return CURLGSSAPI_DELEGATION_POLICY_FLAG;
379   if(curlx_raw_equal("always", str))
380     return CURLGSSAPI_DELEGATION_FLAG;
381   warnf(config, "unrecognized delegation method '%s', using none\n", str);
382   return CURLGSSAPI_DELEGATION_NONE;
383 }
384