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