Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/networking/wget.c


Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/networking/wget.c

    r3232 r3621  
    1010 */
    1111
     12//config:config WGET
     13//config:   bool "wget"
     14//config:   default y
     15//config:   help
     16//config:     wget is a utility for non-interactive download of files from HTTP
     17//config:     and FTP servers.
     18//config:
     19//config:config FEATURE_WGET_STATUSBAR
     20//config:   bool "Enable a nifty process meter (+2k)"
     21//config:   default y
     22//config:   depends on WGET
     23//config:   help
     24//config:     Enable the transfer progress bar for wget transfers.
     25//config:
     26//config:config FEATURE_WGET_AUTHENTICATION
     27//config:   bool "Enable HTTP authentication"
     28//config:   default y
     29//config:   depends on WGET
     30//config:   help
     31//config:     Support authenticated HTTP transfers.
     32//config:
     33//config:config FEATURE_WGET_LONG_OPTIONS
     34//config:   bool "Enable long options"
     35//config:   default y
     36//config:   depends on WGET && LONG_OPTS
     37//config:   help
     38//config:     Support long options for the wget applet.
     39//config:
     40//config:config FEATURE_WGET_TIMEOUT
     41//config:   bool "Enable timeout option -T SEC"
     42//config:   default y
     43//config:   depends on WGET
     44//config:   help
     45//config:     Supports network read and connect timeouts for wget,
     46//config:     so that wget will give up and timeout, through the -T
     47//config:     command line option.
     48//config:
     49//config:     Currently only connect and network data read timeout are
     50//config:     supported (i.e., timeout is not applied to the DNS query). When
     51//config:     FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option
     52//config:     will work in addition to -T.
     53//config:
     54//config:config FEATURE_WGET_OPENSSL
     55//config:   bool "Try to connect to HTTPS using openssl"
     56//config:   default y
     57//config:   depends on WGET
     58//config:   help
     59//config:     Choose how wget establishes SSL connection for https:// URLs.
     60//config:
     61//config:     Busybox itself contains no SSL code. wget will spawn
     62//config:     a helper program to talk over HTTPS.
     63//config:
     64//config:     OpenSSL has a simple SSL client for debug purposes.
     65//config:     If you select "openssl" helper, wget will effectively call
     66//config:     "openssl s_client -quiet -connect IP:443 2>/dev/null"
     67//config:     and pipe its data through it.
     68//config:     Note inconvenient API: host resolution is done twice,
     69//config:     and there is no guarantee openssl's idea of IPv6 address
     70//config:     format is the same as ours.
     71//config:     Another problem is that s_client prints debug information
     72//config:     to stderr, and it needs to be suppressed. This means
     73//config:     all error messages get suppressed too.
     74//config:     openssl is also a big binary, often dynamically linked
     75//config:     against ~15 libraries.
     76//config:
     77//config:config FEATURE_WGET_SSL_HELPER
     78//config:   bool "Try to connect to HTTPS using ssl_helper"
     79//config:   default y
     80//config:   depends on WGET
     81//config:   help
     82//config:     Choose how wget establishes SSL connection for https:// URLs.
     83//config:
     84//config:     Busybox itself contains no SSL code. wget will spawn
     85//config:     a helper program to talk over HTTPS.
     86//config:
     87//config:     ssl_helper is a tool which can be built statically
     88//config:     from busybox sources against a small embedded SSL library.
     89//config:     Please see networking/ssl_helper/README.
     90//config:     It does not require double host resolution and emits
     91//config:     error messages to stderr.
     92//config:
     93//config:     Precompiled static binary may be available at
     94//config:     http://busybox.net/downloads/binaries/
     95
     96//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP))
     97
     98//kbuild:lib-$(CONFIG_WGET) += wget.o
     99
    12100//usage:#define wget_trivial_usage
    13101//usage:    IF_FEATURE_WGET_LONG_OPTIONS(
     
    15103//usage:       "    [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n"
    16104/* Since we ignore these opts, we don't show them in --help */
    17 /* //usage:    "    [--no-check-certificate] [--no-cache]" */
     105/* //usage:    "    [--no-check-certificate] [--no-cache] [--passive-ftp] [-t TRIES]" */
     106/* //usage:    "    [-nv] [-nc] [-nH] [-np]" */
    18107//usage:       "    [-U|--user-agent AGENT]" IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
    19108//usage:    )
     
    39128#if 0
    40129# define log_io(...) bb_error_msg(__VA_ARGS__)
     130# define SENDFMT(fp, fmt, ...) \
     131    do { \
     132        log_io("> " fmt, ##__VA_ARGS__); \
     133        fprintf(fp, fmt, ##__VA_ARGS__); \
     134    } while (0);
    41135#else
    42136# define log_io(...) ((void)0)
     137# define SENDFMT(fp, fmt, ...) fprintf(fp, fmt, ##__VA_ARGS__)
    43138#endif
    44139
     
    47142    char *allocated;
    48143    const char *path;
    49     const char *user;
     144    char       *user;
     145    const char *protocol;
    50146    char       *host;
    51147    int         port;
    52     smallint    is_ftp;
    53148};
    54 
     149static const char P_FTP[] ALIGN1 = "ftp";
     150static const char P_HTTP[] ALIGN1 = "http";
     151#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER
     152static const char P_HTTPS[] ALIGN1 = "https";
     153#endif
     154
     155#if ENABLE_FEATURE_WGET_LONG_OPTIONS
     156/* User-specified headers prevent using our corresponding built-in headers.  */
     157enum {
     158    HDR_HOST          = (1<<0),
     159    HDR_USER_AGENT    = (1<<1),
     160    HDR_RANGE         = (1<<2),
     161    HDR_AUTH          = (1<<3) * ENABLE_FEATURE_WGET_AUTHENTICATION,
     162    HDR_PROXY_AUTH    = (1<<4) * ENABLE_FEATURE_WGET_AUTHENTICATION,
     163};
     164static const char wget_user_headers[] ALIGN1 =
     165    "Host:\0"
     166    "User-Agent:\0"
     167    "Range:\0"
     168# if ENABLE_FEATURE_WGET_AUTHENTICATION
     169    "Authorization:\0"
     170    "Proxy-Authorization:\0"
     171# endif
     172    ;
     173# define USR_HEADER_HOST       (G.user_headers & HDR_HOST)
     174# define USR_HEADER_USER_AGENT (G.user_headers & HDR_USER_AGENT)
     175# define USR_HEADER_RANGE      (G.user_headers & HDR_RANGE)
     176# define USR_HEADER_AUTH       (G.user_headers & HDR_AUTH)
     177# define USR_HEADER_PROXY_AUTH (G.user_headers & HDR_PROXY_AUTH)
     178#else /* No long options, no user-headers :( */
     179# define USR_HEADER_HOST       0
     180# define USR_HEADER_USER_AGENT 0
     181# define USR_HEADER_RANGE      0
     182# define USR_HEADER_AUTH       0
     183# define USR_HEADER_PROXY_AUTH 0
     184#endif
    55185
    56186/* Globals */
     
    63193    bb_progress_t pmt;
    64194#endif
    65         char *dir_prefix;
     195    char *dir_prefix;
    66196#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    67         char *post_data;
    68         char *extra_headers;
    69 #endif
    70         char *fname_out;        /* where to direct output (-O) */
    71         const char *proxy_flag; /* Use proxies if env vars are set */
    72         const char *user_agent; /* "User-Agent" header field */
     197    char *post_data;
     198    char *extra_headers;
     199    unsigned char user_headers; /* Headers mentioned by the user */
     200#endif
     201    char *fname_out;        /* where to direct output (-O) */
     202    const char *proxy_flag; /* Use proxies if env vars are set */
     203    const char *user_agent; /* "User-Agent" header field */
    73204#if ENABLE_FEATURE_WGET_TIMEOUT
    74205    unsigned timeout_seconds;
     206    bool die_if_timed_out;
    75207#endif
    76208    int output_fd;
     
    87219#define G (*ptr_to_globals)
    88220#define INIT_G() do { \
    89         SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
    90     IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) \
     221    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
     222} while (0)
     223#define FINI_G() do { \
     224    FREE_PTR_TO_GLOBALS(); \
    91225} while (0)
    92226
     
    196330}
    197331
     332#if ENABLE_FEATURE_WGET_TIMEOUT
     333static void alarm_handler(int sig UNUSED_PARAM)
     334{
     335    /* This is theoretically unsafe (uses stdio and malloc in signal handler) */
     336    if (G.die_if_timed_out)
     337        bb_error_msg_and_die("download timed out");
     338}
     339static void set_alarm(void)
     340{
     341    if (G.timeout_seconds) {
     342        alarm(G.timeout_seconds);
     343        G.die_if_timed_out = 1;
     344    }
     345}
     346# define clear_alarm() ((void)(G.die_if_timed_out = 0))
     347#else
     348# define set_alarm()   ((void)0)
     349# define clear_alarm() ((void)0)
     350#endif
     351
    198352static FILE *open_socket(len_and_sockaddr *lsa)
    199353{
     354    int fd;
    200355    FILE *fp;
     356
     357    set_alarm();
     358    fd = xconnect_stream(lsa);
     359    clear_alarm();
    201360
    202361    /* glibc 2.4 seems to try seeking on it - ??! */
    203362    /* hopefully it understands what ESPIPE means... */
    204     fp = fdopen(xconnect_stream(lsa), "r+");
    205     if (fp == NULL)
     363    fp = fdopen(fd, "r+");
     364    if (!fp)
    206365        bb_perror_msg_and_die(bb_msg_memory_exhausted);
    207366
     
    215374    char *buf_ptr;
    216375
     376    set_alarm();
    217377    if (fgets(G.wget_buf, sizeof(G.wget_buf) - 1, fp) == NULL)
    218378        bb_perror_msg_and_die("error getting response");
     379    clear_alarm();
    219380
    220381    buf_ptr = strchrnul(G.wget_buf, '\n');
     
    257418    h->allocated = url = xstrdup(src_url);
    258419
    259     if (strncmp(url, "http://", 7) == 0) {
    260         h->port = bb_lookup_port("http", "tcp", 80);
    261         h->host = url + 7;
    262         h->is_ftp = 0;
    263     } else if (strncmp(url, "ftp://", 6) == 0) {
    264         h->port = bb_lookup_port("ftp", "tcp", 21);
    265         h->host = url + 6;
    266         h->is_ftp = 1;
    267     } else
    268         bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url));
     420    h->protocol = P_FTP;
     421    p = strstr(url, "://");
     422    if (p) {
     423        *p = '\0';
     424        h->host = p + 3;
     425        if (strcmp(url, P_FTP) == 0) {
     426            h->port = bb_lookup_port(P_FTP, "tcp", 21);
     427        } else
     428#if ENABLE_FEATURE_WGET_OPENSSL || ENABLE_FEATURE_WGET_SSL_HELPER
     429        if (strcmp(url, P_HTTPS) == 0) {
     430            h->port = bb_lookup_port(P_HTTPS, "tcp", 443);
     431            h->protocol = P_HTTPS;
     432        } else
     433#endif
     434        if (strcmp(url, P_HTTP) == 0) {
     435 http:
     436            h->port = bb_lookup_port(P_HTTP, "tcp", 80);
     437            h->protocol = P_HTTP;
     438        } else {
     439            *p = ':';
     440            bb_error_msg_and_die("not an http or ftp url: %s", sanitize_string(url));
     441        }
     442    } else {
     443        // GNU wget is user-friendly and falls back to http://
     444        h->host = url;
     445        goto http;
     446    }
    269447
    270448    // FYI:
     
    298476    }
    299477
    300     // We used to set h->user to NULL here, but this interferes
    301     // with handling of code 302 ("object was moved")
    302 
    303478    sp = strrchr(h->host, '@');
    304479    if (sp != NULL) {
     
    309484        // Standard wget and curl do this too.
    310485        *sp = '\0';
    311         h->user = percent_decode_in_place(h->host, /*strict:*/ 0);
     486        free(h->user);
     487        h->user = xstrdup(percent_decode_in_place(h->host, /*strict:*/ 0));
    312488        h->host = sp + 1;
    313489    }
    314 
    315     sp = h->host;
     490    /* else: h->user remains NULL, or as set by original request
     491     * before redirect (if we are here after a redirect).
     492     */
    316493}
    317494
     
    329506
    330507    /* convert the header name to lower case */
    331     for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.'; ++s) {
    332         /* tolower for "A-Z", no-op for "0-9a-z-." */
     508    for (s = G.wget_buf; isalnum(*s) || *s == '-' || *s == '.' || *s == '_'; ++s) {
     509        /*
     510         * No-op for 20-3f and 60-7f. "0-9a-z-." are in these ranges.
     511         * 40-5f range ("@A-Z[\]^_") maps to 60-7f.
     512         * "A-Z" maps to "a-z".
     513         * "@[\]" can't occur in header names.
     514         * "^_" maps to "~,DEL" (which is wrong).
     515         * "^" was never seen yet, "_" was seen from web.archive.org
     516         * (x-archive-orig-x_commoncrawl_Signature: HEXSTRING).
     517         */
    333518        *s |= 0x20;
    334519    }
     
    441626}
    442627
     628#if ENABLE_FEATURE_WGET_OPENSSL
     629static int spawn_https_helper_openssl(const char *host, unsigned port)
     630{
     631    char *allocated = NULL;
     632    int sp[2];
     633    int pid;
     634    IF_FEATURE_WGET_SSL_HELPER(volatile int child_failed = 0;)
     635
     636    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
     637        /* Kernel can have AF_UNIX support disabled */
     638        bb_perror_msg_and_die("socketpair");
     639
     640    if (!strchr(host, ':'))
     641        host = allocated = xasprintf("%s:%u", host, port);
     642
     643    fflush_all();
     644    pid = xvfork();
     645    if (pid == 0) {
     646        /* Child */
     647        char *argv[6];
     648
     649        close(sp[0]);
     650        xmove_fd(sp[1], 0);
     651        xdup2(0, 1);
     652        /*
     653         * openssl s_client -quiet -connect www.kernel.org:443 2>/dev/null
     654         * It prints some debug stuff on stderr, don't know how to suppress it.
     655         * Work around by dev-nulling stderr. We lose all error messages :(
     656         */
     657        xmove_fd(2, 3);
     658        xopen("/dev/null", O_RDWR);
     659        argv[0] = (char*)"openssl";
     660        argv[1] = (char*)"s_client";
     661        argv[2] = (char*)"-quiet";
     662        argv[3] = (char*)"-connect";
     663        argv[4] = (char*)host;
     664        argv[5] = NULL;
     665        BB_EXECVP(argv[0], argv);
     666        xmove_fd(3, 2);
     667# if ENABLE_FEATURE_WGET_SSL_HELPER
     668        child_failed = 1;
     669        xfunc_die();
     670# else
     671        bb_perror_msg_and_die("can't execute '%s'", argv[0]);
     672# endif
     673        /* notreached */
     674    }
     675
     676    /* Parent */
     677    free(allocated);
     678    close(sp[1]);
     679# if ENABLE_FEATURE_WGET_SSL_HELPER
     680    if (child_failed) {
     681        close(sp[0]);
     682        return -1;
     683    }
     684# endif
     685    return sp[0];
     686}
     687#endif
     688
     689/* See networking/ssl_helper/README how to build one */
     690#if ENABLE_FEATURE_WGET_SSL_HELPER
     691static void spawn_https_helper_small(int network_fd)
     692{
     693    int sp[2];
     694    int pid;
     695
     696    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) != 0)
     697        /* Kernel can have AF_UNIX support disabled */
     698        bb_perror_msg_and_die("socketpair");
     699
     700    pid = BB_MMU ? xfork() : xvfork();
     701    if (pid == 0) {
     702        /* Child */
     703        char *argv[3];
     704
     705        close(sp[0]);
     706        xmove_fd(sp[1], 0);
     707        xdup2(0, 1);
     708        xmove_fd(network_fd, 3);
     709        /*
     710         * A simple ssl/tls helper
     711         */
     712        argv[0] = (char*)"ssl_helper";
     713        argv[1] = (char*)"-d3";
     714        argv[2] = NULL;
     715        BB_EXECVP(argv[0], argv);
     716        bb_perror_msg_and_die("can't execute '%s'", argv[0]);
     717        /* notreached */
     718    }
     719
     720    /* Parent */
     721    close(sp[1]);
     722    xmove_fd(sp[0], network_fd);
     723}
     724#endif
     725
    443726static void NOINLINE retrieve_file_data(FILE *dfp)
    444727{
     
    509792                second_cnt = G.timeout_seconds;
    510793#endif
    511                 continue;
     794                goto bump;
    512795            }
    513796
     
    542825                 */
    543826            }
     827#endif
     828 bump:
    544829            /* Need to do it _every_ second for "stalled" indicator
    545830             * to be shown properly.
    546831             */
    547832            progress_meter(PROGRESS_BUMP);
    548 #endif
    549833        } /* while (reading data) */
    550834
     
    613897    use_proxy = (strcmp(G.proxy_flag, "off") != 0);
    614898    if (use_proxy) {
    615         proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy");
     899        proxy = getenv(target.protocol == P_FTP ? "ftp_proxy" : "http_proxy");
     900//FIXME: what if protocol is https? Ok to use http_proxy?
    616901        use_proxy = (proxy && proxy[0]);
    617902        if (use_proxy)
     
    673958    G.got_clen = 0;
    674959    G.chunked = 0;
    675     if (use_proxy || !target.is_ftp) {
     960    if (use_proxy || target.protocol != P_FTP) {
    676961        /*
    677962         *  HTTP session
     
    680965        int status;
    681966
    682 
    683         /* Open socket to http server */
     967        /* Open socket to http(s) server */
     968#if ENABLE_FEATURE_WGET_OPENSSL
     969        /* openssl (and maybe ssl_helper) support is configured */
     970        if (target.protocol == P_HTTPS) {
     971            /* openssl-based helper
     972             * Inconvenient API since we can't give it an open fd
     973             */
     974            int fd = spawn_https_helper_openssl(server.host, server.port);
     975# if ENABLE_FEATURE_WGET_SSL_HELPER
     976            if (fd < 0) { /* no openssl? try ssl_helper */
     977                sfp = open_socket(lsa);
     978                spawn_https_helper_small(fileno(sfp));
     979                goto socket_opened;
     980            }
     981# else
     982            /* We don't check for exec("openssl") failure in this case */
     983# endif
     984            sfp = fdopen(fd, "r+");
     985            if (!sfp)
     986                bb_perror_msg_and_die(bb_msg_memory_exhausted);
     987            goto socket_opened;
     988        }
    684989        sfp = open_socket(lsa);
    685 
     990 socket_opened:
     991#elif ENABLE_FEATURE_WGET_SSL_HELPER
     992        /* Only ssl_helper support is configured */
     993        sfp = open_socket(lsa);
     994        if (target.protocol == P_HTTPS)
     995            spawn_https_helper_small(fileno(sfp));
     996#else
     997        /* ssl (https) support is not configured */
     998        sfp = open_socket(lsa);
     999#endif
    6861000        /* Send HTTP request */
    6871001        if (use_proxy) {
    688             fprintf(sfp, "GET %stp://%s/%s HTTP/1.1\r\n",
    689                 target.is_ftp ? "f" : "ht", target.host,
     1002            SENDFMT(sfp, "GET %s://%s/%s HTTP/1.1\r\n",
     1003                target.protocol, target.host,
    6901004                target.path);
    6911005        } else {
    692             if (option_mask32 & WGET_OPT_POST_DATA)
    693                 fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path);
    694             else
    695                 fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path);
    696         }
    697 
    698         fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n",
    699             target.host, G.user_agent);
     1006            SENDFMT(sfp, "%s /%s HTTP/1.1\r\n",
     1007                (option_mask32 & WGET_OPT_POST_DATA) ? "POST" : "GET",
     1008                target.path);
     1009        }
     1010        if (!USR_HEADER_HOST)
     1011            SENDFMT(sfp, "Host: %s\r\n", target.host);
     1012        if (!USR_HEADER_USER_AGENT)
     1013            SENDFMT(sfp, "User-Agent: %s\r\n", G.user_agent);
    7001014
    7011015        /* Ask server to close the connection as soon as we are done
    7021016         * (IOW: we do not intend to send more requests)
    7031017         */
    704         fprintf(sfp, "Connection: close\r\n");
     1018        SENDFMT(sfp, "Connection: close\r\n");
    7051019
    7061020#if ENABLE_FEATURE_WGET_AUTHENTICATION
    707         if (target.user) {
    708             fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
     1021        if (target.user && !USR_HEADER_AUTH) {
     1022            SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n"+6,
    7091023                base64enc(target.user));
    7101024        }
    711         if (use_proxy && server.user) {
    712             fprintf(sfp, "Proxy-Authorization: Basic %s\r\n",
     1025        if (use_proxy && server.user && !USR_HEADER_PROXY_AUTH) {
     1026            SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n",
    7131027                base64enc(server.user));
    7141028        }
    7151029#endif
    7161030
    717         if (G.beg_range != 0)
    718             fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
     1031        if (G.beg_range != 0 && !USR_HEADER_RANGE)
     1032            SENDFMT(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range);
    7191033
    7201034#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    721         if (G.extra_headers)
     1035        if (G.extra_headers) {
     1036            log_io(G.extra_headers);
    7221037            fputs(G.extra_headers, sfp);
     1038        }
    7231039
    7241040        if (option_mask32 & WGET_OPT_POST_DATA) {
    725             fprintf(sfp,
     1041            SENDFMT(sfp,
    7261042                "Content-Type: application/x-www-form-urlencoded\r\n"
    7271043                "Content-Length: %u\r\n"
     
    7331049#endif
    7341050        {
    735             fprintf(sfp, "\r\n");
     1051            SENDFMT(sfp, "\r\n");
    7361052        }
    7371053
     
    8481164                    parse_url(str, &target);
    8491165                    if (!use_proxy) {
     1166                        /* server.user remains untouched */
    8501167                        free(server.allocated);
    8511168                        server.allocated = NULL;
     
    8661183        /* For HTTP, data is pumped over the same connection */
    8671184        dfp = sfp;
    868 
    8691185    } else {
    8701186        /*
     
    8971213    free(server.allocated);
    8981214    free(target.allocated);
     1215    free(server.user);
     1216    free(target.user);
    8991217    free(fname_out_alloc);
    9001218    free(redirected_path);
     
    9151233        "proxy\0"            Required_argument "Y"
    9161234        "user-agent\0"       Required_argument "U"
    917 #if ENABLE_FEATURE_WGET_TIMEOUT
    918         "timeout\0"          Required_argument "T"
    919 #endif
     1235IF_FEATURE_WGET_TIMEOUT(
     1236        "timeout\0"          Required_argument "T")
    9201237        /* Ignored: */
    921         // "tries\0"            Required_argument "t"
     1238IF_DESKTOP( "tries\0"            Required_argument "t")
     1239        "header\0"           Required_argument "\xff"
     1240        "post-data\0"        Required_argument "\xfe"
    9221241        /* Ignored (we always use PASV): */
    923         "passive-ftp\0"      No_argument       "\xff"
    924         "header\0"           Required_argument "\xfe"
    925         "post-data\0"        Required_argument "\xfd"
     1242IF_DESKTOP( "passive-ftp\0"      No_argument       "\xf0")
    9261243        /* Ignored (we don't do ssl) */
    927         "no-check-certificate\0" No_argument   "\xfc"
     1244IF_DESKTOP( "no-check-certificate\0" No_argument   "\xf0")
    9281245        /* Ignored (we don't support caching) */
    929         "no-cache\0"         No_argument       "\xfb"
     1246IF_DESKTOP( "no-cache\0"         No_argument       "\xf0")
     1247IF_DESKTOP( "no-verbose\0"       No_argument       "\xf0")
     1248IF_DESKTOP( "no-clobber\0"       No_argument       "\xf0")
     1249IF_DESKTOP( "no-host-directories\0" No_argument    "\xf0")
     1250IF_DESKTOP( "no-parent\0"        No_argument       "\xf0")
    9301251        ;
    9311252#endif
     
    9371258    INIT_G();
    9381259
    939     IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;)
     1260#if ENABLE_FEATURE_WGET_TIMEOUT
     1261    G.timeout_seconds = 900;
     1262    signal(SIGALRM, alarm_handler);
     1263#endif
    9401264    G.proxy_flag = "on";   /* use proxies if env vars are set */
    9411265    G.user_agent = "Wget"; /* "User-Agent" header field */
     
    9441268    applet_long_options = wget_longopts;
    9451269#endif
    946     opt_complementary = "-1" IF_FEATURE_WGET_TIMEOUT(":T+") IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::");
    947     getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:",
    948         &G.fname_out, &G.dir_prefix,
     1270    opt_complementary = "-1" /* at least one URL */
     1271        IF_FEATURE_WGET_TIMEOUT(":T+") /* -T NUM */
     1272        IF_FEATURE_WGET_LONG_OPTIONS(":\xff::"); /* --header is a list */
     1273    getopt32(argv, "csqO:P:Y:U:T:"
     1274        /*ignored:*/ "t:"
     1275        /*ignored:*/ "n::"
     1276        /* wget has exactly four -n<letter> opts, all of which we can ignore:
     1277         * -nv --no-verbose: be moderately quiet (-q is full quiet)
     1278         * -nc --no-clobber: abort if exists, neither download to FILE.n nor overwrite FILE
     1279         * -nH --no-host-directories: wget -r http://host/ won't create host/
     1280         * -np --no-parent
     1281         * "n::" above says that we accept -n[ARG].
     1282         * Specifying "n:" would be a bug: "-n ARG" would eat ARG!
     1283         */
     1284        , &G.fname_out, &G.dir_prefix,
    9491285        &G.proxy_flag, &G.user_agent,
    9501286        IF_FEATURE_WGET_TIMEOUT(&G.timeout_seconds) IF_NOT_FEATURE_WGET_TIMEOUT(NULL),
    951         NULL /* -t RETRIES */
     1287        NULL, /* -t RETRIES */
     1288        NULL  /* -n[ARG] */
    9521289        IF_FEATURE_WGET_LONG_OPTIONS(, &headers_llist)
    9531290        IF_FEATURE_WGET_LONG_OPTIONS(, &G.post_data)
     
    9571294#if ENABLE_FEATURE_WGET_LONG_OPTIONS
    9581295    if (headers_llist) {
    959         int size = 1;
    960         char *cp;
     1296        int size = 0;
     1297        char *hdr;
    9611298        llist_t *ll = headers_llist;
    9621299        while (ll) {
     
    9641301            ll = ll->link;
    9651302        }
    966         G.extra_headers = cp = xmalloc(size);
     1303        G.extra_headers = hdr = xmalloc(size + 1);
    9671304        while (headers_llist) {
    968             cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist));
     1305            int bit;
     1306            const char *words;
     1307
     1308            size = sprintf(hdr, "%s\r\n",
     1309                    (char*)llist_pop(&headers_llist));
     1310            /* a bit like index_in_substrings but don't match full key */
     1311            bit = 1;
     1312            words = wget_user_headers;
     1313            while (*words) {
     1314                if (strstr(hdr, words) == hdr) {
     1315                    G.user_headers |= bit;
     1316                    break;
     1317                }
     1318                bit <<= 1;
     1319                words += strlen(words) + 1;
     1320            }
     1321            hdr += size;
    9691322        }
    9701323    }
     
    9881341        xclose(G.output_fd);
    9891342
     1343#if ENABLE_FEATURE_CLEAN_UP && ENABLE_FEATURE_WGET_LONG_OPTIONS
     1344    free(G.extra_headers);
     1345#endif
     1346    FINI_G();
     1347
    9901348    return EXIT_SUCCESS;
    9911349}
Note: See TracChangeset for help on using the changeset viewer.