Disable hash check if neither OpenSSL nor GNUTLS is installed.
[platform/upstream/curl.git] / src / tool_operate.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2012, 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 "tool_setup.h"
23
24 #ifdef HAVE_UNISTD_H
25 #  include <unistd.h>
26 #endif
27
28 #ifdef HAVE_FCNTL_H
29 #  include <fcntl.h>
30 #endif
31
32 #ifdef HAVE_UTIME_H
33 #  include <utime.h>
34 #elif defined(HAVE_SYS_UTIME_H)
35 #  include <sys/utime.h>
36 #endif
37
38 #ifdef HAVE_LOCALE_H
39 #  include <locale.h>
40 #endif
41
42 #ifdef HAVE_NETINET_TCP_H
43 #  include <netinet/tcp.h>
44 #endif
45
46 #include "rawstr.h"
47
48 #define ENABLE_CURLX_PRINTF
49 /* use our own printf() functions */
50 #include "curlx.h"
51
52 #include "tool_binmode.h"
53 #include "tool_cfgable.h"
54 #include "tool_cb_dbg.h"
55 #include "tool_cb_hdr.h"
56 #include "tool_cb_prg.h"
57 #include "tool_cb_rea.h"
58 #include "tool_cb_see.h"
59 #include "tool_cb_wrt.h"
60 #include "tool_dirhie.h"
61 #include "tool_doswin.h"
62 #include "tool_easysrc.h"
63 #include "tool_getparam.h"
64 #include "tool_helpers.h"
65 #include "tool_homedir.h"
66 #include "tool_libinfo.h"
67 #include "tool_main.h"
68 #include "tool_msgs.h"
69 #include "tool_operate.h"
70 #include "tool_operhlp.h"
71 #include "tool_parsecfg.h"
72 #include "tool_setopt.h"
73 #include "tool_sleep.h"
74 #include "tool_urlglob.h"
75 #include "tool_util.h"
76 #include "tool_writeenv.h"
77 #include "tool_writeout.h"
78 #include "tool_xattr.h"
79
80 #include "memdebug.h" /* keep this as LAST include */
81
82 #define CURLseparator  "--_curl_--"
83
84 #ifndef O_BINARY
85 /* since O_BINARY as used in bitmasks, setting it to zero makes it usable in
86    source code but yet it doesn't ruin anything */
87 #  define O_BINARY 0
88 #endif
89
90 #define CURL_CA_CERT_ERRORMSG1                                              \
91   "More details here: http://curl.haxx.se/docs/sslcerts.html\n\n"           \
92   "curl performs SSL certificate verification by default, "                 \
93   "using a \"bundle\"\n"                                                    \
94   " of Certificate Authority (CA) public keys (CA certs). If the default\n" \
95   " bundle file isn't adequate, you can specify an alternate file\n"        \
96   " using the --cacert option.\n"
97
98 #define CURL_CA_CERT_ERRORMSG2                                              \
99   "If this HTTPS server uses a certificate signed by a CA represented in\n" \
100   " the bundle, the certificate verification probably failed due to a\n"    \
101   " problem with the certificate (it might be expired, or the name might\n" \
102   " not match the domain name in the URL).\n"                               \
103   "If you'd like to turn off curl's verification of the certificate, use\n" \
104   " the -k (or --insecure) option.\n"
105
106 static int is_fatal_error(int code)
107 {
108   switch(code) {
109   /* TODO: Should CURLE_SSL_CACERT be included as critical error ? */
110   case CURLE_FAILED_INIT:
111   case CURLE_OUT_OF_MEMORY:
112   case CURLE_UNKNOWN_OPTION:
113   case CURLE_FUNCTION_NOT_FOUND:
114   case CURLE_BAD_FUNCTION_ARGUMENT:
115     /* critical error */
116     return 1;
117   default:
118     break;
119   }
120   /* no error or not critical */
121   return 0;
122 }
123
124 int operate(struct Configurable *config, int argc, argv_item_t argv[])
125 {
126   char errorbuffer[CURL_ERROR_SIZE];
127   struct ProgressData progressbar;
128   struct getout *urlnode;
129
130   struct OutStruct heads;
131
132 #ifdef HAVE_LIBMETALINK
133   metalinkfile *mlfile_last = NULL;
134 #endif /* HAVE_LIBMETALINK */
135
136   CURL *curl = NULL;
137   char *httpgetfields = NULL;
138
139   bool stillflags;
140   int res = 0;
141   int i;
142
143   errorbuffer[0] = '\0';
144   /* default headers output stream is stdout */
145   memset(&heads, 0, sizeof(struct OutStruct));
146   heads.stream = stdout;
147   heads.config = config;
148
149   memory_tracking_init();
150
151   /*
152   ** Initialize curl library - do not call any libcurl functions before
153   ** this point. Note that the memory_tracking_init() magic above is an
154   ** exception, but then that's not part of the official public API.
155   */
156   if(main_init() != CURLE_OK) {
157     helpf(config->errors, "error initializing curl library\n");
158     return CURLE_FAILED_INIT;
159   }
160
161   /* Get libcurl info right away */
162   if(get_libcurl_info() != CURLE_OK) {
163     helpf(config->errors, "error retrieving curl library information\n");
164     main_free();
165     return CURLE_FAILED_INIT;
166   }
167
168   /* Get a curl handle to use for all forthcoming curl transfers */
169   curl = curl_easy_init();
170   if(!curl) {
171     helpf(config->errors, "error initializing curl easy handle\n");
172     main_free();
173     return CURLE_FAILED_INIT;
174   }
175   config->easy = curl;
176
177   /*
178   ** Beyond this point no return'ing from this function allowed.
179   ** Jump to label 'quit_curl' in order to abandon this function
180   ** from outside of nested loops further down below.
181   */
182
183   /* setup proper locale from environment */
184 #ifdef HAVE_SETLOCALE
185   setlocale(LC_ALL, "");
186 #endif
187
188   /* inits */
189   config->postfieldsize = -1;
190   config->showerror = -1; /* will show errors */
191   config->use_httpget = FALSE;
192   config->create_dirs = FALSE;
193   config->maxredirs = DEFAULT_MAXREDIRS;
194   config->proto = CURLPROTO_ALL; /* FIXME: better to read from library */
195   config->proto_present = FALSE;
196   config->proto_redir =
197     CURLPROTO_ALL & ~(CURLPROTO_FILE|CURLPROTO_SCP); /* not FILE or SCP */
198   config->proto_redir_present = FALSE;
199
200   if((argc > 1) &&
201      (!curlx_strnequal("--", argv[1], 2) && (argv[1][0] == '-')) &&
202      strchr(argv[1], 'q')) {
203     /*
204      * The first flag, that is not a verbose name, but a shortname
205      * and it includes the 'q' flag!
206      */
207     ;
208   }
209   else {
210     parseconfig(NULL, config); /* ignore possible failure */
211   }
212
213   if((argc < 2)  && !config->url_list) {
214     helpf(config->errors, NULL);
215     res = CURLE_FAILED_INIT;
216     goto quit_curl;
217   }
218
219   /* Parse options */
220   for(i = 1, stillflags = TRUE; i < argc; i++) {
221     if(stillflags &&
222        ('-' == argv[i][0])) {
223       char *nextarg;
224       bool passarg;
225       char *origopt = argv[i];
226
227       char *flag = argv[i];
228
229       if(curlx_strequal("--", argv[i]))
230         /* this indicates the end of the flags and thus enables the
231            following (URL) argument to start with -. */
232         stillflags = FALSE;
233       else {
234         nextarg = (i < (argc-1)) ? argv[i+1] : NULL;
235
236         res = getparameter(flag, nextarg, &passarg, config);
237         if(res) {
238           int retval = CURLE_OK;
239           if(res != PARAM_HELP_REQUESTED) {
240             const char *reason = param2text(res);
241             helpf(config->errors, "option %s: %s\n", origopt, reason);
242             retval = CURLE_FAILED_INIT;
243           }
244           res = retval;
245           goto quit_curl;
246         }
247
248         if(passarg) /* we're supposed to skip this */
249           i++;
250       }
251     }
252     else {
253       bool used;
254       /* just add the URL please */
255       res = getparameter((char *)"--url", argv[i], &used, config);
256       if(res)
257         goto quit_curl;
258     }
259   }
260
261   if((!config->url_list || !config->url_list->url) && !config->list_engines) {
262     helpf(config->errors, "no URL specified!\n");
263     res = CURLE_FAILED_INIT;
264     goto quit_curl;
265   }
266
267   if(!config->useragent)
268     config->useragent = my_useragent();
269   if(!config->useragent) {
270     helpf(config->errors, "out of memory\n");
271     res = CURLE_OUT_OF_MEMORY;
272     goto quit_curl;
273   }
274
275   /* On WIN32 we can't set the path to curl-ca-bundle.crt
276    * at compile time. So we look here for the file in two ways:
277    * 1: look at the environment variable CURL_CA_BUNDLE for a path
278    * 2: if #1 isn't found, use the windows API function SearchPath()
279    *    to find it along the app's path (includes app's dir and CWD)
280    *
281    * We support the environment variable thing for non-Windows platforms
282    * too. Just for the sake of it.
283    */
284   if(!config->cacert &&
285      !config->capath &&
286      !config->insecure_ok) {
287     char *env;
288     env = curlx_getenv("CURL_CA_BUNDLE");
289     if(env) {
290       config->cacert = strdup(env);
291       if(!config->cacert) {
292         curl_free(env);
293         helpf(config->errors, "out of memory\n");
294         res = CURLE_OUT_OF_MEMORY;
295         goto quit_curl;
296       }
297     }
298     else {
299       env = curlx_getenv("SSL_CERT_DIR");
300       if(env) {
301         config->capath = strdup(env);
302         if(!config->capath) {
303           curl_free(env);
304           helpf(config->errors, "out of memory\n");
305           res = CURLE_OUT_OF_MEMORY;
306           goto quit_curl;
307         }
308       }
309       else {
310         env = curlx_getenv("SSL_CERT_FILE");
311         if(env) {
312           config->cacert = strdup(env);
313           if(!config->cacert) {
314             curl_free(env);
315             helpf(config->errors, "out of memory\n");
316             res = CURLE_OUT_OF_MEMORY;
317             goto quit_curl;
318           }
319         }
320       }
321     }
322
323     if(env)
324       curl_free(env);
325 #ifdef WIN32
326     else {
327       res = FindWin32CACert(config, "curl-ca-bundle.crt");
328       if(res)
329         goto quit_curl;
330     }
331 #endif
332   }
333
334   if(config->postfields) {
335     if(config->use_httpget) {
336       /* Use the postfields data for a http get */
337       httpgetfields = strdup(config->postfields);
338       Curl_safefree(config->postfields);
339       if(!httpgetfields) {
340         helpf(config->errors, "out of memory\n");
341         res = CURLE_OUT_OF_MEMORY;
342         goto quit_curl;
343       }
344       if(SetHTTPrequest(config,
345                         (config->no_body?HTTPREQ_HEAD:HTTPREQ_GET),
346                         &config->httpreq)) {
347         res = PARAM_BAD_USE;
348         goto quit_curl;
349       }
350     }
351     else {
352       if(SetHTTPrequest(config, HTTPREQ_SIMPLEPOST, &config->httpreq)) {
353         res = PARAM_BAD_USE;
354         goto quit_curl;
355       }
356     }
357   }
358
359 #ifndef CURL_DISABLE_LIBCURL_OPTION
360   res = easysrc_init();
361   if(res) {
362     helpf(config->errors, "out of memory\n");
363     goto quit_curl;
364   }
365 #endif
366
367   if(config->list_engines) {
368     struct curl_slist *engines = NULL;
369     curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines);
370     list_engines(engines);
371     curl_slist_free_all(engines);
372     res = CURLE_OK;
373     goto quit_curl;
374   }
375
376   /* Single header file for all URLs */
377   if(config->headerfile) {
378     /* open file for output: */
379     if(!curlx_strequal(config->headerfile, "-")) {
380       FILE *newfile = fopen(config->headerfile, "wb");
381       if(!newfile) {
382         warnf(config, "Failed to open %s\n", config->headerfile);
383         res = CURLE_WRITE_ERROR;
384         goto quit_curl;
385       }
386       else {
387         heads.filename = config->headerfile;
388         heads.s_isreg = TRUE;
389         heads.fopened = TRUE;
390         heads.stream = newfile;
391       }
392     }
393   }
394
395   /*
396   ** Nested loops start here.
397   */
398
399   /* loop through the list of given URLs */
400
401   for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) {
402
403     int up; /* upload file counter within a single upload glob */
404     char *infiles; /* might be a glob pattern */
405     char *outfiles;
406     int infilenum;
407     URLGlob *inglob;
408
409     int metalink = 0; /* nonzero for metalink download. Put outside of
410                          HAVE_LIBMETALINK to reduce #ifdef */
411 #ifdef HAVE_LIBMETALINK
412     metalinkfile *mlfile;
413     metalink_resource *mlres;
414 #endif /* HAVE_LIBMETALINK */
415
416     outfiles = NULL;
417     infilenum = 1;
418     inglob = NULL;
419
420 #ifdef HAVE_LIBMETALINK
421     if(urlnode->flags & GETOUT_METALINK) {
422       metalink = 1;
423       if(mlfile_last == NULL) {
424         mlfile_last = config->metalinkfile_list;
425       }
426       mlfile = mlfile_last;
427       mlfile_last = mlfile_last->next;
428       mlres = mlfile->resource;
429     }
430     else {
431       mlfile = NULL;
432       mlres = NULL;
433     }
434 #endif /* HAVE_LIBMETALINK */
435
436     /* urlnode->url is the full URL (it might be NULL) */
437
438     if(!urlnode->url) {
439       /* This node has no URL. Free node data without destroying the
440          node itself nor modifying next pointer and continue to next */
441       Curl_safefree(urlnode->outfile);
442       Curl_safefree(urlnode->infile);
443       urlnode->flags = 0;
444       continue; /* next URL please */
445     }
446
447     /* save outfile pattern before expansion */
448     if(urlnode->outfile) {
449       outfiles = strdup(urlnode->outfile);
450       if(!outfiles) {
451         helpf(config->errors, "out of memory\n");
452         res = CURLE_OUT_OF_MEMORY;
453         break;
454       }
455     }
456
457     infiles = urlnode->infile;
458
459     if(!config->globoff && infiles) {
460       /* Unless explicitly shut off */
461       res = glob_url(&inglob, infiles, &infilenum,
462                      config->showerror?config->errors:NULL);
463       if(res) {
464         Curl_safefree(outfiles);
465         break;
466       }
467     }
468
469     /* Here's the loop for uploading multiple files within the same
470        single globbed string. If no upload, we enter the loop once anyway. */
471     for(up = 0 ; up < infilenum; up++) {
472
473       char *uploadfile; /* a single file, never a glob */
474       int separator;
475       URLGlob *urls;
476       int urlnum;
477
478       uploadfile = NULL;
479       separator = 0;
480       urls = NULL;
481       urlnum = 0;
482
483       if(!up && !infiles)
484         Curl_nop_stmt;
485       else {
486         if(inglob) {
487           res = glob_next_url(&uploadfile, inglob);
488           if(res == CURLE_OUT_OF_MEMORY)
489             helpf(config->errors, "out of memory\n");
490         }
491         else if(!up) {
492           uploadfile = strdup(infiles);
493           if(!uploadfile) {
494             helpf(config->errors, "out of memory\n");
495             res = CURLE_OUT_OF_MEMORY;
496           }
497         }
498         else
499           uploadfile = NULL;
500         if(!uploadfile)
501           break;
502       }
503
504 #ifdef HAVE_LIBMETALINK
505       if(metalink) {
506         /* For Metalink download, we don't use glob. Instead we use
507            the number of resources as urlnum. */
508         urlnum = count_next_metalink_resource(mlfile);
509       }
510       else
511 #endif /* HAVE_LIBMETALINK */
512       if(!config->globoff) {
513         /* Unless explicitly shut off, we expand '{...}' and '[...]'
514            expressions and return total number of URLs in pattern set */
515         res = glob_url(&urls, urlnode->url, &urlnum,
516                        config->showerror?config->errors:NULL);
517         if(res) {
518           Curl_safefree(uploadfile);
519           break;
520         }
521       }
522       else
523         urlnum = 1; /* without globbing, this is a single URL */
524
525       /* if multiple files extracted to stdout, insert separators! */
526       separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1);
527
528       /* Here's looping around each globbed URL */
529       for(i = 0 ; i < urlnum; i++) {
530
531         int infd;
532         bool infdopen;
533         char *outfile;
534         struct OutStruct outs;
535         struct InStruct input;
536         struct timeval retrystart;
537         curl_off_t uploadfilesize;
538         long retry_numretries;
539         long retry_sleep_default;
540         long retry_sleep;
541         char *this_url;
542         HeaderData hdrdata;
543 #ifdef HAVE_LIBMETALINK
544         int metalink_next_res = 0;
545 #endif /* HAVE_LIBMETALINK */
546
547         outfile = NULL;
548         infdopen = FALSE;
549         infd = STDIN_FILENO;
550         uploadfilesize = -1; /* -1 means unknown */
551
552         /* default output stream is stdout */
553         memset(&outs, 0, sizeof(struct OutStruct));
554         outs.stream = stdout;
555         outs.config = config;
556
557 #ifdef HAVE_LIBMETALINK
558         if(metalink) {
559           /* For Metalink download, use name in Metalink file as
560              filename. */
561           outfile = strdup(mlfile->filename);
562           if(!outfile) {
563             res = CURLE_OUT_OF_MEMORY;
564             goto show_error;
565           }
566           this_url = strdup(mlres->url);
567           if(!this_url) {
568             res = CURLE_OUT_OF_MEMORY;
569             goto show_error;
570           }
571         }
572         else {
573 #endif /* HAVE_LIBMETALINK */
574           if(urls) {
575             res = glob_next_url(&this_url, urls);
576             if(res)
577               goto show_error;
578           }
579           else if(!i) {
580             this_url = strdup(urlnode->url);
581             if(!this_url) {
582               res = CURLE_OUT_OF_MEMORY;
583               goto show_error;
584             }
585           }
586           else
587             this_url = NULL;
588           if(!this_url)
589             break;
590
591           if(outfiles) {
592             outfile = strdup(outfiles);
593             if(!outfile) {
594               res = CURLE_OUT_OF_MEMORY;
595               goto show_error;
596             }
597           }
598 #ifdef HAVE_LIBMETALINK
599         }
600 #endif /* HAVE_LIBMETALINK */
601
602         if((urlnode->flags&GETOUT_USEREMOTE) ||
603            (outfile && !curlx_strequal("-", outfile)) ) {
604
605           /*
606            * We have specified a file name to store the result in, or we have
607            * decided we want to use the remote file name.
608            */
609
610           if(!outfile) {
611             /* extract the file name from the URL */
612             res = get_url_file_name(&outfile, this_url);
613             if(res)
614               goto show_error;
615             if((!outfile || !*outfile) && !config->content_disposition) {
616               helpf(config->errors, "Remote file name has no length!\n");
617               res = CURLE_WRITE_ERROR;
618               goto quit_urls;
619             }
620 #if defined(MSDOS) || defined(WIN32)
621             /* For DOS and WIN32, we do some major replacing of
622                bad characters in the file name before using it */
623             outfile = sanitize_dos_name(outfile);
624             if(!outfile) {
625               res = CURLE_OUT_OF_MEMORY;
626               goto show_error;
627             }
628 #endif /* MSDOS || WIN32 */
629           }
630           else if(urls) {
631             /* fill '#1' ... '#9' terms from URL pattern */
632             char *storefile = outfile;
633             res = glob_match_url(&outfile, storefile, urls);
634             Curl_safefree(storefile);
635             if(res) {
636               /* bad globbing */
637               warnf(config, "bad output glob!\n");
638               goto quit_urls;
639             }
640           }
641
642           /* Create the directory hierarchy, if not pre-existent to a multiple
643              file output call */
644
645           if(config->create_dirs || metalink) {
646             res = create_dir_hierarchy(outfile, config->errors);
647             /* create_dir_hierarchy shows error upon CURLE_WRITE_ERROR */
648             if(res == CURLE_WRITE_ERROR)
649               goto quit_urls;
650             if(res) {
651               goto show_error;
652             }
653           }
654
655           if((urlnode->flags & GETOUT_USEREMOTE)
656              && config->content_disposition) {
657             /* Our header callback MIGHT set the filename */
658             DEBUGASSERT(!outs.filename);
659           }
660
661           if(config->resume_from_current) {
662             /* We're told to continue from where we are now. Get the size
663                of the file as it is now and open it for append instead */
664             struct_stat fileinfo;
665             /* VMS -- Danger, the filesize is only valid for stream files */
666             if(0 == stat(outfile, &fileinfo))
667               /* set offset to current file size: */
668               config->resume_from = fileinfo.st_size;
669             else
670               /* let offset be 0 */
671               config->resume_from = 0;
672           }
673
674           if(config->resume_from) {
675             /* open file for output: */
676             FILE *file = fopen(outfile, config->resume_from?"ab":"wb");
677             if(!file) {
678               helpf(config->errors, "Can't open '%s'!\n", outfile);
679               res = CURLE_WRITE_ERROR;
680               goto quit_urls;
681             }
682             outs.fopened = TRUE;
683             outs.stream = file;
684             outs.init = config->resume_from;
685           }
686           else {
687             outs.stream = NULL; /* open when needed */
688           }
689           outs.filename = outfile;
690           outs.s_isreg = TRUE;
691         }
692
693         if(uploadfile && !stdin_upload(uploadfile)) {
694           /*
695            * We have specified a file to upload and it isn't "-".
696            */
697           struct_stat fileinfo;
698
699           this_url = add_file_name_to_url(curl, this_url, uploadfile);
700           if(!this_url) {
701             res = CURLE_OUT_OF_MEMORY;
702             goto show_error;
703           }
704           /* VMS Note:
705            *
706            * Reading binary from files can be a problem...  Only FIXED, VAR
707            * etc WITHOUT implied CC will work Others need a \n appended to a
708            * line
709            *
710            * - Stat gives a size but this is UNRELIABLE in VMS As a f.e. a
711            * fixed file with implied CC needs to have a byte added for every
712            * record processed, this can by derived from Filesize & recordsize
713            * for VARiable record files the records need to be counted!  for
714            * every record add 1 for linefeed and subtract 2 for the record
715            * header for VARIABLE header files only the bare record data needs
716            * to be considered with one appended if implied CC
717            */
718
719           infd = open(uploadfile, O_RDONLY | O_BINARY);
720           if((infd == -1) || fstat(infd, &fileinfo)) {
721             helpf(config->errors, "Can't open '%s'!\n", uploadfile);
722             if(infd != -1) {
723               close(infd);
724               infd = STDIN_FILENO;
725             }
726             res = CURLE_READ_ERROR;
727             goto quit_urls;
728           }
729           infdopen = TRUE;
730
731           /* we ignore file size for char/block devices, sockets, etc. */
732           if(S_ISREG(fileinfo.st_mode))
733             uploadfilesize = fileinfo.st_size;
734
735         }
736         else if(uploadfile && stdin_upload(uploadfile)) {
737           /* count to see if there are more than one auth bit set
738              in the authtype field */
739           int authbits = 0;
740           int bitcheck = 0;
741           while(bitcheck < 32) {
742             if(config->authtype & (1UL << bitcheck++)) {
743               authbits++;
744               if(authbits > 1) {
745                 /* more than one, we're done! */
746                 break;
747               }
748             }
749           }
750
751           /*
752            * If the user has also selected --anyauth or --proxy-anyauth
753            * we should warn him/her.
754            */
755           if(config->proxyanyauth || (authbits>1)) {
756             warnf(config,
757                   "Using --anyauth or --proxy-anyauth with upload from stdin"
758                   " involves a big risk of it not working. Use a temporary"
759                   " file or a fixed auth type instead!\n");
760           }
761
762           DEBUGASSERT(infdopen == FALSE);
763           DEBUGASSERT(infd == STDIN_FILENO);
764
765           set_binmode(stdin);
766           if(curlx_strequal(uploadfile, ".")) {
767             if(curlx_nonblock((curl_socket_t)infd, TRUE) < 0)
768               warnf(config,
769                     "fcntl failed on fd=%d: %s\n", infd, strerror(errno));
770           }
771         }
772
773         if(uploadfile && config->resume_from_current)
774           config->resume_from = -1; /* -1 will then force get-it-yourself */
775
776         if(output_expected(this_url, uploadfile)
777            && outs.stream && isatty(fileno(outs.stream)))
778           /* we send the output to a tty, therefore we switch off the progress
779              meter */
780           config->noprogress = config->isatty = TRUE;
781
782         if(urlnum > 1 && !(config->mute)) {
783           fprintf(config->errors, "\n[%d/%d]: %s --> %s\n",
784                   i+1, urlnum, this_url, outfile ? outfile : "<stdout>");
785           if(separator)
786             printf("%s%s\n", CURLseparator, this_url);
787         }
788         if(httpgetfields) {
789           char *urlbuffer;
790           /* Find out whether the url contains a file name */
791           const char *pc = strstr(this_url, "://");
792           char sep = '?';
793           if(pc)
794             pc += 3;
795           else
796             pc = this_url;
797
798           pc = strrchr(pc, '/'); /* check for a slash */
799
800           if(pc) {
801             /* there is a slash present in the URL */
802
803             if(strchr(pc, '?'))
804               /* Ouch, there's already a question mark in the URL string, we
805                  then append the data with an ampersand separator instead! */
806               sep='&';
807           }
808           /*
809            * Then append ? followed by the get fields to the url.
810            */
811           urlbuffer = malloc(strlen(this_url) + strlen(httpgetfields) + 3);
812           if(!urlbuffer) {
813             res = CURLE_OUT_OF_MEMORY;
814             goto show_error;
815           }
816           if(pc)
817             sprintf(urlbuffer, "%s%c%s", this_url, sep, httpgetfields);
818           else
819             /* Append  / before the ? to create a well-formed url
820                if the url contains a hostname only
821             */
822             sprintf(urlbuffer, "%s/?%s", this_url, httpgetfields);
823
824           Curl_safefree(this_url); /* free previous URL */
825           this_url = urlbuffer; /* use our new URL instead! */
826         }
827
828         if(!config->errors)
829           config->errors = stderr;
830
831         if((!outfile || !strcmp(outfile, "-")) && !config->use_ascii) {
832           /* We get the output to stdout and we have not got the ASCII/text
833              flag, then set stdout to be binary */
834           set_binmode(stdout);
835         }
836
837         if(config->tcp_nodelay)
838           my_setopt(curl, CURLOPT_TCP_NODELAY, 1);
839
840         /* where to store */
841         my_setopt(curl, CURLOPT_WRITEDATA, &outs);
842         /* what call to write */
843         my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
844
845         /* for uploads */
846         input.fd = infd;
847         input.config = config;
848         /* Note that if CURLOPT_READFUNCTION is fread (the default), then
849          * lib/telnet.c will Curl_poll() on the input file descriptor
850          * rather then calling the READFUNCTION at regular intervals.
851          * The circumstances in which it is preferable to enable this
852          * behaviour, by omitting to set the READFUNCTION & READDATA options,
853          * have not been determined.
854          */
855         my_setopt(curl, CURLOPT_READDATA, &input);
856         /* what call to read */
857         my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
858
859         /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
860            CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
861         my_setopt(curl, CURLOPT_SEEKDATA, &input);
862         my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
863
864         if(config->recvpersecond)
865           /* tell libcurl to use a smaller sized buffer as it allows us to
866              make better sleeps! 7.9.9 stuff! */
867           my_setopt(curl, CURLOPT_BUFFERSIZE, config->recvpersecond);
868
869         /* size of uploaded file: */
870         if(uploadfilesize != -1)
871           my_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadfilesize);
872         my_setopt_str(curl, CURLOPT_URL, this_url);     /* what to fetch */
873         my_setopt(curl, CURLOPT_NOPROGRESS, config->noprogress);
874         if(config->no_body) {
875           my_setopt(curl, CURLOPT_NOBODY, 1);
876           my_setopt(curl, CURLOPT_HEADER, 1);
877         }
878         else
879           my_setopt(curl, CURLOPT_HEADER, config->include_headers);
880
881 #if !defined(CURL_DISABLE_PROXY)
882         {
883           /* TODO: Make this a run-time check instead of compile-time one. */
884
885           my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
886           my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
887
888           /* new in libcurl 7.3 */
889           my_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
890
891           /* new in libcurl 7.5 */
892           if(config->proxy)
893             my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver);
894
895           /* new in libcurl 7.10 */
896           if(config->socksproxy) {
897             my_setopt_str(curl, CURLOPT_PROXY, config->socksproxy);
898             my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->socksver);
899           }
900
901           /* new in libcurl 7.10.6 */
902           if(config->proxyanyauth)
903             my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
904                               (long) CURLAUTH_ANY);
905           else if(config->proxynegotiate)
906             my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
907                               (long) CURLAUTH_GSSNEGOTIATE);
908           else if(config->proxyntlm)
909             my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
910                               (long) CURLAUTH_NTLM);
911           else if(config->proxydigest)
912             my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
913                               (long) CURLAUTH_DIGEST);
914           else if(config->proxybasic)
915             my_setopt_bitmask(curl, CURLOPT_PROXYAUTH,
916                               (long) CURLAUTH_BASIC);
917
918           /* new in libcurl 7.19.4 */
919           my_setopt(curl, CURLOPT_NOPROXY, config->noproxy);
920         }
921 #endif
922
923         my_setopt(curl, CURLOPT_FAILONERROR, config->failonerror);
924         my_setopt(curl, CURLOPT_UPLOAD, uploadfile?TRUE:FALSE);
925         my_setopt(curl, CURLOPT_DIRLISTONLY, config->dirlistonly);
926         my_setopt(curl, CURLOPT_APPEND, config->ftp_append);
927
928         if(config->netrc_opt)
929           my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
930         else if(config->netrc || config->netrc_file)
931           my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
932         else
933           my_setopt(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED);
934
935         if(config->netrc_file)
936           my_setopt(curl, CURLOPT_NETRC_FILE, config->netrc_file);
937
938         my_setopt(curl, CURLOPT_TRANSFERTEXT, config->use_ascii);
939         my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd);
940         my_setopt_str(curl, CURLOPT_RANGE, config->range);
941         my_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
942         my_setopt(curl, CURLOPT_TIMEOUT, config->timeout);
943
944         if(built_in_protos & CURLPROTO_HTTP) {
945
946           long postRedir = 0;
947
948           my_setopt(curl, CURLOPT_FOLLOWLOCATION,
949                     config->followlocation);
950           my_setopt(curl, CURLOPT_UNRESTRICTED_AUTH,
951                     config->unrestricted_auth);
952
953           switch(config->httpreq) {
954           case HTTPREQ_SIMPLEPOST:
955             my_setopt_str(curl, CURLOPT_POSTFIELDS,
956                           config->postfields);
957             my_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
958                       config->postfieldsize);
959             break;
960           case HTTPREQ_POST:
961             my_setopt_httppost(curl, CURLOPT_HTTPPOST, config->httppost);
962             break;
963           default:
964             break;
965           }
966
967           my_setopt_str(curl, CURLOPT_REFERER, config->referer);
968           my_setopt(curl, CURLOPT_AUTOREFERER, config->autoreferer);
969           my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
970           my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
971
972           /* new in libcurl 7.5 */
973           my_setopt(curl, CURLOPT_MAXREDIRS, config->maxredirs);
974
975           /* new in libcurl 7.9.1 */
976           if(config->httpversion)
977             my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
978
979           /* new in libcurl 7.10.6 (default is Basic) */
980           if(config->authtype)
981             my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, (long) config->authtype);
982
983           /* curl 7.19.1 (the 301 version existed in 7.18.2),
984              303 was added in 7.26.0 */
985           if(config->post301)
986             postRedir |= CURL_REDIR_POST_301;
987           if(config->post302)
988             postRedir |= CURL_REDIR_POST_302;
989           if(config->post303)
990             postRedir |= CURL_REDIR_POST_303;
991           my_setopt(curl, CURLOPT_POSTREDIR, postRedir);
992
993           /* new in libcurl 7.21.6 */
994           if(config->encoding)
995             my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, "");
996
997           /* new in libcurl 7.21.6 */
998           if(config->tr_encoding)
999             my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1);
1000
1001         } /* (built_in_protos & CURLPROTO_HTTP) */
1002
1003         my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
1004         my_setopt(curl, CURLOPT_LOW_SPEED_LIMIT,
1005                   config->low_speed_limit);
1006         my_setopt(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
1007         my_setopt(curl, CURLOPT_MAX_SEND_SPEED_LARGE,
1008                   config->sendpersecond);
1009         my_setopt(curl, CURLOPT_MAX_RECV_SPEED_LARGE,
1010                   config->recvpersecond);
1011         my_setopt(curl, CURLOPT_RESUME_FROM_LARGE,
1012                   config->use_resume?config->resume_from:0);
1013
1014         my_setopt(curl, CURLOPT_SSLCERT, config->cert);
1015         my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
1016         my_setopt(curl, CURLOPT_SSLKEY, config->key);
1017         my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
1018         my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
1019
1020         if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
1021
1022           /* SSH and SSL private key uses same command-line option */
1023           /* new in libcurl 7.16.1 */
1024           my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
1025           /* new in libcurl 7.16.1 */
1026           my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
1027
1028           /* new in libcurl 7.17.1: SSH host key md5 checking allows us
1029              to fail if we are not talking to who we think we should */
1030           my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
1031                         config->hostpubmd5);
1032         }
1033
1034         if(config->cacert)
1035           my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
1036         if(config->capath)
1037           my_setopt_str(curl, CURLOPT_CAPATH, config->capath);
1038         if(config->crlfile)
1039           my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
1040
1041         if(curlinfo->features & CURL_VERSION_SSL) {
1042           if(config->insecure_ok) {
1043             my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
1044             my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1L);
1045           }
1046           else {
1047             my_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
1048             /* libcurl default is strict verifyhost -> 2L   */
1049             /* my_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); */
1050           }
1051         }
1052
1053         if(built_in_protos & (CURLPROTO_SCP|CURLPROTO_SFTP)) {
1054           if(!config->insecure_ok) {
1055             char *home;
1056             char *file;
1057             res = CURLE_OUT_OF_MEMORY;
1058             home = homedir();
1059             if(home) {
1060               file = aprintf("%s/%sssh/known_hosts", home, DOT_CHAR);
1061               if(file) {
1062                 /* new in curl 7.19.6 */
1063                 res = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, file);
1064                 curl_free(file);
1065                 if(res == CURLE_UNKNOWN_OPTION)
1066                   /* libssh2 version older than 1.1.1 */
1067                   res = CURLE_OK;
1068               }
1069               Curl_safefree(home);
1070             }
1071             if(res)
1072               goto show_error;
1073           }
1074         }
1075
1076         if(config->no_body || config->remote_time) {
1077           /* no body or use remote time */
1078           my_setopt(curl, CURLOPT_FILETIME, TRUE);
1079         }
1080
1081         my_setopt(curl, CURLOPT_CRLF, config->crlf);
1082         my_setopt_slist(curl, CURLOPT_QUOTE, config->quote);
1083         my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
1084         my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
1085
1086 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
1087         {
1088           /* TODO: Make this a run-time check instead of compile-time one. */
1089
1090           if(config->cookie)
1091             my_setopt_str(curl, CURLOPT_COOKIE, config->cookie);
1092
1093           if(config->cookiefile)
1094             my_setopt_str(curl, CURLOPT_COOKIEFILE, config->cookiefile);
1095
1096           /* new in libcurl 7.9 */
1097           if(config->cookiejar)
1098             my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar);
1099
1100           /* new in libcurl 7.9.7 */
1101           my_setopt(curl, CURLOPT_COOKIESESSION, config->cookiesession);
1102         }
1103 #endif
1104
1105         my_setopt_enum(curl, CURLOPT_SSLVERSION, config->ssl_version);
1106         my_setopt_enum(curl, CURLOPT_TIMECONDITION, config->timecond);
1107         my_setopt(curl, CURLOPT_TIMEVALUE, config->condtime);
1108         my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
1109         my_setopt(curl, CURLOPT_STDERR, config->errors);
1110
1111         /* three new ones in libcurl 7.3: */
1112         my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
1113         my_setopt_str(curl, CURLOPT_KRBLEVEL, config->krblevel);
1114
1115         progressbarinit(&progressbar, config);
1116         if((config->progressmode == CURL_PROGRESS_BAR) &&
1117            !config->noprogress && !config->mute) {
1118           /* we want the alternative style, then we have to implement it
1119              ourselves! */
1120           my_setopt(curl, CURLOPT_PROGRESSFUNCTION, tool_progress_cb);
1121           my_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
1122         }
1123
1124         /* new in libcurl 7.6.2: */
1125         my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
1126
1127         /* new in libcurl 7.7: */
1128         my_setopt_str(curl, CURLOPT_RANDOM_FILE, config->random_file);
1129         my_setopt(curl, CURLOPT_EGDSOCKET, config->egd_file);
1130         my_setopt(curl, CURLOPT_CONNECTTIMEOUT, config->connecttimeout);
1131
1132         if(config->cipher_list)
1133           my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);
1134
1135         /* new in libcurl 7.9.2: */
1136         if(config->disable_epsv)
1137           /* disable it */
1138           my_setopt(curl, CURLOPT_FTP_USE_EPSV, FALSE);
1139
1140         /* new in libcurl 7.10.5 */
1141         if(config->disable_eprt)
1142           /* disable it */
1143           my_setopt(curl, CURLOPT_FTP_USE_EPRT, FALSE);
1144
1145         if(config->tracetype != TRACE_NONE) {
1146           my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
1147           my_setopt(curl, CURLOPT_DEBUGDATA, config);
1148           my_setopt(curl, CURLOPT_VERBOSE, TRUE);
1149         }
1150
1151         /* new in curl 7.9.3 */
1152         if(config->engine) {
1153           res = res_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
1154           if(res)
1155             goto show_error;
1156           my_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1);
1157         }
1158
1159         /* new in curl 7.10.7, extended in 7.19.4 but this only sets 0 or 1 */
1160         my_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
1161                   config->ftp_create_dirs);
1162
1163         /* new in curl 7.10.8 */
1164         if(config->max_filesize)
1165           my_setopt(curl, CURLOPT_MAXFILESIZE_LARGE,
1166                     config->max_filesize);
1167
1168         if(4 == config->ip_version)
1169           my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
1170         else if(6 == config->ip_version)
1171           my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
1172         else
1173           my_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER);
1174
1175         /* new in curl 7.15.5 */
1176         if(config->ftp_ssl_reqd)
1177           my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
1178
1179         /* new in curl 7.11.0 */
1180         else if(config->ftp_ssl)
1181           my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
1182
1183         /* new in curl 7.16.0 */
1184         else if(config->ftp_ssl_control)
1185           my_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL);
1186
1187         /* new in curl 7.16.1 */
1188         if(config->ftp_ssl_ccc)
1189           my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC, config->ftp_ssl_ccc_mode);
1190
1191 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
1192         {
1193           /* TODO: Make this a run-time check instead of compile-time one. */
1194
1195           /* new in curl 7.19.4 */
1196           if(config->socks5_gssapi_service)
1197             my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_SERVICE,
1198                           config->socks5_gssapi_service);
1199
1200           /* new in curl 7.19.4 */
1201           if(config->socks5_gssapi_nec)
1202             my_setopt_str(curl, CURLOPT_SOCKS5_GSSAPI_NEC,
1203                           config->socks5_gssapi_nec);
1204         }
1205 #endif
1206         /* curl 7.13.0 */
1207         my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
1208
1209         my_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
1210
1211         /* curl 7.14.2 */
1212         my_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip);
1213
1214         /* curl 7.15.1 */
1215         my_setopt(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
1216
1217         /* curl 7.15.2 */
1218         if(config->localport) {
1219           my_setopt(curl, CURLOPT_LOCALPORT, config->localport);
1220           my_setopt_str(curl, CURLOPT_LOCALPORTRANGE,
1221                         config->localportrange);
1222         }
1223
1224         /* curl 7.15.5 */
1225         my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
1226                       config->ftp_alternative_to_user);
1227
1228         /* curl 7.16.0 */
1229         if(config->disable_sessionid)
1230           my_setopt(curl, CURLOPT_SSL_SESSIONID_CACHE,
1231                     !config->disable_sessionid);
1232
1233         /* curl 7.16.2 */
1234         if(config->raw) {
1235           my_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, FALSE);
1236           my_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, FALSE);
1237         }
1238
1239         /* curl 7.17.1 */
1240         if(!config->nokeepalive) {
1241           my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
1242           if(config->alivetime != 0) {
1243 #if !defined(TCP_KEEPIDLE) || !defined(TCP_KEEPINTVL)
1244             warnf(config, "Keep-alive functionality somewhat crippled due to "
1245                 "missing support in your operating system!\n");
1246 #endif
1247             my_setopt(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime);
1248             my_setopt(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime);
1249           }
1250         }
1251         else
1252           my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L);
1253
1254         /* curl 7.20.0 */
1255         if(config->tftp_blksize)
1256           my_setopt(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
1257
1258         if(config->mail_from)
1259           my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from);
1260
1261         if(config->mail_rcpt)
1262           my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
1263
1264         /* curl 7.20.x */
1265         if(config->ftp_pret)
1266           my_setopt(curl, CURLOPT_FTP_USE_PRET, TRUE);
1267
1268         if(config->proto_present)
1269           my_setopt_flags(curl, CURLOPT_PROTOCOLS, config->proto);
1270         if(config->proto_redir_present)
1271           my_setopt_flags(curl, CURLOPT_REDIR_PROTOCOLS, config->proto_redir);
1272
1273         hdrdata.urlnode = urlnode;
1274         hdrdata.outs = &outs;
1275         hdrdata.heads = &heads;
1276
1277         my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
1278         my_setopt(curl, CURLOPT_HEADERDATA, &hdrdata);
1279
1280         if(config->resolve)
1281           /* new in 7.21.3 */
1282           my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve);
1283
1284         /* new in 7.21.4 */
1285         if(curlinfo->features & CURL_VERSION_TLSAUTH_SRP) {
1286           if(config->tls_username)
1287             my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME,
1288                           config->tls_username);
1289           if(config->tls_password)
1290             my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD,
1291                           config->tls_password);
1292           if(config->tls_authtype)
1293             my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE,
1294                           config->tls_authtype);
1295         }
1296
1297         /* new in 7.22.0 */
1298         if(config->gssapi_delegation)
1299           my_setopt_str(curl, CURLOPT_GSSAPI_DELEGATION,
1300                         config->gssapi_delegation);
1301
1302         /* new in 7.25.0 */
1303         if(config->ssl_allow_beast)
1304           my_setopt(curl, CURLOPT_SSL_OPTIONS, (long)CURLSSLOPT_ALLOW_BEAST);
1305
1306         if(config->mail_auth)
1307           my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
1308
1309         /* initialize retry vars for loop below */
1310         retry_sleep_default = (config->retry_delay) ?
1311           config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
1312
1313         retry_numretries = config->req_retry;
1314         retry_sleep = retry_sleep_default; /* ms */
1315         retrystart = tvnow();
1316
1317 #ifndef CURL_DISABLE_LIBCURL_OPTION
1318         res = easysrc_perform();
1319         if(res) {
1320           goto show_error;
1321         }
1322 #endif
1323
1324         for(;;) {
1325           res = curl_easy_perform(curl);
1326
1327           if(config->content_disposition && outs.stream && !config->mute &&
1328              outs.filename)
1329             printf("curl: Saved to filename '%s'\n", outs.filename);
1330
1331           /* if retry-max-time is non-zero, make sure we haven't exceeded the
1332              time */
1333           if(retry_numretries &&
1334              (!config->retry_maxtime ||
1335               (tvdiff(tvnow(), retrystart) <
1336                config->retry_maxtime*1000L)) ) {
1337             enum {
1338               RETRY_NO,
1339               RETRY_TIMEOUT,
1340               RETRY_HTTP,
1341               RETRY_FTP,
1342               RETRY_LAST /* not used */
1343             } retry = RETRY_NO;
1344             long response;
1345             if((CURLE_OPERATION_TIMEDOUT == res) ||
1346                (CURLE_COULDNT_RESOLVE_HOST == res) ||
1347                (CURLE_COULDNT_RESOLVE_PROXY == res) ||
1348                (CURLE_FTP_ACCEPT_TIMEOUT == res))
1349               /* retry timeout always */
1350               retry = RETRY_TIMEOUT;
1351             else if((CURLE_OK == res) ||
1352                     (config->failonerror &&
1353                      (CURLE_HTTP_RETURNED_ERROR == res))) {
1354               /* If it returned OK. _or_ failonerror was enabled and it
1355                  returned due to such an error, check for HTTP transient
1356                  errors to retry on. */
1357               char *effective_url = NULL;
1358               curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
1359               if(effective_url &&
1360                  checkprefix("http", effective_url)) {
1361                 /* This was HTTP(S) */
1362                 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
1363
1364                 switch(response) {
1365                 case 500: /* Internal Server Error */
1366                 case 502: /* Bad Gateway */
1367                 case 503: /* Service Unavailable */
1368                 case 504: /* Gateway Timeout */
1369                   retry = RETRY_HTTP;
1370                   /*
1371                    * At this point, we have already written data to the output
1372                    * file (or terminal). If we write to a file, we must rewind
1373                    * or close/re-open the file so that the next attempt starts
1374                    * over from the beginning.
1375                    *
1376                    * TODO: similar action for the upload case. We might need
1377                    * to start over reading from a previous point if we have
1378                    * uploaded something when this was returned.
1379                    */
1380                   break;
1381                 }
1382               }
1383             } /* if CURLE_OK */
1384             else if(res) {
1385               curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
1386
1387               if(response/100 == 4)
1388                 /*
1389                  * This is typically when the FTP server only allows a certain
1390                  * amount of users and we are not one of them.  All 4xx codes
1391                  * are transient.
1392                  */
1393                 retry = RETRY_FTP;
1394             }
1395
1396             if(retry) {
1397               static const char * const m[]={
1398                 NULL, "timeout", "HTTP error", "FTP error"
1399               };
1400               warnf(config, "Transient problem: %s "
1401                     "Will retry in %ld seconds. "
1402                     "%ld retries left.\n",
1403                     m[retry], retry_sleep/1000L, retry_numretries);
1404
1405               tool_go_sleep(retry_sleep);
1406               retry_numretries--;
1407               if(!config->retry_delay) {
1408                 retry_sleep *= 2;
1409                 if(retry_sleep > RETRY_SLEEP_MAX)
1410                   retry_sleep = RETRY_SLEEP_MAX;
1411               }
1412               if(outs.bytes && outs.filename) {
1413                 /* We have written data to a output file, we truncate file
1414                  */
1415                 if(!config->mute)
1416                   fprintf(config->errors, "Throwing away %"
1417                           CURL_FORMAT_CURL_OFF_T " bytes\n",
1418                           outs.bytes);
1419                 fflush(outs.stream);
1420                 /* truncate file at the position where we started appending */
1421 #ifdef HAVE_FTRUNCATE
1422                 if(ftruncate( fileno(outs.stream), outs.init)) {
1423                   /* when truncate fails, we can't just append as then we'll
1424                      create something strange, bail out */
1425                   if(!config->mute)
1426                     fprintf(config->errors,
1427                             "failed to truncate, exiting\n");
1428                   res = CURLE_WRITE_ERROR;
1429                   goto quit_urls;
1430                 }
1431                 /* now seek to the end of the file, the position where we
1432                    just truncated the file in a large file-safe way */
1433                 fseek(outs.stream, 0, SEEK_END);
1434 #else
1435                 /* ftruncate is not available, so just reposition the file
1436                    to the location we would have truncated it. This won't
1437                    work properly with large files on 32-bit systems, but
1438                    most of those will have ftruncate. */
1439                 fseek(outs.stream, (long)outs.init, SEEK_SET);
1440 #endif
1441                 outs.bytes = 0; /* clear for next round */
1442               }
1443               continue; /* curl_easy_perform loop */
1444             }
1445           } /* if retry_numretries */
1446 #ifdef HAVE_LIBMETALINK
1447           else if(metalink) {
1448             /* Metalink: Decide to try the next resource or
1449                not. Basically, we want to try the next resource if
1450                download was not successful. */
1451             long response;
1452             if(CURLE_OK == res) {
1453               /* TODO We want to try next resource when download was
1454                  not successful. How to know that? */
1455               char *effective_url = NULL;
1456               curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &effective_url);
1457               if(effective_url &&
1458                  curlx_strnequal(effective_url, "http", 4)) {
1459                 /* This was HTTP(S) */
1460                 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
1461                 if(response != 200 && response != 206) {
1462                   metalink_next_res = 1;
1463                 }
1464               }
1465             }
1466             else
1467               metalink_next_res = 1;
1468           }
1469 #endif /* HAVE_LIBMETALINK */
1470
1471           /* In all ordinary cases, just break out of loop here */
1472           break; /* curl_easy_perform loop */
1473
1474         }
1475
1476         if((config->progressmode == CURL_PROGRESS_BAR) &&
1477            progressbar.calls)
1478           /* if the custom progress bar has been displayed, we output a
1479              newline here */
1480           fputs("\n", progressbar.out);
1481
1482         if(config->writeout)
1483           ourWriteOut(curl, &outs, config->writeout);
1484
1485         if(config->writeenv)
1486           ourWriteEnv(curl);
1487
1488         /*
1489         ** Code within this loop may jump directly here to label 'show_error'
1490         ** in order to display an error message for CURLcode stored in 'res'
1491         ** variable and exit loop once that necessary writing and cleanup
1492         ** in label 'quit_urls' has been done.
1493         */
1494
1495         show_error:
1496
1497 #ifdef __VMS
1498         if(is_vms_shell()) {
1499           /* VMS DCL shell behavior */
1500           if(!config->showerror)
1501             vms_show = VMSSTS_HIDE;
1502         }
1503         else
1504 #endif
1505         if(res && config->showerror) {
1506           fprintf(config->errors, "curl: (%d) %s\n", res, (errorbuffer[0]) ?
1507                   errorbuffer : curl_easy_strerror((CURLcode)res));
1508           if(res == CURLE_SSL_CACERT)
1509             fprintf(config->errors, "%s%s",
1510                     CURL_CA_CERT_ERRORMSG1, CURL_CA_CERT_ERRORMSG2);
1511         }
1512
1513         /* Fall through comment to 'quit_urls' label */
1514
1515         /*
1516         ** Upon error condition and always that a message has already been
1517         ** displayed, code within this loop may jump directly here to label
1518         ** 'quit_urls' otherwise it should jump to 'show_error' label above.
1519         **
1520         ** When 'res' variable is _not_ CURLE_OK loop will exit once that
1521         ** all code following 'quit_urls' has been executed. Otherwise it
1522         ** will loop to the beginning from where it may exit if there are
1523         ** no more urls left.
1524         */
1525
1526         quit_urls:
1527
1528         /* Set file extended attributes */
1529         if(!res && config->xattr && outs.fopened && outs.stream) {
1530           int rc = fwrite_xattr(curl, fileno(outs.stream));
1531           if(rc)
1532             warnf(config, "Error setting extended attributes: %s\n",
1533                   strerror(errno));
1534         }
1535
1536         /* Close the file */
1537         if(outs.fopened && outs.stream) {
1538           int rc = fclose(outs.stream);
1539           if(!res && rc) {
1540             /* something went wrong in the writing process */
1541             res = CURLE_WRITE_ERROR;
1542             fprintf(config->errors, "(%d) Failed writing body\n", res);
1543           }
1544         }
1545         else if(!outs.s_isreg && outs.stream) {
1546           /* Dump standard stream buffered data */
1547           int rc = fflush(outs.stream);
1548           if(!res && rc) {
1549             /* something went wrong in the writing process */
1550             res = CURLE_WRITE_ERROR;
1551             fprintf(config->errors, "(%d) Failed writing body\n", res);
1552           }
1553         }
1554
1555 #ifdef __AMIGA__
1556         if(!res && outs.s_isreg && outs.filename) {
1557           /* Set the url (up to 80 chars) as comment for the file */
1558           if(strlen(url) > 78)
1559             url[79] = '\0';
1560           SetComment(outs.filename, url);
1561         }
1562 #endif
1563
1564 #ifdef HAVE_UTIME
1565         /* File time can only be set _after_ the file has been closed */
1566         if(!res && config->remote_time && outs.s_isreg && outs.filename) {
1567           /* Ask libcurl if we got a remote file time */
1568           long filetime = -1;
1569           curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime);
1570           if(filetime >= 0) {
1571             struct utimbuf times;
1572             times.actime = (time_t)filetime;
1573             times.modtime = (time_t)filetime;
1574             utime(outs.filename, &times); /* set the time we got */
1575           }
1576         }
1577 #endif
1578
1579 #ifdef HAVE_LIBMETALINK
1580         if(!metalink && res == CURLE_OK && outs.filename) {
1581           /* Check the content-type header field and if it indicates
1582              Metalink file, parse it and add getout for them. */
1583           char *content_type;
1584           curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &content_type);
1585           if(content_type && check_metalink_content_type(content_type)) {
1586             if(!(config->mute)) {
1587               fprintf(config->errors, "\nParsing Metalink file: %s\n",
1588                       outs.filename);
1589             }
1590             if(parse_metalink(config, outs.filename) == 0)
1591               fprintf(config->errors,
1592                       "Metalink file is parsed successfully\n");
1593             else
1594               fprintf(config->errors, "Could not parse Metalink file.\n");
1595           }
1596         }
1597 #  ifdef METALINK_HASH_CHECK
1598         else if(metalink && res == CURLE_OK && !metalink_next_res) {
1599           int rv = metalink_check_hash(config, mlfile, outs.filename);
1600           if(rv == 0) {
1601             metalink_next_res = 1;
1602           }
1603         }
1604 #  endif /* METALINK_HASH_CHECK */
1605 #endif /* HAVE_LIBMETALINK */
1606
1607         /* No more business with this output struct */
1608         if(outs.alloc_filename)
1609           Curl_safefree(outs.filename);
1610         memset(&outs, 0, sizeof(struct OutStruct));
1611
1612         /* Free loop-local allocated memory and close loop-local opened fd */
1613
1614         Curl_safefree(outfile);
1615         Curl_safefree(this_url);
1616
1617         if(infdopen) {
1618           close(infd);
1619           infdopen = FALSE;
1620           infd = STDIN_FILENO;
1621         }
1622
1623 #ifdef HAVE_LIBMETALINK
1624         if(metalink) {
1625           /* Should exit if error is fatal. */
1626           if(is_fatal_error(res)) {
1627             break;
1628           }
1629           if(!metalink_next_res)
1630             break;
1631           mlres = mlres->next;
1632           if(mlres == NULL)
1633             /* TODO If metalink_next_res is 1 and mlres is NULL,
1634              * set res to error code
1635              */
1636             break;
1637         }
1638         else
1639 #endif /* HAVE_LIBMETALINK */
1640         if(urlnum > 1) {
1641           /* when url globbing, exit loop upon critical error */
1642           if(is_fatal_error(res))
1643             break;
1644         }
1645         else if(res)
1646           /* when not url globbing, exit loop upon any error */
1647           break;
1648
1649       } /* loop to the next URL */
1650
1651       /* Free loop-local allocated memory */
1652
1653       Curl_safefree(uploadfile);
1654
1655       if(urls) {
1656         /* Free list of remaining URLs */
1657         glob_cleanup(urls);
1658         urls = NULL;
1659       }
1660
1661       if(infilenum > 1) {
1662         /* when file globbing, exit loop upon critical error */
1663         if(is_fatal_error(res))
1664           break;
1665       }
1666       else if(res)
1667         /* when not file globbing, exit loop upon any error */
1668         break;
1669
1670     } /* loop to the next globbed upload file */
1671
1672     /* Free loop-local allocated memory */
1673
1674     Curl_safefree(outfiles);
1675
1676     if(inglob) {
1677       /* Free list of globbed upload files */
1678       glob_cleanup(inglob);
1679       inglob = NULL;
1680     }
1681
1682     /* Free this URL node data without destroying the
1683        the node itself nor modifying next pointer. */
1684     Curl_safefree(urlnode->url);
1685     Curl_safefree(urlnode->outfile);
1686     Curl_safefree(urlnode->infile);
1687     urlnode->flags = 0;
1688
1689     /*
1690     ** Bail out upon critical errors
1691     */
1692     if(is_fatal_error(res))
1693       goto quit_curl;
1694
1695   } /* for-loop through all URLs */
1696
1697   /*
1698   ** Nested loops end here.
1699   */
1700
1701   quit_curl:
1702
1703   /* Free function-local referenced allocated memory */
1704   Curl_safefree(httpgetfields);
1705
1706   /* Free list of given URLs */
1707   clean_getout(config);
1708
1709   /* Cleanup the curl handle now that our
1710      progressbar struct is still in scope */
1711   if(curl) {
1712     curl_easy_cleanup(curl);
1713     config->easy = curl = NULL;
1714   }
1715 #ifndef CURL_DISABLE_LIBCURL_OPTION
1716   easysrc_cleanup();
1717 #endif
1718
1719   /* Close function-local opened file descriptors */
1720
1721   if(heads.fopened && heads.stream)
1722     fclose(heads.stream);
1723   if(heads.alloc_filename)
1724     Curl_safefree(heads.filename);
1725
1726   if(config->trace_fopened && config->trace_stream)
1727     fclose(config->trace_stream);
1728
1729 #ifndef CURL_DISABLE_LIBCURL_OPTION
1730   /* Dump the libcurl code if previously enabled.
1731      NOTE: that this function relies on config->errors amongst other things
1732      so not everything can be closed and cleaned before this is called */
1733   dumpeasysrc(config);
1734 #endif
1735
1736   if(config->errors_fopened && config->errors)
1737     fclose(config->errors);
1738
1739 #ifdef HAVE_LIBMETALINK
1740   /* Release metalink related resources here */
1741   clean_metalink(config);
1742 #endif /* HAVE_LIBMETALINK */
1743
1744   main_free(); /* cleanup */
1745
1746   return res;
1747 }
1748