aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-02-13 02:33:11 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2011-02-13 02:33:11 +0100
commita3661096f2e8b49f66ce6c9bba71aa01b79098e2 (patch)
tree414beb813d77cc08760afa6353deed929d014d71
parenta84eadf9bf4112e16d71304c586dfbb64eb85fed (diff)
downloadbusybox-w32-a3661096f2e8b49f66ce6c9bba71aa01b79098e2.tar.gz
busybox-w32-a3661096f2e8b49f66ce6c9bba71aa01b79098e2.tar.bz2
busybox-w32-a3661096f2e8b49f66ce6c9bba71aa01b79098e2.zip
wget: support multiple URLs on command line
function old new delta wget_main 2190 2310 +120 progress_meter 124 140 +16 parse_url 288 304 +16 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 152/0) Total: 152 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/wget.c289
1 files changed, 160 insertions, 129 deletions
diff --git a/networking/wget.c b/networking/wget.c
index 45d428be9..76bd5e260 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -15,8 +15,7 @@
15 15
16 16
17struct host_info { 17struct host_info {
18 // May be used if we ever will want to free() all xstrdup()s... 18 char *allocated;
19 /* char *allocated; */
20 const char *path; 19 const char *path;
21 const char *user; 20 const char *user;
22 char *host; 21 char *host;
@@ -34,6 +33,14 @@ struct globals {
34 const char *curfile; /* Name of current file being transferred */ 33 const char *curfile; /* Name of current file being transferred */
35 bb_progress_t pmt; 34 bb_progress_t pmt;
36#endif 35#endif
36 char *dir_prefix;
37#if ENABLE_FEATURE_WGET_LONG_OPTIONS
38 char *post_data;
39 char *extra_headers;
40#endif
41 char *fname_out; /* where to direct output (-O) */
42 const char *proxy_flag; /* Use proxies if env vars are set */
43 const char *user_agent; /* "User-Agent" header field */
37#if ENABLE_FEATURE_WGET_TIMEOUT 44#if ENABLE_FEATURE_WGET_TIMEOUT
38 unsigned timeout_seconds; 45 unsigned timeout_seconds;
39#endif 46#endif
@@ -87,6 +94,7 @@ static void progress_meter(int flag)
87 G.chunked ? 0 : G.beg_range + G.transferred + G.content_len); 94 G.chunked ? 0 : G.beg_range + G.transferred + G.content_len);
88 95
89 if (flag == PROGRESS_END) { 96 if (flag == PROGRESS_END) {
97 bb_progress_free(&G.pmt);
90 bb_putchar_stderr('\n'); 98 bb_putchar_stderr('\n');
91 G.transferred = 0; 99 G.transferred = 0;
92 } 100 }
@@ -242,11 +250,12 @@ static int ftpcmd(const char *s1, const char *s2, FILE *fp)
242 return result; 250 return result;
243} 251}
244 252
245static void parse_url(char *src_url, struct host_info *h) 253static void parse_url(const char *src_url, struct host_info *h)
246{ 254{
247 char *url, *p, *sp; 255 char *url, *p, *sp;
248 256
249 /* h->allocated = */ url = xstrdup(src_url); 257 free(h->allocated);
258 h->allocated = url = xstrdup(src_url);
250 259
251 if (strncmp(url, "http://", 7) == 0) { 260 if (strncmp(url, "http://", 7) == 0) {
252 h->port = bb_lookup_port("http", "tcp", 80); 261 h->port = bb_lookup_port("http", "tcp", 80);
@@ -571,103 +580,36 @@ static void NOINLINE retrieve_file_data(FILE *dfp, int output_fd)
571 G.got_clen = 1; 580 G.got_clen = 1;
572 } 581 }
573 582
574 G.chunked = 0; /* make progress meter show 100% even for chunked */ 583 /* Draw full bar and free its resources */
584 G.chunked = 0; /* makes it show 100% even for chunked download */
575 progress_meter(PROGRESS_END); 585 progress_meter(PROGRESS_END);
576} 586}
577 587
578int wget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 588static int download_one_url(const char *url)
579int wget_main(int argc UNUSED_PARAM, char **argv)
580{ 589{
581 struct host_info server, target; 590 bool use_proxy; /* Use proxies if env vars are set */
582 len_and_sockaddr *lsa;
583 unsigned opt;
584 int redir_limit; 591 int redir_limit;
585 char *proxy = NULL; 592 int output_fd;
586 char *dir_prefix = NULL; 593 len_and_sockaddr *lsa;
587#if ENABLE_FEATURE_WGET_LONG_OPTIONS
588 char *post_data;
589 char *extra_headers = NULL;
590 llist_t *headers_llist = NULL;
591#endif
592 FILE *sfp; /* socket to web/ftp server */ 594 FILE *sfp; /* socket to web/ftp server */
593 FILE *dfp; /* socket to ftp server (data) */ 595 FILE *dfp; /* socket to ftp server (data) */
594 char *fname_out; /* where to direct output (-O) */ 596 char *proxy = NULL;
595 int output_fd = -1; 597 char *fname_out_alloc;
596 bool use_proxy; /* Use proxies if env vars are set */ 598 struct host_info server;
597 const char *proxy_flag = "on"; /* Use proxies if env vars are set */ 599 struct host_info target;
598 const char *user_agent = "Wget";/* "User-Agent" header field */
599
600 static const char keywords[] ALIGN1 =
601 "content-length\0""transfer-encoding\0""chunked\0""location\0";
602 enum {
603 KEY_content_length = 1, KEY_transfer_encoding, KEY_chunked, KEY_location
604 };
605#if ENABLE_FEATURE_WGET_LONG_OPTIONS
606 static const char wget_longopts[] ALIGN1 =
607 /* name, has_arg, val */
608 "continue\0" No_argument "c"
609 "spider\0" No_argument "s"
610 "quiet\0" No_argument "q"
611 "output-document\0" Required_argument "O"
612 "directory-prefix\0" Required_argument "P"
613 "proxy\0" Required_argument "Y"
614 "user-agent\0" Required_argument "U"
615#if ENABLE_FEATURE_WGET_TIMEOUT
616 "timeout\0" Required_argument "T"
617#endif
618 /* Ignored: */
619 // "tries\0" Required_argument "t"
620 /* Ignored (we always use PASV): */
621 "passive-ftp\0" No_argument "\xff"
622 "header\0" Required_argument "\xfe"
623 "post-data\0" Required_argument "\xfd"
624 /* Ignored (we don't do ssl) */
625 "no-check-certificate\0" No_argument "\xfc"
626 ;
627#endif
628
629 INIT_G();
630
631#if ENABLE_FEATURE_WGET_LONG_OPTIONS
632 applet_long_options = wget_longopts;
633#endif
634 /* server.allocated = target.allocated = NULL; */
635 opt_complementary = "-1" IF_FEATURE_WGET_TIMEOUT(":T+") IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::");
636 opt = getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:",
637 &fname_out, &dir_prefix,
638 &proxy_flag, &user_agent,
639 IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL),
640 NULL /* -t RETRIES */
641 IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
642 IF_FEATURE_WGET_LONG_OPTIONS(, &post_data)
643 );
644#if ENABLE_FEATURE_WGET_LONG_OPTIONS
645 if (headers_llist) {
646 int size = 1;
647 char *cp;
648 llist_t *ll = headers_llist;
649 while (ll) {
650 size += strlen(ll->data) + 2;
651 ll = ll->link;
652 }
653 extra_headers = cp = xmalloc(size);
654 while (headers_llist) {
655 cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist));
656 }
657 }
658#endif
659
660 /* TODO: compat issue: should handle "wget URL1 URL2..." */
661 600
601 server.allocated = NULL;
602 target.allocated = NULL;
603 server.user = NULL;
662 target.user = NULL; 604 target.user = NULL;
663 parse_url(argv[optind], &target); 605
606 parse_url(url, &target);
664 607
665 /* Use the proxy if necessary */ 608 /* Use the proxy if necessary */
666 use_proxy = (strcmp(proxy_flag, "off") != 0); 609 use_proxy = (strcmp(G.proxy_flag, "off") != 0);
667 if (use_proxy) { 610 if (use_proxy) {
668 proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy"); 611 proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");
669 if (proxy && proxy[0]) { 612 if (proxy && proxy[0]) {
670 server.user = NULL;
671 parse_url(proxy, &server); 613 parse_url(proxy, &server);
672 } else { 614 } else {
673 use_proxy = 0; 615 use_proxy = 0;
@@ -676,7 +618,8 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
676 if (!use_proxy) { 618 if (!use_proxy) {
677 server.port = target.port; 619 server.port = target.port;
678 if (ENABLE_FEATURE_IPV6) { 620 if (ENABLE_FEATURE_IPV6) {
679 server.host = xstrdup(target.host); 621 //free(server.allocated); - can't be non-NULL
622 server.host = server.allocated = xstrdup(target.host);
680 } else { 623 } else {
681 server.host = target.host; 624 server.host = target.host;
682 } 625 }
@@ -685,34 +628,31 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
685 if (ENABLE_FEATURE_IPV6) 628 if (ENABLE_FEATURE_IPV6)
686 strip_ipv6_scope_id(target.host); 629 strip_ipv6_scope_id(target.host);
687 630
688 /* Guess an output filename, if there was no -O FILE */ 631 /* If there was no -O FILE, guess output filename */
689 if (!(opt & WGET_OPT_OUTNAME)) { 632 output_fd = -1;
690 fname_out = bb_get_last_path_component_nostrip(target.path); 633 fname_out_alloc = NULL;
634 if (!G.fname_out) {
635 G.fname_out = bb_get_last_path_component_nostrip(target.path);
691 /* handle "wget http://kernel.org//" */ 636 /* handle "wget http://kernel.org//" */
692 if (fname_out[0] == '/' || !fname_out[0]) 637 if (G.fname_out[0] == '/' || !G.fname_out[0])
693 fname_out = (char*)"index.html"; 638 G.fname_out = (char*)"index.html";
694 /* -P DIR is considered only if there was no -O FILE */ 639 /* -P DIR is considered only if there was no -O FILE */
695 if (dir_prefix) 640 if (G.dir_prefix)
696 fname_out = concat_path_file(dir_prefix, fname_out); 641 G.fname_out = fname_out_alloc = concat_path_file(G.dir_prefix, G.fname_out);
697 } else { 642 } else {
698 if (LONE_DASH(fname_out)) { 643 if (LONE_DASH(G.fname_out)) {
699 /* -O - */ 644 /* -O - */
700 output_fd = 1; 645 output_fd = 1;
701 opt &= ~WGET_OPT_CONTINUE; 646 option_mask32 &= ~WGET_OPT_CONTINUE;
702 } 647 }
703 } 648 }
704#if ENABLE_FEATURE_WGET_STATUSBAR 649#if ENABLE_FEATURE_WGET_STATUSBAR
705 G.curfile = bb_get_last_path_component_nostrip(fname_out); 650 G.curfile = bb_get_last_path_component_nostrip(G.fname_out);
706#endif 651#endif
707 652
708 /* Impossible?
709 if ((opt & WGET_OPT_CONTINUE) && !fname_out)
710 bb_error_msg_and_die("can't specify continue (-c) without a filename (-O)");
711 */
712
713 /* Determine where to start transfer */ 653 /* Determine where to start transfer */
714 if (opt & WGET_OPT_CONTINUE) { 654 if (option_mask32 & WGET_OPT_CONTINUE) {
715 output_fd = open(fname_out, O_WRONLY); 655 output_fd = open(G.fname_out, O_WRONLY);
716 if (output_fd >= 0) { 656 if (output_fd >= 0) {
717 G.beg_range = xlseek(output_fd, 0, SEEK_END); 657 G.beg_range = xlseek(output_fd, 0, SEEK_END);
718 } 658 }
@@ -723,12 +663,13 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
723 redir_limit = 5; 663 redir_limit = 5;
724 resolve_lsa: 664 resolve_lsa:
725 lsa = xhost2sockaddr(server.host, server.port); 665 lsa = xhost2sockaddr(server.host, server.port);
726 if (!(opt & WGET_OPT_QUIET)) { 666 if (!(option_mask32 & WGET_OPT_QUIET)) {
727 char *s = xmalloc_sockaddr2dotted(&lsa->u.sa); 667 char *s = xmalloc_sockaddr2dotted(&lsa->u.sa);
728 fprintf(stderr, "Connecting to %s (%s)\n", server.host, s); 668 fprintf(stderr, "Connecting to %s (%s)\n", server.host, s);
729 free(s); 669 free(s);
730 } 670 }
731 establish_session: 671 establish_session:
672 G.chunked = G.got_clen = 0;
732 if (use_proxy || !target.is_ftp) { 673 if (use_proxy || !target.is_ftp) {
733 /* 674 /*
734 * HTTP session 675 * HTTP session
@@ -736,6 +677,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
736 char *str; 677 char *str;
737 int status; 678 int status;
738 679
680
739 /* Open socket to http server */ 681 /* Open socket to http server */
740 sfp = open_socket(lsa); 682 sfp = open_socket(lsa);
741 683
@@ -745,14 +687,14 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
745 target.is_ftp ? "f" : "ht", target.host, 687 target.is_ftp ? "f" : "ht", target.host,
746 target.path); 688 target.path);
747 } else { 689 } else {
748 if (opt & WGET_OPT_POST_DATA) 690 if (option_mask32 & WGET_OPT_POST_DATA)
749 fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path); 691 fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path);
750 else 692 else
751 fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path); 693 fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);
752 } 694 }
753 695
754 fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n", 696 fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
755 target.host, user_agent); 697 target.host, G.user_agent);
756 698
757 /* Ask server to close the connection as soon as we are done 699 /* Ask server to close the connection as soon as we are done
758 * (IOW: we do not intend to send more requests) 700 * (IOW: we do not intend to send more requests)
@@ -774,11 +716,11 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
774 fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range); 716 fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
775 717
776#if ENABLE_FEATURE_WGET_LONG_OPTIONS 718#if ENABLE_FEATURE_WGET_LONG_OPTIONS
777 if (extra_headers) 719 if (G.extra_headers)
778 fputs(extra_headers, sfp); 720 fputs(G.extra_headers, sfp);
779 721
780 if (opt & WGET_OPT_POST_DATA) { 722 if (option_mask32 & WGET_OPT_POST_DATA) {
781 char *estr = URL_escape(post_data); 723 char *estr = URL_escape(G.post_data);
782 fprintf(sfp, 724 fprintf(sfp,
783 "Content-Type: application/x-www-form-urlencoded\r\n" 725 "Content-Type: application/x-www-form-urlencoded\r\n"
784 "Content-Length: %u\r\n" 726 "Content-Length: %u\r\n"
@@ -810,7 +752,7 @@ int wget_main(int argc UNUSED_PARAM, char **argv)
810 switch (status) { 752 switch (status) {
811 case 0: 753 case 0:
812 case 100: 754 case 100:
813 while (gethdr(sfp /*, &n*/) != NULL) 755 while (gethdr(sfp) != NULL)
814 /* eat all remaining headers */; 756 /* eat all remaining headers */;
815 goto read_response; 757 goto read_response;
816 case 200: 758 case 200:
@@ -856,9 +798,16 @@ However, in real world it was observed that some web servers
856 /* 798 /*
857 * Retrieve HTTP headers. 799 * Retrieve HTTP headers.
858 */ 800 */
859 while ((str = gethdr(sfp /*, &n*/)) != NULL) { 801 while ((str = gethdr(sfp)) != NULL) {
860 /* gethdr converted "FOO:" string to lowercase */ 802 static const char keywords[] ALIGN1 =
803 "content-length\0""transfer-encoding\0""location\0";
804 enum {
805 KEY_content_length = 1, KEY_transfer_encoding, KEY_location
806 };
861 smalluint key; 807 smalluint key;
808
809 /* gethdr converted "FOO:" string to lowercase */
810
862 /* strip trailing whitespace */ 811 /* strip trailing whitespace */
863 char *s = strchrnul(str, '\0') - 1; 812 char *s = strchrnul(str, '\0') - 1;
864 while (s >= str && (*s == ' ' || *s == '\t')) { 813 while (s >= str && (*s == ' ' || *s == '\t')) {
@@ -875,23 +824,22 @@ However, in real world it was observed that some web servers
875 continue; 824 continue;
876 } 825 }
877 if (key == KEY_transfer_encoding) { 826 if (key == KEY_transfer_encoding) {
878 if (index_in_strings(keywords, str_tolower(str)) + 1 != KEY_chunked) 827 if (strcmp(str_tolower(str), "chunked") != 0)
879 bb_error_msg_and_die("transfer encoding '%s' is not supported", sanitize_string(str)); 828 bb_error_msg_and_die("transfer encoding '%s' is not supported", sanitize_string(str));
880 G.chunked = G.got_clen = 1; 829 G.chunked = 1;
881 } 830 }
882 if (key == KEY_location && status >= 300) { 831 if (key == KEY_location && status >= 300) {
883 if (--redir_limit == 0) 832 if (--redir_limit == 0)
884 bb_error_msg_and_die("too many redirections"); 833 bb_error_msg_and_die("too many redirections");
885 fclose(sfp); 834 fclose(sfp);
886 G.got_clen = 0; 835 if (str[0] == '/') {
887 G.chunked = 0; 836 free(target.allocated);
888 if (str[0] == '/') 837 target.path = target.allocated = xstrdup(str+1);
889 /* free(target.allocated); */
890 target.path = /* target.allocated = */ xstrdup(str+1);
891 /* lsa stays the same: it's on the same server */ 838 /* lsa stays the same: it's on the same server */
892 else { 839 } else {
893 parse_url(str, &target); 840 parse_url(str, &target);
894 if (!use_proxy) { 841 if (!use_proxy) {
842 free(server.allocated);
895 server.host = target.host; 843 server.host = target.host;
896 /* strip_ipv6_scope_id(target.host); - no! */ 844 /* strip_ipv6_scope_id(target.host); - no! */
897 /* we assume remote never gives us IPv6 addr with scope id */ 845 /* we assume remote never gives us IPv6 addr with scope id */
@@ -916,30 +864,113 @@ However, in real world it was observed that some web servers
916 sfp = prepare_ftp_session(&dfp, &target, lsa); 864 sfp = prepare_ftp_session(&dfp, &target, lsa);
917 } 865 }
918 866
919 if (opt & WGET_OPT_SPIDER) { 867 free(lsa);
920 if (ENABLE_FEATURE_CLEAN_UP) 868 free(server.allocated);
921 fclose(sfp); 869 free(target.allocated);
870
871 if (option_mask32 & WGET_OPT_SPIDER) {
872 free(fname_out_alloc);
873 fclose(sfp);
922 return EXIT_SUCCESS; 874 return EXIT_SUCCESS;
923 } 875 }
924 876
925 if (output_fd < 0) { 877 if (output_fd < 0) {
926 int o_flags = O_WRONLY | O_CREAT | O_TRUNC | O_EXCL; 878 int o_flags = O_WRONLY | O_CREAT | O_TRUNC | O_EXCL;
927 /* compat with wget: -O FILE can overwrite */ 879 /* compat with wget: -O FILE can overwrite */
928 if (opt & WGET_OPT_OUTNAME) 880 if (option_mask32 & WGET_OPT_OUTNAME)
929 o_flags = O_WRONLY | O_CREAT | O_TRUNC; 881 o_flags = O_WRONLY | O_CREAT | O_TRUNC;
930 output_fd = xopen(fname_out, o_flags); 882 output_fd = xopen(G.fname_out, o_flags);
931 } 883 }
932 884
885 free(fname_out_alloc);
886
933 retrieve_file_data(dfp, output_fd); 887 retrieve_file_data(dfp, output_fd);
934 xclose(output_fd); 888 xclose(output_fd);
935 889
936 if (dfp != sfp) { 890 if (dfp != sfp) {
937 /* It's ftp. Close it properly */ 891 /* It's ftp. Close data connection properly */
938 fclose(dfp); 892 fclose(dfp);
939 if (ftpcmd(NULL, NULL, sfp) != 226) 893 if (ftpcmd(NULL, NULL, sfp) != 226)
940 bb_error_msg_and_die("ftp error: %s", sanitize_string(G.wget_buf + 4)); 894 bb_error_msg_and_die("ftp error: %s", sanitize_string(G.wget_buf + 4));
941 /* ftpcmd("QUIT", NULL, sfp); - why bother? */ 895 /* ftpcmd("QUIT", NULL, sfp); - why bother? */
942 } 896 }
897 fclose(sfp);
943 898
944 return EXIT_SUCCESS; 899 return EXIT_SUCCESS;
945} 900}
901
902int wget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
903int wget_main(int argc UNUSED_PARAM, char **argv)
904{
905#if ENABLE_FEATURE_WGET_LONG_OPTIONS
906 static const char wget_longopts[] ALIGN1 =
907 /* name, has_arg, val */
908 "continue\0" No_argument "c"
909//FIXME: -s isn't --spider, it's --save-headers!
910 "spider\0" No_argument "s"
911 "quiet\0" No_argument "q"
912 "output-document\0" Required_argument "O"
913 "directory-prefix\0" Required_argument "P"
914 "proxy\0" Required_argument "Y"
915 "user-agent\0" Required_argument "U"
916#if ENABLE_FEATURE_WGET_TIMEOUT
917 "timeout\0" Required_argument "T"
918#endif
919 /* Ignored: */
920 // "tries\0" Required_argument "t"
921 /* Ignored (we always use PASV): */
922 "passive-ftp\0" No_argument "\xff"
923 "header\0" Required_argument "\xfe"
924 "post-data\0" Required_argument "\xfd"
925 /* Ignored (we don't do ssl) */
926 "no-check-certificate\0" No_argument "\xfc"
927 ;
928#endif
929
930 int exitcode;
931#if ENABLE_FEATURE_WGET_LONG_OPTIONS
932 llist_t *headers_llist = NULL;
933#endif
934
935 INIT_G();
936
937 IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;)
938 G.proxy_flag = "on"; /* use proxies if env vars are set */
939 G.user_agent = "Wget"; /* "User-Agent" header field */
940
941#if ENABLE_FEATURE_WGET_LONG_OPTIONS
942 applet_long_options = wget_longopts;
943#endif
944 opt_complementary = "-1" IF_FEATURE_WGET_TIMEOUT(":T+") IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::");
945 getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:",
946 &G.fname_out, &G.dir_prefix,
947 &G.proxy_flag, &G.user_agent,
948 IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL),
949 NULL /* -t RETRIES */
950 IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
951 IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data)
952 );
953 argv += optind;
954
955#if ENABLE_FEATURE_WGET_LONG_OPTIONS
956 if (headers_llist) {
957 int size = 1;
958 char *cp;
959 llist_t *ll = headers_llist;
960 while (ll) {
961 size += strlen(ll->data) + 2;
962 ll = ll->link;
963 }
964 G.extra_headers = cp = xmalloc(size);
965 while (headers_llist) {
966 cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist));
967 }
968 }
969#endif
970
971 exitcode = 0;
972 while (*argv)
973 exitcode |= download_one_url(*argv++);
974
975 return exitcode;
976}