diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2011-02-13 02:33:11 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-02-13 02:33:11 +0100 |
commit | a3661096f2e8b49f66ce6c9bba71aa01b79098e2 (patch) | |
tree | 414beb813d77cc08760afa6353deed929d014d71 | |
parent | a84eadf9bf4112e16d71304c586dfbb64eb85fed (diff) | |
download | busybox-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.c | 289 |
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 | ||
17 | struct host_info { | 17 | struct 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 | ||
245 | static void parse_url(char *src_url, struct host_info *h) | 253 | static 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 | ||
578 | int wget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 588 | static int download_one_url(const char *url) |
579 | int 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 | |||
902 | int wget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
903 | int 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 | } | ||