]> sjero.net Git - wget/blob - src/main.c
Add --bindport option to force TCP source port.
[wget] / src / main.c
1 /* Command line parsing.
2    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3    2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation,
4    Inc.
5
6 This file is part of GNU Wget.
7
8 GNU Wget is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Wget is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
20
21 Additional permission under GNU GPL version 3 section 7
22
23 If you modify this program, or any covered work, by linking or
24 combining it with the OpenSSL project's OpenSSL library (or a
25 modified version of that library), containing parts covered by the
26 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
27 grants you additional permission to convey the resulting work.
28 Corresponding Source for a non-source form of such a combination
29 shall include the source code for the parts of OpenSSL used as well
30 as that of the covered work.  */
31
32 #include "wget.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <signal.h>
39 #ifdef ENABLE_NLS
40 # include <locale.h>
41 #endif
42 #include <assert.h>
43 #include <errno.h>
44 #include <time.h>
45
46 #include "exits.h"
47 #include "utils.h"
48 #include "init.h"
49 #include "retr.h"
50 #include "recur.h"
51 #include "host.h"
52 #include "url.h"
53 #include "progress.h"           /* for progress_handle_sigwinch */
54 #include "convert.h"
55 #include "spider.h"
56 #include "http.h"               /* for save_cookies */
57 #include "ptimer.h"
58 #include "warc.h"
59 #include <getopt.h>
60 #include <getpass.h>
61 #include <quote.h>
62
63 #ifdef WINDOWS
64 # include <io.h>
65 # include <fcntl.h>
66 #endif
67
68 #ifdef __VMS
69 # include "vms.h"
70 #endif /* __VMS */
71
72 #ifndef PATH_SEPARATOR
73 # define PATH_SEPARATOR '/'
74 #endif
75
76 #ifndef ENABLE_IRI
77 struct iri dummy_iri;
78 #endif
79
80 struct options opt;
81
82 /* defined in version.c */
83 extern char *version_string;
84 extern char *compilation_string;
85 extern char *system_getrc;
86 extern char *link_string;
87 /* defined in build_info.c */
88 extern const char *compiled_features[];
89 /* Used for --version output in print_version */
90 #define MAX_CHARS_PER_LINE      72
91 #define TABULATION              4
92
93 #if defined(SIGHUP) || defined(SIGUSR1)
94 static void redirect_output_signal (int);
95 #endif
96
97 const char *exec_name;
98
99 /* Number of successfully downloaded URLs */
100 int numurls = 0;
101 \f
102 #ifndef TESTING
103 /* Initialize I18N/L10N.  That amounts to invoking setlocale, and
104    setting up gettext's message catalog using bindtextdomain and
105    textdomain.  Does nothing if NLS is disabled or missing.  */
106
107 static void
108 i18n_initialize (void)
109 {
110   /* ENABLE_NLS implies existence of functions invoked here.  */
111 #ifdef ENABLE_NLS
112   /* Set the current locale.  */
113   setlocale (LC_ALL, "");
114   /* Set the text message domain.  */
115   bindtextdomain ("wget", LOCALEDIR);
116   textdomain ("wget");
117 #endif /* ENABLE_NLS */
118 }
119 \f
120 /* Definition of command-line options. */
121
122 static void print_help (void);
123 static void print_version (void);
124
125 #ifdef HAVE_SSL
126 # define IF_SSL(x) x
127 #else
128 # define IF_SSL(x) NULL
129 #endif
130
131 struct cmdline_option {
132   const char *long_name;
133   char short_name;
134   enum {
135     OPT_VALUE,
136     OPT_BOOLEAN,
137     OPT_FUNCALL,
138     /* Non-standard options that have to be handled specially in
139        main().  */
140     OPT__APPEND_OUTPUT,
141     OPT__CLOBBER,
142     OPT__DONT_REMOVE_LISTING,
143     OPT__EXECUTE,
144     OPT__NO,
145     OPT__PARENT
146   } type;
147   const void *data;             /* for standard options */
148   int argtype;                  /* for non-standard options */
149 };
150
151 static struct cmdline_option option_data[] =
152   {
153     { "accept", 'A', OPT_VALUE, "accept", -1 },
154     { "accept-regex", 0, OPT_VALUE, "acceptregex", -1 },
155     { "adjust-extension", 'E', OPT_BOOLEAN, "adjustextension", -1 },
156     { "append-output", 'a', OPT__APPEND_OUTPUT, NULL, required_argument },
157     { "ask-password", 0, OPT_BOOLEAN, "askpassword", -1 },
158     { "auth-no-challenge", 0, OPT_BOOLEAN, "authnochallenge", -1 },
159     { "background", 'b', OPT_BOOLEAN, "background", -1 },
160     { "backup-converted", 'K', OPT_BOOLEAN, "backupconverted", -1 },
161     { "backups", 0, OPT_BOOLEAN, "backups", -1 },
162     { "base", 'B', OPT_VALUE, "base", -1 },
163     { "bind-address", 0, OPT_VALUE, "bindaddress", -1 },
164     { "bind-port", 0, OPT_VALUE, "bindport", -1 },
165     { "body-data", 0, OPT_VALUE, "bodydata", -1 },
166     { "body-file", 0, OPT_VALUE, "bodyfile", -1 },
167     { IF_SSL ("ca-certificate"), 0, OPT_VALUE, "cacertificate", -1 },
168     { IF_SSL ("ca-directory"), 0, OPT_VALUE, "cadirectory", -1 },
169     { "cache", 0, OPT_BOOLEAN, "cache", -1 },
170     { IF_SSL ("certificate"), 0, OPT_VALUE, "certificate", -1 },
171     { IF_SSL ("certificate-type"), 0, OPT_VALUE, "certificatetype", -1 },
172     { IF_SSL ("check-certificate"), 0, OPT_BOOLEAN, "checkcertificate", -1 },
173     { "clobber", 0, OPT__CLOBBER, NULL, optional_argument },
174     { "config", 0, OPT_VALUE, "chooseconfig", -1 },
175     { "connect-timeout", 0, OPT_VALUE, "connecttimeout", -1 },
176     { "continue", 'c', OPT_BOOLEAN, "continue", -1 },
177     { "convert-links", 'k', OPT_BOOLEAN, "convertlinks", -1 },
178     { "content-disposition", 0, OPT_BOOLEAN, "contentdisposition", -1 },
179     { "content-on-error", 0, OPT_BOOLEAN, "contentonerror", -1 },
180     { "cookies", 0, OPT_BOOLEAN, "cookies", -1 },
181     { "cut-dirs", 0, OPT_VALUE, "cutdirs", -1 },
182     { "debug", 'd', OPT_BOOLEAN, "debug", -1 },
183     { "default-page", 0, OPT_VALUE, "defaultpage", -1 },
184     { "delete-after", 0, OPT_BOOLEAN, "deleteafter", -1 },
185     { "directories", 0, OPT_BOOLEAN, "dirstruct", -1 },
186     { "directory-prefix", 'P', OPT_VALUE, "dirprefix", -1 },
187     { "dns-cache", 0, OPT_BOOLEAN, "dnscache", -1 },
188     { "dns-timeout", 0, OPT_VALUE, "dnstimeout", -1 },
189     { "domains", 'D', OPT_VALUE, "domains", -1 },
190     { "dont-remove-listing", 0, OPT__DONT_REMOVE_LISTING, NULL, no_argument },
191     { "dot-style", 0, OPT_VALUE, "dotstyle", -1 }, /* deprecated */
192     { "egd-file", 0, OPT_VALUE, "egdfile", -1 },
193     { "exclude-directories", 'X', OPT_VALUE, "excludedirectories", -1 },
194     { "exclude-domains", 0, OPT_VALUE, "excludedomains", -1 },
195     { "execute", 'e', OPT__EXECUTE, NULL, required_argument },
196     { "follow-ftp", 0, OPT_BOOLEAN, "followftp", -1 },
197     { "follow-tags", 0, OPT_VALUE, "followtags", -1 },
198     { "force-directories", 'x', OPT_BOOLEAN, "dirstruct", -1 },
199     { "force-html", 'F', OPT_BOOLEAN, "forcehtml", -1 },
200     { "ftp-password", 0, OPT_VALUE, "ftppassword", -1 },
201 #ifdef __VMS
202     { "ftp-stmlf", 0, OPT_BOOLEAN, "ftpstmlf", -1 },
203 #endif /* def __VMS */
204     { "ftp-user", 0, OPT_VALUE, "ftpuser", -1 },
205     { "glob", 0, OPT_BOOLEAN, "glob", -1 },
206     { "header", 0, OPT_VALUE, "header", -1 },
207     { "help", 'h', OPT_FUNCALL, (void *)print_help, no_argument },
208     { "host-directories", 0, OPT_BOOLEAN, "addhostdir", -1 },
209     { "html-extension", 'E', OPT_BOOLEAN, "adjustextension", -1 }, /* deprecated */
210     { "htmlify", 0, OPT_BOOLEAN, "htmlify", -1 },
211     { "http-keep-alive", 0, OPT_BOOLEAN, "httpkeepalive", -1 },
212     { "http-passwd", 0, OPT_VALUE, "httppassword", -1 }, /* deprecated */
213     { "http-password", 0, OPT_VALUE, "httppassword", -1 },
214     { "http-user", 0, OPT_VALUE, "httpuser", -1 },
215     { IF_SSL ("https-only"), 0, OPT_BOOLEAN, "httpsonly", -1 },
216     { "ignore-case", 0, OPT_BOOLEAN, "ignorecase", -1 },
217     { "ignore-length", 0, OPT_BOOLEAN, "ignorelength", -1 },
218     { "ignore-tags", 0, OPT_VALUE, "ignoretags", -1 },
219     { "include-directories", 'I', OPT_VALUE, "includedirectories", -1 },
220 #ifdef ENABLE_IPV6
221     { "inet4-only", '4', OPT_BOOLEAN, "inet4only", -1 },
222     { "inet6-only", '6', OPT_BOOLEAN, "inet6only", -1 },
223 #endif
224     { "input-file", 'i', OPT_VALUE, "input", -1 },
225     { "iri", 0, OPT_BOOLEAN, "iri", -1 },
226     { "keep-session-cookies", 0, OPT_BOOLEAN, "keepsessioncookies", -1 },
227     { "level", 'l', OPT_VALUE, "reclevel", -1 },
228     { "limit-rate", 0, OPT_VALUE, "limitrate", -1 },
229     { "load-cookies", 0, OPT_VALUE, "loadcookies", -1 },
230     { "local-encoding", 0, OPT_VALUE, "localencoding", -1 },
231     { "max-redirect", 0, OPT_VALUE, "maxredirect", -1 },
232     { "method", 0, OPT_VALUE, "method", -1 },
233     { "mirror", 'm', OPT_BOOLEAN, "mirror", -1 },
234     { "no", 'n', OPT__NO, NULL, required_argument },
235     { "no-clobber", 0, OPT_BOOLEAN, "noclobber", -1 },
236     { "no-config", 0, OPT_BOOLEAN, "noconfig", -1},
237     { "no-parent", 0, OPT_BOOLEAN, "noparent", -1 },
238     { "output-document", 'O', OPT_VALUE, "outputdocument", -1 },
239     { "output-file", 'o', OPT_VALUE, "logfile", -1 },
240     { "page-requisites", 'p', OPT_BOOLEAN, "pagerequisites", -1 },
241     { "parent", 0, OPT__PARENT, NULL, optional_argument },
242     { "passive-ftp", 0, OPT_BOOLEAN, "passiveftp", -1 },
243     { "password", 0, OPT_VALUE, "password", -1 },
244     { "post-data", 0, OPT_VALUE, "postdata", -1 },
245     { "post-file", 0, OPT_VALUE, "postfile", -1 },
246     { "prefer-family", 0, OPT_VALUE, "preferfamily", -1 },
247     { "preserve-permissions", 0, OPT_BOOLEAN, "preservepermissions", -1 },
248     { IF_SSL ("private-key"), 0, OPT_VALUE, "privatekey", -1 },
249     { IF_SSL ("private-key-type"), 0, OPT_VALUE, "privatekeytype", -1 },
250     { "progress", 0, OPT_VALUE, "progress", -1 },
251     { "show-progress", 0, OPT_BOOLEAN, "showprogress", -1 },
252     { "protocol-directories", 0, OPT_BOOLEAN, "protocoldirectories", -1 },
253     { "proxy", 0, OPT_BOOLEAN, "useproxy", -1 },
254     { "proxy__compat", 'Y', OPT_VALUE, "useproxy", -1 }, /* back-compatible */
255     { "proxy-passwd", 0, OPT_VALUE, "proxypassword", -1 }, /* deprecated */
256     { "proxy-password", 0, OPT_VALUE, "proxypassword", -1 },
257     { "proxy-user", 0, OPT_VALUE, "proxyuser", -1 },
258     { "quiet", 'q', OPT_BOOLEAN, "quiet", -1 },
259     { "quota", 'Q', OPT_VALUE, "quota", -1 },
260     { "random-file", 0, OPT_VALUE, "randomfile", -1 },
261     { "random-wait", 0, OPT_BOOLEAN, "randomwait", -1 },
262     { "read-timeout", 0, OPT_VALUE, "readtimeout", -1 },
263     { "recursive", 'r', OPT_BOOLEAN, "recursive", -1 },
264     { "referer", 0, OPT_VALUE, "referer", -1 },
265     { "regex-type", 0, OPT_VALUE, "regextype", -1 },
266     { "reject", 'R', OPT_VALUE, "reject", -1 },
267     { "reject-regex", 0, OPT_VALUE, "rejectregex", -1 },
268     { "relative", 'L', OPT_BOOLEAN, "relativeonly", -1 },
269     { "remote-encoding", 0, OPT_VALUE, "remoteencoding", -1 },
270     { "remove-listing", 0, OPT_BOOLEAN, "removelisting", -1 },
271     { "report-speed", 0, OPT_BOOLEAN, "reportspeed", -1 },
272     { "restrict-file-names", 0, OPT_BOOLEAN, "restrictfilenames", -1 },
273     { "retr-symlinks", 0, OPT_BOOLEAN, "retrsymlinks", -1 },
274     { "retry-connrefused", 0, OPT_BOOLEAN, "retryconnrefused", -1 },
275     { "save-cookies", 0, OPT_VALUE, "savecookies", -1 },
276     { "save-headers", 0, OPT_BOOLEAN, "saveheaders", -1 },
277     { IF_SSL ("secure-protocol"), 0, OPT_VALUE, "secureprotocol", -1 },
278     { "server-response", 'S', OPT_BOOLEAN, "serverresponse", -1 },
279     { "span-hosts", 'H', OPT_BOOLEAN, "spanhosts", -1 },
280     { "spider", 0, OPT_BOOLEAN, "spider", -1 },
281     { "start-pos", 0, OPT_VALUE, "startpos", -1 },
282     { "strict-comments", 0, OPT_BOOLEAN, "strictcomments", -1 },
283     { "timeout", 'T', OPT_VALUE, "timeout", -1 },
284     { "timestamping", 'N', OPT_BOOLEAN, "timestamping", -1 },
285     { "tries", 't', OPT_VALUE, "tries", -1 },
286     { "unlink", 0, OPT_BOOLEAN, "unlink", -1 },
287     { "trust-server-names", 0, OPT_BOOLEAN, "trustservernames", -1 },
288     { "use-server-timestamps", 0, OPT_BOOLEAN, "useservertimestamps", -1 },
289     { "user", 0, OPT_VALUE, "user", -1 },
290     { "user-agent", 'U', OPT_VALUE, "useragent", -1 },
291     { "verbose", 'v', OPT_BOOLEAN, "verbose", -1 },
292     { "verbose", 0, OPT_BOOLEAN, "verbose", -1 },
293     { "version", 'V', OPT_FUNCALL, (void *) print_version, no_argument },
294     { "wait", 'w', OPT_VALUE, "wait", -1 },
295     { "waitretry", 0, OPT_VALUE, "waitretry", -1 },
296     { "warc-cdx", 0, OPT_BOOLEAN, "warccdx", -1 },
297 #ifdef HAVE_LIBZ
298     { "warc-compression", 0, OPT_BOOLEAN, "warccompression", -1 },
299 #endif
300     { "warc-dedup", 0, OPT_VALUE, "warccdxdedup", -1 },
301     { "warc-digests", 0, OPT_BOOLEAN, "warcdigests", -1 },
302     { "warc-file", 0, OPT_VALUE, "warcfile", -1 },
303     { "warc-header", 0, OPT_VALUE, "warcheader", -1 },
304     { "warc-keep-log", 0, OPT_BOOLEAN, "warckeeplog", -1 },
305     { "warc-max-size", 0, OPT_VALUE, "warcmaxsize", -1 },
306     { "warc-tempdir", 0, OPT_VALUE, "warctempdir", -1 },
307 #ifdef USE_WATT32
308     { "wdebug", 0, OPT_BOOLEAN, "wdebug", -1 },
309 #endif
310   };
311
312 #undef IF_SSL
313
314 /* Return a string that contains S with "no-" prepended.  The string
315    is NUL-terminated and allocated off static storage at Wget
316    startup.  */
317
318 static char *
319 no_prefix (const char *s)
320 {
321   static char buffer[2048];
322   static char *p = buffer;
323
324   char *cp = p;
325   int size = 3 + strlen (s) + 1;  /* "no-STRING\0" */
326   if (p + size >= buffer + sizeof (buffer))
327     abort ();
328
329   cp[0] = 'n', cp[1] = 'o', cp[2] = '-';
330   strcpy (cp + 3, s);
331   p += size;
332   return cp;
333 }
334
335 /* The arguments that that main passes to getopt_long. */
336 static struct option long_options[2 * countof (option_data) + 1];
337 static char short_options[128];
338
339 /* Mapping between short option chars and option_data indices. */
340 static unsigned char optmap[96];
341
342 /* Marker for `--no-FOO' values in long_options.  */
343 #define BOOLEAN_NEG_MARKER 1024
344
345 /* Initialize the long_options array used by getopt_long from the data
346    in option_data.  */
347
348 static void
349 init_switches (void)
350 {
351   char *p = short_options;
352   size_t i, o = 0;
353   for (i = 0; i < countof (option_data); i++)
354     {
355       struct cmdline_option *cmdopt = &option_data[i];
356       struct option *longopt;
357
358       if (!cmdopt->long_name)
359         /* The option is disabled. */
360         continue;
361
362       longopt = &long_options[o++];
363       longopt->name = cmdopt->long_name;
364       longopt->val = i;
365       if (cmdopt->short_name)
366         {
367           *p++ = cmdopt->short_name;
368           optmap[cmdopt->short_name - 32] = longopt - long_options;
369         }
370       switch (cmdopt->type)
371         {
372         case OPT_VALUE:
373           longopt->has_arg = required_argument;
374           if (cmdopt->short_name)
375             *p++ = ':';
376           break;
377         case OPT_BOOLEAN:
378           /* Specify an optional argument for long options, so that
379              --option=off works the same as --no-option, for
380              compatibility with pre-1.10 Wget.  However, don't specify
381              optional arguments short-option booleans because they
382              prevent combining of short options.  */
383           longopt->has_arg = optional_argument;
384           /* For Boolean options, add the "--no-FOO" variant, which is
385              identical to "--foo", except it has opposite meaning and
386              it doesn't allow an argument.  */
387           longopt = &long_options[o++];
388           longopt->name = no_prefix (cmdopt->long_name);
389           longopt->has_arg = no_argument;
390           /* Mask the value so we'll be able to recognize that we're
391              dealing with the false value.  */
392           longopt->val = i | BOOLEAN_NEG_MARKER;
393           break;
394         default:
395           assert (cmdopt->argtype != -1);
396           longopt->has_arg = cmdopt->argtype;
397           if (cmdopt->short_name)
398             {
399               if (longopt->has_arg == required_argument)
400                 *p++ = ':';
401               /* Don't handle optional_argument */
402             }
403         }
404     }
405   /* Terminate short_options. */
406   *p = '\0';
407   /* No need for xzero(long_options[o]) because its storage is static
408      and it will be zeroed by default.  */
409   assert (o <= countof (long_options));
410 }
411
412 /* Print the usage message.  */
413 static int
414 print_usage (int error)
415 {
416   return fprintf (error ? stderr : stdout,
417                   _("Usage: %s [OPTION]... [URL]...\n"), exec_name);
418 }
419
420 /* Print the help message, describing all the available options.  If
421    you add an option, be sure to update this list.  */
422 static void
423 print_help (void)
424 {
425   /* We split the help text this way to ease translation of individual
426      entries.  */
427   static const char *help[] = {
428     "\n",
429     N_("\
430 Mandatory arguments to long options are mandatory for short options too.\n\n"),
431     N_("\
432 Startup:\n"),
433     N_("\
434   -V,  --version                   display the version of Wget and exit.\n"),
435     N_("\
436   -h,  --help                      print this help.\n"),
437     N_("\
438   -b,  --background                go to background after startup.\n"),
439     N_("\
440   -e,  --execute=COMMAND           execute a `.wgetrc'-style command.\n"),
441     "\n",
442
443     N_("\
444 Logging and input file:\n"),
445     N_("\
446   -o,  --output-file=FILE          log messages to FILE.\n"),
447     N_("\
448   -a,  --append-output=FILE        append messages to FILE.\n"),
449 #ifdef ENABLE_DEBUG
450     N_("\
451   -d,  --debug                     print lots of debugging information.\n"),
452 #endif
453 #ifdef USE_WATT32
454     N_("\
455        --wdebug                    print Watt-32 debug output.\n"),
456 #endif
457     N_("\
458   -q,  --quiet                     quiet (no output).\n"),
459     N_("\
460   -v,  --verbose                   be verbose (this is the default).\n"),
461     N_("\
462   -nv, --no-verbose                turn off verboseness, without being quiet.\n"),
463     N_("\
464        --report-speed=TYPE         Output bandwidth as TYPE.  TYPE can be bits.\n"),
465     N_("\
466   -i,  --input-file=FILE           download URLs found in local or external FILE.\n"),
467     N_("\
468   -F,  --force-html                treat input file as HTML.\n"),
469     N_("\
470   -B,  --base=URL                  resolves HTML input-file links (-i -F)\n\
471                                    relative to URL.\n"),
472     N_("\
473        --config=FILE               Specify config file to use.\n"),
474     N_("\
475        --no-config                 Do not read any config file.\n"),
476     "\n",
477
478     N_("\
479 Download:\n"),
480     N_("\
481   -t,  --tries=NUMBER              set number of retries to NUMBER (0 unlimits).\n"),
482     N_("\
483        --retry-connrefused         retry even if connection is refused.\n"),
484     N_("\
485   -O,  --output-document=FILE      write documents to FILE.\n"),
486     N_("\
487   -nc, --no-clobber                skip downloads that would download to\n\
488                                    existing files (overwriting them).\n"),
489     N_("\
490   -c,  --continue                  resume getting a partially-downloaded file.\n"),
491     N_("\
492        --start-pos=OFFSET          start downloading from zero-based position OFFSET.\n"),
493     N_("\
494        --progress=TYPE             select progress gauge type.\n"),
495     N_("\
496        --show-progress             display the progress bar in any verbosity mode.\n"),
497     N_("\
498   -N,  --timestamping              don't re-retrieve files unless newer than\n\
499                                    local.\n"),
500     N_("\
501   --no-use-server-timestamps       don't set the local file's timestamp by\n\
502                                    the one on the server.\n"),
503     N_("\
504   -S,  --server-response           print server response.\n"),
505     N_("\
506        --spider                    don't download anything.\n"),
507     N_("\
508   -T,  --timeout=SECONDS           set all timeout values to SECONDS.\n"),
509     N_("\
510        --dns-timeout=SECS          set the DNS lookup timeout to SECS.\n"),
511     N_("\
512        --connect-timeout=SECS      set the connect timeout to SECS.\n"),
513     N_("\
514        --read-timeout=SECS         set the read timeout to SECS.\n"),
515     N_("\
516   -w,  --wait=SECONDS              wait SECONDS between retrievals.\n"),
517     N_("\
518        --waitretry=SECONDS         wait 1..SECONDS between retries of a retrieval.\n"),
519     N_("\
520        --random-wait               wait from 0.5*WAIT...1.5*WAIT secs between retrievals.\n"),
521     N_("\
522        --no-proxy                  explicitly turn off proxy.\n"),
523     N_("\
524   -Q,  --quota=NUMBER              set retrieval quota to NUMBER.\n"),
525     N_("\
526        --bind-address=ADDRESS      bind to ADDRESS (hostname or IP) on local host.\n"),
527     N_("\
528        --limit-rate=RATE           limit download rate to RATE.\n"),
529     N_("\
530        --no-dns-cache              disable caching DNS lookups.\n"),
531     N_("\
532        --restrict-file-names=OS    restrict chars in file names to ones OS allows.\n"),
533     N_("\
534        --ignore-case               ignore case when matching files/directories.\n"),
535 #ifdef ENABLE_IPV6
536     N_("\
537   -4,  --inet4-only                connect only to IPv4 addresses.\n"),
538     N_("\
539   -6,  --inet6-only                connect only to IPv6 addresses.\n"),
540     N_("\
541        --prefer-family=FAMILY      connect first to addresses of specified family,\n\
542                                    one of IPv6, IPv4, or none.\n"),
543 #endif
544     N_("\
545        --user=USER                 set both ftp and http user to USER.\n"),
546     N_("\
547        --password=PASS             set both ftp and http password to PASS.\n"),
548     N_("\
549        --ask-password              prompt for passwords.\n"),
550     N_("\
551        --no-iri                    turn off IRI support.\n"),
552     N_("\
553        --local-encoding=ENC        use ENC as the local encoding for IRIs.\n"),
554     N_("\
555        --remote-encoding=ENC       use ENC as the default remote encoding.\n"),
556     N_("\
557        --unlink                    remove file before clobber.\n"),
558     "\n",
559
560     N_("\
561 Directories:\n"),
562     N_("\
563   -nd, --no-directories            don't create directories.\n"),
564     N_("\
565   -x,  --force-directories         force creation of directories.\n"),
566     N_("\
567   -nH, --no-host-directories       don't create host directories.\n"),
568     N_("\
569        --protocol-directories      use protocol name in directories.\n"),
570     N_("\
571   -P,  --directory-prefix=PREFIX   save files to PREFIX/...\n"),
572     N_("\
573        --cut-dirs=NUMBER           ignore NUMBER remote directory components.\n"),
574     "\n",
575
576     N_("\
577 HTTP options:\n"),
578     N_("\
579        --http-user=USER            set http user to USER.\n"),
580     N_("\
581        --http-password=PASS        set http password to PASS.\n"),
582     N_("\
583        --no-cache                  disallow server-cached data.\n"),
584     N_ ("\
585        --default-page=NAME         Change the default page name (normally\n\
586                                    this is `index.html'.).\n"),
587     N_("\
588   -E,  --adjust-extension          save HTML/CSS documents with proper extensions.\n"),
589     N_("\
590        --ignore-length             ignore `Content-Length' header field.\n"),
591     N_("\
592        --header=STRING             insert STRING among the headers.\n"),
593     N_("\
594        --max-redirect              maximum redirections allowed per page.\n"),
595     N_("\
596        --proxy-user=USER           set USER as proxy username.\n"),
597     N_("\
598        --proxy-password=PASS       set PASS as proxy password.\n"),
599     N_("\
600        --referer=URL               include `Referer: URL' header in HTTP request.\n"),
601     N_("\
602        --save-headers              save the HTTP headers to file.\n"),
603     N_("\
604   -U,  --user-agent=AGENT          identify as AGENT instead of Wget/VERSION.\n"),
605     N_("\
606        --no-http-keep-alive        disable HTTP keep-alive (persistent connections).\n"),
607     N_("\
608        --no-cookies                don't use cookies.\n"),
609     N_("\
610        --load-cookies=FILE         load cookies from FILE before session.\n"),
611     N_("\
612        --save-cookies=FILE         save cookies to FILE after session.\n"),
613     N_("\
614        --keep-session-cookies      load and save session (non-permanent) cookies.\n"),
615     N_("\
616        --post-data=STRING          use the POST method; send STRING as the data.\n"),
617     N_("\
618        --post-file=FILE            use the POST method; send contents of FILE.\n"),
619     N_("\
620        --method=HTTPMethod         use method \"HTTPMethod\" in the header.\n"),
621     N_("\
622        --body-data=STRING          Send STRING as data. --method MUST be set.\n"),
623     N_("\
624        --body-file=FILE            Send contents of FILE. --method MUST be set.\n"),
625     N_("\
626        --content-disposition       honor the Content-Disposition header when\n\
627                                    choosing local file names (EXPERIMENTAL).\n"),
628     N_("\
629        --content-on-error          output the received content on server errors.\n"),
630     N_("\
631        --auth-no-challenge         send Basic HTTP authentication information\n\
632                                    without first waiting for the server's\n\
633                                    challenge.\n"),
634     "\n",
635
636 #ifdef HAVE_SSL
637     N_("\
638 HTTPS (SSL/TLS) options:\n"),
639     N_("\
640        --secure-protocol=PR        choose secure protocol, one of auto, SSLv2,\n\
641                                    SSLv3, TLSv1 and PFS.\n"),
642     N_("\
643        --https-only                only follow secure HTTPS links\n"),
644     N_("\
645        --no-check-certificate      don't validate the server's certificate.\n"),
646     N_("\
647        --certificate=FILE          client certificate file.\n"),
648     N_("\
649        --certificate-type=TYPE     client certificate type, PEM or DER.\n"),
650     N_("\
651        --private-key=FILE          private key file.\n"),
652     N_("\
653        --private-key-type=TYPE     private key type, PEM or DER.\n"),
654     N_("\
655        --ca-certificate=FILE       file with the bundle of CA's.\n"),
656     N_("\
657        --ca-directory=DIR          directory where hash list of CA's is stored.\n"),
658     N_("\
659        --random-file=FILE          file with random data for seeding the SSL PRNG.\n"),
660     N_("\
661        --egd-file=FILE             file naming the EGD socket with random data.\n"),
662     "\n",
663 #endif /* HAVE_SSL */
664
665     N_("\
666 FTP options:\n"),
667 #ifdef __VMS
668     N_("\
669        --ftp-stmlf                 Use Stream_LF format for all binary FTP files.\n"),
670 #endif /* def __VMS */
671     N_("\
672        --ftp-user=USER             set ftp user to USER.\n"),
673     N_("\
674        --ftp-password=PASS         set ftp password to PASS.\n"),
675     N_("\
676        --no-remove-listing         don't remove `.listing' files.\n"),
677     N_("\
678        --no-glob                   turn off FTP file name globbing.\n"),
679     N_("\
680        --no-passive-ftp            disable the \"passive\" transfer mode.\n"),
681     N_("\
682        --preserve-permissions      preserve remote file permissions.\n"),
683     N_("\
684        --retr-symlinks             when recursing, get linked-to files (not dir).\n"),
685     "\n",
686
687     N_("\
688 WARC options:\n"),
689     N_("\
690        --warc-file=FILENAME        save request/response data to a .warc.gz file.\n"),
691     N_("\
692        --warc-header=STRING        insert STRING into the warcinfo record.\n"),
693     N_("\
694        --warc-max-size=NUMBER      set maximum size of WARC files to NUMBER.\n"),
695     N_("\
696        --warc-cdx                  write CDX index files.\n"),
697     N_("\
698        --warc-dedup=FILENAME       do not store records listed in this CDX file.\n"),
699 #ifdef HAVE_LIBZ
700     N_("\
701        --no-warc-compression       do not compress WARC files with GZIP.\n"),
702 #endif
703     N_("\
704        --no-warc-digests           do not calculate SHA1 digests.\n"),
705     N_("\
706        --no-warc-keep-log          do not store the log file in a WARC record.\n"),
707     N_("\
708        --warc-tempdir=DIRECTORY    location for temporary files created by the\n\
709                                    WARC writer.\n"),
710     "\n",
711
712     N_("\
713 Recursive download:\n"),
714     N_("\
715   -r,  --recursive                 specify recursive download.\n"),
716     N_("\
717   -l,  --level=NUMBER              maximum recursion depth (inf or 0 for infinite).\n"),
718     N_("\
719        --delete-after              delete files locally after downloading them.\n"),
720     N_("\
721   -k,  --convert-links             make links in downloaded HTML or CSS point to\n\
722                                    local files.\n"),
723     N_("\
724        --backups=N                 before writing file X, rotate up to N backup files.\n"),
725
726 #ifdef __VMS
727     N_("\
728   -K,  --backup-converted          before converting file X, back up as X_orig.\n"),
729 #else /* def __VMS */
730     N_("\
731   -K,  --backup-converted          before converting file X, back up as X.orig.\n"),
732 #endif /* def __VMS [else] */
733     N_("\
734   -m,  --mirror                    shortcut for -N -r -l inf --no-remove-listing.\n"),
735     N_("\
736   -p,  --page-requisites           get all images, etc. needed to display HTML page.\n"),
737     N_("\
738        --strict-comments           turn on strict (SGML) handling of HTML comments.\n"),
739     "\n",
740
741     N_("\
742 Recursive accept/reject:\n"),
743     N_("\
744   -A,  --accept=LIST               comma-separated list of accepted extensions.\n"),
745     N_("\
746   -R,  --reject=LIST               comma-separated list of rejected extensions.\n"),
747     N_("\
748        --accept-regex=REGEX        regex matching accepted URLs.\n"),
749     N_("\
750        --reject-regex=REGEX        regex matching rejected URLs.\n"),
751 #ifdef HAVE_LIBPCRE
752     N_("\
753        --regex-type=TYPE           regex type (posix|pcre).\n"),
754 #else
755     N_("\
756        --regex-type=TYPE           regex type (posix).\n"),
757 #endif
758     N_("\
759   -D,  --domains=LIST              comma-separated list of accepted domains.\n"),
760     N_("\
761        --exclude-domains=LIST      comma-separated list of rejected domains.\n"),
762     N_("\
763        --follow-ftp                follow FTP links from HTML documents.\n"),
764     N_("\
765        --follow-tags=LIST          comma-separated list of followed HTML tags.\n"),
766     N_("\
767        --ignore-tags=LIST          comma-separated list of ignored HTML tags.\n"),
768     N_("\
769   -H,  --span-hosts                go to foreign hosts when recursive.\n"),
770     N_("\
771   -L,  --relative                  follow relative links only.\n"),
772     N_("\
773   -I,  --include-directories=LIST  list of allowed directories.\n"),
774     N_("\
775        --trust-server-names        use the name specified by the redirection\n\
776                                    url last component.\n"),
777     N_("\
778   -X,  --exclude-directories=LIST  list of excluded directories.\n"),
779     N_("\
780   -np, --no-parent                 don't ascend to the parent directory.\n"),
781     "\n",
782     N_("Mail bug reports and suggestions to <bug-wget@gnu.org>.\n")
783   };
784
785   size_t i;
786
787   if (printf (_("GNU Wget %s, a non-interactive network retriever.\n"),
788               version_string) < 0)
789     exit (3);
790   if (print_usage (0) < 0)
791     exit (3);
792
793   for (i = 0; i < countof (help); i++)
794     if (fputs (_(help[i]), stdout) < 0)
795       exit (3);
796
797   exit (0);
798 }
799
800 /* Return a human-readable printed representation of INTERVAL,
801    measured in seconds.  */
802
803 static char *
804 secs_to_human_time (double interval)
805 {
806   static char buf[32];
807   int secs = (int) (interval + 0.5);
808   int hours, mins, days;
809
810   days = secs / 86400, secs %= 86400;
811   hours = secs / 3600, secs %= 3600;
812   mins = secs / 60, secs %= 60;
813
814   if (days)
815     sprintf (buf, "%dd %dh %dm %ds", days, hours, mins, secs);
816   else if (hours)
817     sprintf (buf, "%dh %dm %ds", hours, mins, secs);
818   else if (mins)
819     sprintf (buf, "%dm %ds", mins, secs);
820   else
821     sprintf (buf, "%ss", print_decimal (interval));
822
823   return buf;
824 }
825
826 static char *
827 prompt_for_password (void)
828 {
829   if (opt.user)
830     fprintf (stderr, _("Password for user %s: "), quote (opt.user));
831   else
832     fprintf (stderr, _("Password: "));
833   return getpass("");
834 }
835
836 /* Function that prints the line argument while limiting it
837    to at most line_length. prefix is printed on the first line
838    and an appropriate number of spaces are added on subsequent
839    lines.*/
840 static int
841 format_and_print_line (const char *prefix, const char *line,
842                        int line_length)
843 {
844   int remaining_chars;
845   char *line_dup, *token;
846
847   assert (prefix != NULL);
848   assert (line != NULL);
849   assert (line_length > TABULATION);
850
851   line_dup = xstrdup (line);
852
853   if (printf ("%s", prefix) < 0)
854     return -1;
855
856   /* Wrap to new line after prefix. */
857   remaining_chars = 0;
858
859   /* We break on spaces. */
860   token = strtok (line_dup, " ");
861   while (token != NULL)
862     {
863       /* If however a token is much larger than the maximum
864          line length, all bets are off and we simply print the
865          token on the next line. */
866       if (remaining_chars <= (int) strlen (token))
867         {
868           if (printf ("\n%*c", TABULATION, ' ') < 0)
869             return -1;
870           remaining_chars = line_length - TABULATION;
871         }
872       if (printf ("%s ", token) < 0)
873         return -1;
874       remaining_chars -= strlen (token) + 1;  /* account for " " */
875       token = strtok (NULL, " ");
876     }
877
878   if (printf ("\n") < 0)
879     return -1;
880
881   xfree (line_dup);
882   return 0;
883 }
884
885 static void
886 print_version (void)
887 {
888   const char *wgetrc_title  = _("Wgetrc: ");
889   const char *locale_title  = _("Locale: ");
890   const char *compile_title = _("Compile: ");
891   const char *link_title    = _("Link: ");
892   char *env_wgetrc, *user_wgetrc;
893   int i;
894
895   if (printf (_("GNU Wget %s built on %s.\n\n"), version_string, OS_TYPE) < 0)
896     exit (3);
897
898   for (i = 0; compiled_features[i] != NULL; )
899     {
900       int line_length = MAX_CHARS_PER_LINE;
901       while ((line_length > 0) && (compiled_features[i] != NULL))
902         {
903           if (printf ("%s ", compiled_features[i]) < 0)
904             exit (3);
905           line_length -= strlen (compiled_features[i]) + 2;
906           i++;
907         }
908       if (printf ("\n") < 0)
909         exit (3);
910     }
911   if (printf ("\n") < 0)
912     exit (3);
913
914   /* Handle the case when $WGETRC is unset and $HOME/.wgetrc is
915      absent. */
916   if (printf ("%s\n", wgetrc_title) < 0)
917     exit (3);
918
919   env_wgetrc = wgetrc_env_file_name ();
920   if (env_wgetrc && *env_wgetrc)
921     {
922       if (printf (_("    %s (env)\n"), env_wgetrc) < 0)
923         exit (3);
924       xfree (env_wgetrc);
925     }
926   user_wgetrc = wgetrc_user_file_name ();
927   if (user_wgetrc)
928     {
929       if (printf (_("    %s (user)\n"), user_wgetrc) < 0)
930         exit (3);
931       xfree (user_wgetrc);
932     }
933 #ifdef SYSTEM_WGETRC
934   if (printf (_("    %s (system)\n"), SYSTEM_WGETRC) < 0)
935     exit (3);
936 #endif
937
938 #ifdef ENABLE_NLS
939   if (format_and_print_line (locale_title,
940                              LOCALEDIR,
941                              MAX_CHARS_PER_LINE) < 0)
942     exit (3);
943 #endif /* def ENABLE_NLS */
944
945   if (compilation_string != NULL)
946     if (format_and_print_line (compile_title,
947                                compilation_string,
948                                MAX_CHARS_PER_LINE) < 0)
949       exit (3);
950
951   if (link_string != NULL)
952     if (format_and_print_line (link_title,
953                                link_string,
954                                MAX_CHARS_PER_LINE) < 0)
955       exit (3);
956
957   if (printf ("\n") < 0)
958     exit (3);
959
960   /* TRANSLATORS: When available, an actual copyright character
961      (circle-c) should be used in preference to "(C)". */
962   if (printf (_("\
963 Copyright (C) %s Free Software Foundation, Inc.\n"), "2014") < 0)
964     exit (3);
965   if (fputs (_("\
966 License GPLv3+: GNU GPL version 3 or later\n\
967 <http://www.gnu.org/licenses/gpl.html>.\n\
968 This is free software: you are free to change and redistribute it.\n\
969 There is NO WARRANTY, to the extent permitted by law.\n"), stdout) < 0)
970     exit (3);
971   /* TRANSLATORS: When available, please use the proper diacritics for
972      names such as this one. See en_US.po for reference. */
973   if (fputs (_("\nOriginally written by Hrvoje Niksic <hniksic@xemacs.org>.\n"),
974              stdout) < 0)
975     exit (3);
976   if (fputs (_("Please send bug reports and questions to <bug-wget@gnu.org>.\n"),
977              stdout) < 0)
978     exit (3);
979
980   exit (0);
981 }
982
983 static char *program_name; /* Needed by lib/error.c. */
984 char *program_argstring; /* Needed by wget_warc.c. */
985
986 int
987 main (int argc, char **argv)
988 {
989   char **url, **t;
990   int i, ret, longindex;
991   int nurl;
992   bool append_to_log = false;
993
994   total_downloaded_bytes = 0;
995
996   program_name = argv[0];
997
998   struct ptimer *timer = ptimer_new ();
999   double start_time = ptimer_measure (timer);
1000
1001   i18n_initialize ();
1002
1003   /* Construct the name of the executable, without the directory part.  */
1004 #ifdef __VMS
1005   /* On VMS, lose the "dev:[dir]" prefix and the ".EXE;nnn" suffix. */
1006   exec_name = vms_basename (argv[0]);
1007 #else /* def __VMS */
1008   exec_name = strrchr (argv[0], PATH_SEPARATOR);
1009   if (!exec_name)
1010     exec_name = argv[0];
1011   else
1012     ++exec_name;
1013 #endif /* def __VMS [else] */
1014
1015 #ifdef WINDOWS
1016   /* Drop extension (typically .EXE) from executable filename. */
1017   windows_main ((char **) &exec_name);
1018 #endif
1019
1020   /* Construct the arguments string. */
1021   int argstring_length = 1;
1022   for (i = 1; i < argc; i++)
1023     argstring_length += strlen (argv[i]) + 2 + 1;
1024   char *p = program_argstring = malloc (argstring_length * sizeof (char));
1025   if (p == NULL)
1026     {
1027       fprintf (stderr, _("Memory allocation problem\n"));
1028       exit (2);
1029     }
1030   for (i = 1; i < argc; i++)
1031     {
1032       *p++ = '"';
1033       int arglen = strlen (argv[i]);
1034       memcpy (p, argv[i], arglen);
1035       p += arglen;
1036       *p++ = '"';
1037       *p++ = ' ';
1038     }
1039   *p = '\0';
1040
1041   /* Load the hard-coded defaults.  */
1042   defaults ();
1043
1044   init_switches ();
1045
1046   /* This separate getopt_long is needed to find the user config file
1047      option ("--config") and parse it before the other user options. */
1048   longindex = -1;
1049   int retconf;
1050   bool use_userconfig = false;
1051   bool noconfig = false;
1052
1053   while ((retconf = getopt_long (argc, argv,
1054                                 short_options, long_options, &longindex)) != -1)
1055     {
1056       int confval;
1057       struct cmdline_option *config_opt;
1058
1059       /* There is no short option for "--config". */
1060       if (longindex >= 0)
1061         {
1062           confval = long_options[longindex].val;
1063           config_opt = &option_data[confval & ~BOOLEAN_NEG_MARKER];
1064           if (strcmp (config_opt->long_name, "no-config") == 0)
1065             {
1066               noconfig = true;
1067               break;
1068             }
1069           else if (strcmp (config_opt->long_name, "config") == 0)
1070             {
1071               bool userrc_ret = true;
1072               userrc_ret &= run_wgetrc (optarg);
1073               use_userconfig = true;
1074               if (userrc_ret)
1075                 break;
1076               else
1077                 {
1078                   fprintf (stderr, _("Exiting due to error in %s\n"), optarg);
1079                   exit (2);
1080                 }
1081             }
1082         }
1083     }
1084
1085   /* If the user did not specify a config, read the system wgetrc and ~/.wgetrc. */
1086   if (noconfig == false && use_userconfig == false)
1087     initialize ();
1088
1089   opterr = 0;
1090   optind = 0;
1091
1092   longindex = -1;
1093   while ((ret = getopt_long (argc, argv,
1094                              short_options, long_options, &longindex)) != -1)
1095     {
1096       int val;
1097       struct cmdline_option *cmdopt;
1098
1099       /* If LONGINDEX is unchanged, it means RET is referring a short
1100          option.  */
1101       if (longindex == -1)
1102         {
1103           if (ret == '?')
1104             {
1105               print_usage (1);
1106               fprintf (stderr, "\n");
1107               fprintf (stderr, _("Try `%s --help' for more options.\n"),
1108                        exec_name);
1109               exit (2);
1110             }
1111           /* Find the short option character in the mapping.  */
1112           longindex = optmap[ret - 32];
1113         }
1114       val = long_options[longindex].val;
1115
1116       /* Use the retrieved value to locate the option in the
1117          option_data array, and to see if we're dealing with the
1118          negated "--no-FOO" variant of the boolean option "--foo".  */
1119       cmdopt = &option_data[val & ~BOOLEAN_NEG_MARKER];
1120       switch (cmdopt->type)
1121         {
1122         case OPT_VALUE:
1123           setoptval (cmdopt->data, optarg, cmdopt->long_name);
1124           break;
1125         case OPT_BOOLEAN:
1126           if (optarg)
1127             /* The user has specified a value -- use it. */
1128             setoptval (cmdopt->data, optarg, cmdopt->long_name);
1129           else
1130             {
1131               /* NEG is true for `--no-FOO' style boolean options. */
1132               bool neg = !!(val & BOOLEAN_NEG_MARKER);
1133               setoptval (cmdopt->data, neg ? "0" : "1", cmdopt->long_name);
1134             }
1135           break;
1136         case OPT_FUNCALL:
1137           {
1138             void (*func) (void) = (void (*) (void)) cmdopt->data;
1139             func ();
1140           }
1141           break;
1142         case OPT__APPEND_OUTPUT:
1143           setoptval ("logfile", optarg, cmdopt->long_name);
1144           append_to_log = true;
1145           break;
1146         case OPT__EXECUTE:
1147           run_command (optarg);
1148           break;
1149         case OPT__NO:
1150           {
1151             /* We support real --no-FOO flags now, but keep these
1152                short options for convenience and backward
1153                compatibility.  */
1154             for (p = optarg; p && *p; p++)
1155               switch (*p)
1156                 {
1157                 case 'v':
1158                   setoptval ("verbose", "0", cmdopt->long_name);
1159                   break;
1160                 case 'H':
1161                   setoptval ("addhostdir", "0", cmdopt->long_name);
1162                   break;
1163                 case 'd':
1164                   setoptval ("dirstruct", "0", cmdopt->long_name);
1165                   break;
1166                 case 'c':
1167                   setoptval ("noclobber", "1", cmdopt->long_name);
1168                   break;
1169                 case 'p':
1170                   setoptval ("noparent", "1", cmdopt->long_name);
1171                   break;
1172                 default:
1173                   fprintf (stderr, _("%s: illegal option -- `-n%c'\n"),
1174                            exec_name, *p);
1175                   print_usage (1);
1176                   fprintf (stderr, "\n");
1177                   fprintf (stderr, _("Try `%s --help' for more options.\n"),
1178                            exec_name);
1179                   exit (1);
1180                 }
1181             break;
1182           }
1183         case OPT__PARENT:
1184         case OPT__CLOBBER:
1185           {
1186             /* The wgetrc commands are named noparent and noclobber,
1187                so we must revert the meaning of the cmdline options
1188                before passing the value to setoptval.  */
1189             bool flag = true;
1190             if (optarg)
1191               flag = (*optarg == '1' || c_tolower (*optarg) == 'y'
1192                       || (c_tolower (optarg[0]) == 'o'
1193                           && c_tolower (optarg[1]) == 'n'));
1194             setoptval (cmdopt->type == OPT__PARENT ? "noparent" : "noclobber",
1195                        flag ? "0" : "1", cmdopt->long_name);
1196             break;
1197           }
1198         case OPT__DONT_REMOVE_LISTING:
1199           setoptval ("removelisting", "0", cmdopt->long_name);
1200           break;
1201         }
1202
1203       longindex = -1;
1204     }
1205
1206   nurl = argc - optind;
1207
1208   /* If we do not have Debug support compiled in AND Wget is invoked with the
1209    * --debug switch, instead of failing, we silently turn it into a no-op. For
1210    *  this no-op, we explicitly set opt.debug to false and hence none of the
1211    *  Debug output messages will be printed.
1212    */
1213 #ifndef ENABLE_DEBUG
1214   if (opt.debug)
1215     {
1216       fprintf (stderr, _("Debugging support not compiled in. "
1217                          "Ignoring --debug flag.\n"));
1218       opt.debug = false;
1219     }
1220 #endif
1221
1222   /* All user options have now been processed, so it's now safe to do
1223      interoption dependency checks. */
1224
1225   if (opt.noclobber && opt.convert_links)
1226     {
1227       fprintf (stderr,
1228                _("Both --no-clobber and --convert-links were specified,"
1229                  " only --convert-links will be used.\n"));
1230       opt.noclobber = false;
1231     }
1232
1233   if (opt.reclevel == 0)
1234       opt.reclevel = INFINITE_RECURSION; /* see recur.h for commentary */
1235
1236   if (opt.spider || opt.delete_after)
1237       opt.no_dirstruct = true;
1238
1239   if (opt.page_requisites && !opt.recursive)
1240     {
1241       /* Don't set opt.recursive here because it would confuse the FTP
1242          code.  Instead, call retrieve_tree below when either
1243          page_requisites or recursive is requested.  */
1244       opt.reclevel = 0;
1245       if (!opt.no_dirstruct)
1246         opt.dirstruct = 1;      /* normally handled by cmd_spec_recursive() */
1247     }
1248
1249   if (opt.verbose == -1)
1250     opt.verbose = !opt.quiet;
1251
1252   if (opt.verbose == 1)
1253     opt.show_progress = true;
1254
1255   /* Sanity checks.  */
1256   if (opt.verbose && opt.quiet)
1257     {
1258       fprintf (stderr, _("Can't be verbose and quiet at the same time.\n"));
1259       print_usage (1);
1260       exit (1);
1261     }
1262   if (opt.timestamping && opt.noclobber)
1263     {
1264       fprintf (stderr, _("\
1265 Can't timestamp and not clobber old files at the same time.\n"));
1266       print_usage (1);
1267       exit (1);
1268     }
1269 #ifdef ENABLE_IPV6
1270   if (opt.ipv4_only && opt.ipv6_only)
1271     {
1272       fprintf (stderr,
1273                _("Cannot specify both --inet4-only and --inet6-only.\n"));
1274       print_usage (1);
1275       exit (1);
1276     }
1277 #endif
1278   if (opt.output_document)
1279     {
1280       if (opt.convert_links
1281           && (nurl > 1 || opt.page_requisites || opt.recursive))
1282         {
1283           fputs (_("\
1284 Cannot specify both -k and -O if multiple URLs are given, or in combination\n\
1285 with -p or -r. See the manual for details.\n\n"), stderr);
1286           print_usage (1);
1287           exit (1);
1288         }
1289       if (opt.page_requisites
1290           || opt.recursive)
1291         {
1292           logprintf (LOG_NOTQUIET, "%s", _("\
1293 WARNING: combining -O with -r or -p will mean that all downloaded content\n\
1294 will be placed in the single file you specified.\n\n"));
1295         }
1296       if (opt.timestamping)
1297         {
1298           logprintf (LOG_NOTQUIET, "%s", _("\
1299 WARNING: timestamping does nothing in combination with -O. See the manual\n\
1300 for details.\n\n"));
1301           opt.timestamping = false;
1302         }
1303       if (opt.noclobber && file_exists_p(opt.output_document))
1304            {
1305               /* Check if output file exists; if it does, exit. */
1306               logprintf (LOG_VERBOSE,
1307                          _("File `%s' already there; not retrieving.\n"),
1308                          opt.output_document);
1309               exit(1);
1310            }
1311     }
1312
1313   if (opt.warc_filename != 0)
1314     {
1315       if (opt.noclobber)
1316         {
1317           fprintf (stderr,
1318                    _("WARC output does not work with --no-clobber, "
1319                      "--no-clobber will be disabled.\n"));
1320           opt.noclobber = false;
1321         }
1322       if (opt.timestamping)
1323         {
1324           fprintf (stderr,
1325                    _("WARC output does not work with timestamping, "
1326                      "timestamping will be disabled.\n"));
1327           opt.timestamping = false;
1328         }
1329       if (opt.spider)
1330         {
1331           fprintf (stderr,
1332                    _("WARC output does not work with --spider.\n"));
1333           exit (1);
1334         }
1335       if (opt.always_rest || opt.start_pos >= 0)
1336         {
1337           fprintf (stderr,
1338                    _("WARC output does not work with --continue or"
1339                      " --start-pos, they will be disabled.\n"));
1340           opt.always_rest = false;
1341           opt.start_pos = -1;
1342         }
1343       if (opt.warc_cdx_dedup_filename != 0 && !opt.warc_digests_enabled)
1344         {
1345           fprintf (stderr,
1346                    _("Digests are disabled; WARC deduplication will "
1347                      "not find duplicate records.\n"));
1348         }
1349       if (opt.warc_keep_log)
1350         {
1351           opt.progress_type = xstrdup ("dot");
1352         }
1353     }
1354
1355   if (opt.ask_passwd && opt.passwd)
1356     {
1357       fprintf (stderr,
1358                _("Cannot specify both --ask-password and --password.\n"));
1359       print_usage (1);
1360       exit (1);
1361     }
1362
1363   if (opt.start_pos >= 0 && opt.always_rest)
1364     {
1365       fprintf (stderr,
1366                _("Specifying both --start-pos and --continue is not "
1367                  "recommended; --continue will be disabled.\n"));
1368       opt.always_rest = false;
1369     }
1370
1371   if (!nurl && !opt.input_filename)
1372     {
1373       /* No URL specified.  */
1374       fprintf (stderr, _("%s: missing URL\n"), exec_name);
1375       print_usage (1);
1376       fprintf (stderr, "\n");
1377       /* #### Something nicer should be printed here -- similar to the
1378          pre-1.5 `--help' page.  */
1379       fprintf (stderr, _("Try `%s --help' for more options.\n"), exec_name);
1380       exit (1);
1381     }
1382
1383   /* Compile the regular expressions.  */
1384   switch (opt.regex_type)
1385     {
1386 #ifdef HAVE_LIBPCRE
1387       case regex_type_pcre:
1388         opt.regex_compile_fun = compile_pcre_regex;
1389         opt.regex_match_fun = match_pcre_regex;
1390         break;
1391 #endif
1392
1393       case regex_type_posix:
1394       default:
1395         opt.regex_compile_fun = compile_posix_regex;
1396         opt.regex_match_fun = match_posix_regex;
1397         break;
1398     }
1399   if (opt.acceptregex_s)
1400     {
1401       opt.acceptregex = opt.regex_compile_fun (opt.acceptregex_s);
1402       if (!opt.acceptregex)
1403         exit (1);
1404     }
1405   if (opt.rejectregex_s)
1406     {
1407       opt.rejectregex = opt.regex_compile_fun (opt.rejectregex_s);
1408       if (!opt.rejectregex)
1409         exit (1);
1410     }
1411   if (opt.post_data || opt.post_file_name)
1412     {
1413       if (opt.post_data && opt.post_file_name)
1414         {
1415           fprintf (stderr, _("You cannot specify both --post-data and --post-file.\n"));
1416           exit (1);
1417         }
1418       else if (opt.method)
1419         {
1420           fprintf (stderr, _("You cannot use --post-data or --post-file along with --method. "
1421                              "--method expects data through --body-data and --body-file options"));
1422           exit (1);
1423         }
1424     }
1425   if (opt.body_data || opt.body_file)
1426     {
1427       if (!opt.method)
1428         {
1429           fprintf (stderr, _("You must specify a method through --method=HTTPMethod "
1430                               "to use with --body-data or --body-file.\n"));
1431           exit (1);
1432         }
1433       else if (opt.body_data && opt.body_file)
1434         {
1435           fprintf (stderr, _("You cannot specify both --body-data and --body-file.\n"));
1436           exit (1);
1437         }
1438     }
1439
1440   /* Set various options as required for opt.method.  */
1441
1442   /* When user specifies HEAD as the method, we do not wish to download any
1443      files. Hence, set wget to run in spider mode.  */
1444   if (opt.method && strcasecmp (opt.method, "HEAD") == 0)
1445     setoptval ("spider", "1", "spider");
1446
1447   /* Convert post_data to body-data and post_file_name to body-file options.
1448      This is required so as to remove redundant code later on in gethttp().
1449      The --post-data and --post-file options may also be removed in
1450      the future hence it makes sense to convert them to aliases for
1451      the more generic --method options.
1452      This MUST occur only after the sanity checks so as to prevent the
1453      user from setting both post and body options simultaneously.
1454   */
1455   if (opt.post_data || opt.post_file_name)
1456     {
1457         setoptval ("method", "POST", "method");
1458         if (opt.post_data)
1459           {
1460             setoptval ("bodydata", opt.post_data, "body-data");
1461             opt.post_data = NULL;
1462           }
1463         else
1464           {
1465             setoptval ("bodyfile", opt.post_file_name, "body-file");
1466             opt.post_file_name = NULL;
1467           }
1468     }
1469
1470 #ifdef ENABLE_IRI
1471   if (opt.enable_iri)
1472     {
1473       if (opt.locale && !check_encoding_name (opt.locale))
1474         opt.locale = NULL;
1475
1476       if (!opt.locale)
1477         opt.locale = find_locale ();
1478
1479       if (opt.encoding_remote && !check_encoding_name (opt.encoding_remote))
1480         opt.encoding_remote = NULL;
1481     }
1482 #else
1483   memset (&dummy_iri, 0, sizeof (dummy_iri));
1484   if (opt.enable_iri || opt.locale || opt.encoding_remote)
1485     {
1486       /* sXXXav : be more specific... */
1487       fprintf (stderr, _("This version does not have support for IRIs\n"));
1488       exit(1);
1489     }
1490 #endif
1491
1492   if (opt.ask_passwd)
1493     {
1494       opt.passwd = prompt_for_password ();
1495
1496       if (opt.passwd == NULL || opt.passwd[0] == '\0')
1497         exit (1);
1498     }
1499
1500 #ifdef USE_WATT32
1501   if (opt.wdebug)
1502      dbug_init();
1503   sock_init();
1504 #else
1505   if (opt.background)
1506     fork_to_background ();
1507 #endif
1508
1509   /* Initialize progress.  Have to do this after the options are
1510      processed so we know where the log file is.  */
1511   if (opt.show_progress)
1512     set_progress_implementation (opt.progress_type);
1513
1514   /* Fill in the arguments.  */
1515   url = alloca_array (char *, nurl + 1);
1516   if (url == NULL)
1517     {
1518       fprintf (stderr, _("Memory allocation problem\n"));
1519       exit (2);
1520     }
1521   for (i = 0; i < nurl; i++, optind++)
1522     {
1523       char *rewritten = rewrite_shorthand_url (argv[optind]);
1524       if (rewritten)
1525         url[i] = rewritten;
1526       else
1527         url[i] = xstrdup (argv[optind]);
1528     }
1529   url[i] = NULL;
1530
1531   /* Initialize logging.  */
1532   log_init (opt.lfilename, append_to_log);
1533
1534   /* Open WARC file. */
1535   if (opt.warc_filename != 0)
1536     warc_init ();
1537
1538   DEBUGP (("DEBUG output created by Wget %s on %s.\n\n",
1539            version_string, OS_TYPE));
1540
1541   /* Open the output filename if necessary.  */
1542
1543 /* 2005-04-17 SMS.
1544    Note that having the output_stream ("-O") file opened here for an FTP
1545    URL rather than in getftp() (ftp.c) (and the http equivalent) rather
1546    limits the ability in VMS to open the file differently for ASCII
1547    versus binary FTP there.  (Of course, doing it here allows a open
1548    failure to be detected immediately, without first connecting to the
1549    server.)
1550 */
1551   if (opt.output_document)
1552     {
1553       if (HYPHENP (opt.output_document))
1554         {
1555 #ifdef WINDOWS
1556           _setmode (_fileno (stdout), _O_BINARY);
1557 #endif
1558           output_stream = stdout;
1559         }
1560       else
1561         {
1562           struct_fstat st;
1563
1564 #ifdef __VMS
1565 /* Common fopen() optional arguments:
1566    sequential access only, access callback function.
1567 */
1568 # define FOPEN_OPT_ARGS , "fop=sqo", "acc", acc_cb, &open_id
1569           int open_id = 7;
1570 #else /* def __VMS */
1571 # define FOPEN_OPT_ARGS
1572 #endif /* def __VMS [else] */
1573
1574           output_stream = fopen (opt.output_document,
1575                                  opt.always_rest ? "ab" : "wb"
1576                                  FOPEN_OPT_ARGS);
1577           if (output_stream == NULL)
1578             {
1579               perror (opt.output_document);
1580               exit (1);
1581             }
1582           if (fstat (fileno (output_stream), &st) == 0 && S_ISREG (st.st_mode))
1583             output_stream_regular = true;
1584         }
1585       if (!output_stream_regular && opt.convert_links)
1586         {
1587           fprintf (stderr, _("-k can be used together with -O only if \
1588 outputting to a regular file.\n"));
1589           print_usage (1);
1590           exit(1);
1591         }
1592     }
1593
1594 #ifdef __VMS
1595   /* Set global ODS5 flag according to the specified destination (if
1596      any), otherwise according to the current default device.
1597   */
1598   if (output_stream == NULL)
1599     set_ods5_dest( "SYS$DISK");
1600   else if (output_stream != stdout)
1601     set_ods5_dest( opt.output_document);
1602 #endif /* def __VMS */
1603
1604 #ifdef WINDOWS
1605   ws_startup ();
1606 #endif
1607
1608 #ifdef SIGHUP
1609   /* Setup the signal handler to redirect output when hangup is
1610      received.  */
1611   if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
1612     signal(SIGHUP, redirect_output_signal);
1613 #endif
1614   /* ...and do the same for SIGUSR1.  */
1615 #ifdef SIGUSR1
1616   signal (SIGUSR1, redirect_output_signal);
1617 #endif
1618 #ifdef SIGPIPE
1619   /* Writing to a closed socket normally signals SIGPIPE, and the
1620      process exits.  What we want is to ignore SIGPIPE and just check
1621      for the return value of write().  */
1622   signal (SIGPIPE, SIG_IGN);
1623 #endif
1624 #ifdef SIGWINCH
1625   signal (SIGWINCH, progress_handle_sigwinch);
1626 #endif
1627
1628   /* Retrieve the URLs from argument list.  */
1629   for (t = url; *t; t++)
1630     {
1631       char *filename = NULL, *redirected_URL = NULL;
1632       int dt, url_err;
1633       /* Need to do a new struct iri every time, because
1634        * retrieve_url may modify it in some circumstances,
1635        * currently. */
1636       struct iri *iri = iri_new ();
1637       struct url *url_parsed;
1638
1639       set_uri_encoding (iri, opt.locale, true);
1640       url_parsed = url_parse (*t, &url_err, iri, true);
1641
1642       if (!url_parsed)
1643         {
1644           char *error = url_error (*t, url_err);
1645           logprintf (LOG_NOTQUIET, "%s: %s.\n",*t, error);
1646           xfree (error);
1647           inform_exit_status (URLERROR);
1648         }
1649       else
1650         {
1651           if ((opt.recursive || opt.page_requisites)
1652               && (url_scheme (*t) != SCHEME_FTP || url_uses_proxy (url_parsed)))
1653             {
1654               int old_follow_ftp = opt.follow_ftp;
1655
1656               /* Turn opt.follow_ftp on in case of recursive FTP retrieval */
1657               if (url_scheme (*t) == SCHEME_FTP)
1658                 opt.follow_ftp = 1;
1659
1660               retrieve_tree (url_parsed, NULL);
1661
1662               opt.follow_ftp = old_follow_ftp;
1663             }
1664           else
1665           {
1666             retrieve_url (url_parsed, *t, &filename, &redirected_URL, NULL,
1667                           &dt, opt.recursive, iri, true);
1668           }
1669
1670           if (opt.delete_after && filename != NULL && file_exists_p (filename))
1671             {
1672               DEBUGP (("Removing file due to --delete-after in main():\n"));
1673               logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
1674               if (unlink (filename))
1675                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1676             }
1677           xfree_null (redirected_URL);
1678           xfree_null (filename);
1679           url_free (url_parsed);
1680         }
1681       iri_free (iri);
1682     }
1683
1684   /* And then from the input file, if any.  */
1685   if (opt.input_filename)
1686     {
1687       int count;
1688       int status;
1689       status = retrieve_from_file (opt.input_filename, opt.force_html, &count);
1690       inform_exit_status (status);
1691       if (!count)
1692         logprintf (LOG_NOTQUIET, _("No URLs found in %s.\n"),
1693                    opt.input_filename);
1694     }
1695
1696   /* Print broken links. */
1697   if (opt.recursive && opt.spider)
1698     print_broken_links ();
1699
1700   /* Print the downloaded sum.  */
1701   if ((opt.recursive || opt.page_requisites
1702        || nurl > 1
1703        || (opt.input_filename && total_downloaded_bytes != 0))
1704       &&
1705       total_downloaded_bytes != 0)
1706     {
1707       double end_time = ptimer_measure (timer);
1708       ptimer_destroy (timer);
1709
1710       char *wall_time = xstrdup (secs_to_human_time (end_time - start_time));
1711       char *download_time = xstrdup (secs_to_human_time (total_download_time));
1712       logprintf (LOG_NOTQUIET,
1713                  _("FINISHED --%s--\nTotal wall clock time: %s\n"
1714                    "Downloaded: %d files, %s in %s (%s)\n"),
1715                  datetime_str (time (NULL)),
1716                  wall_time,
1717                  numurls,
1718                  human_readable (total_downloaded_bytes, 10, 1),
1719                  download_time,
1720                  retr_rate (total_downloaded_bytes, total_download_time));
1721       xfree (wall_time);
1722       xfree (download_time);
1723
1724       /* Print quota warning, if exceeded.  */
1725       if (opt.quota && total_downloaded_bytes > opt.quota)
1726         logprintf (LOG_NOTQUIET,
1727                    _("Download quota of %s EXCEEDED!\n"),
1728                    human_readable (opt.quota, 10, 1));
1729     }
1730
1731   if (opt.cookies_output)
1732     save_cookies ();
1733
1734   if (opt.convert_links && !opt.delete_after)
1735     convert_all_links ();
1736
1737   cleanup ();
1738
1739   exit (get_exit_status ());
1740 }
1741 #endif /* TESTING */
1742 \f
1743 #if defined(SIGHUP) || defined(SIGUSR1)
1744
1745 /* So the signal_name check doesn't blow when only one is available. */
1746 #ifndef SIGHUP
1747 # define SIGHUP -1
1748 #endif
1749 #ifndef SIGUSR1
1750 # define SIGUSR1 -1
1751 #endif
1752
1753 /* Hangup signal handler.  When wget receives SIGHUP or SIGUSR1, it
1754    will proceed operation as usual, trying to write into a log file.
1755    If that is impossible, the output will be turned off.  */
1756
1757 static void
1758 redirect_output_signal (int sig)
1759 {
1760   const char *signal_name = (sig == SIGHUP ? "SIGHUP" :
1761                              (sig == SIGUSR1 ? "SIGUSR1" :
1762                               "WTF?!"));
1763   log_request_redirect_output (signal_name);
1764   progress_schedule_redirect ();
1765   signal (sig, redirect_output_signal);
1766 }
1767 #endif
1768
1769 /*
1770  * vim: et ts=2 sw=2
1771  */