]> sjero.net Git - wget/blob - src/main.c
3d99a1efe16939828632ae8191897ac6a6496067
[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     { "body-data", 0, OPT_VALUE, "bodydata", -1 },
165     { "body-file", 0, OPT_VALUE, "bodyfile", -1 },
166     { IF_SSL ("ca-certificate"), 0, OPT_VALUE, "cacertificate", -1 },
167     { IF_SSL ("ca-directory"), 0, OPT_VALUE, "cadirectory", -1 },
168     { "cache", 0, OPT_BOOLEAN, "cache", -1 },
169     { IF_SSL ("certificate"), 0, OPT_VALUE, "certificate", -1 },
170     { IF_SSL ("certificate-type"), 0, OPT_VALUE, "certificatetype", -1 },
171     { IF_SSL ("check-certificate"), 0, OPT_BOOLEAN, "checkcertificate", -1 },
172     { "clobber", 0, OPT__CLOBBER, NULL, optional_argument },
173     { "config", 0, OPT_VALUE, "chooseconfig", -1 },
174     { "connect-timeout", 0, OPT_VALUE, "connecttimeout", -1 },
175     { "continue", 'c', OPT_BOOLEAN, "continue", -1 },
176     { "convert-links", 'k', OPT_BOOLEAN, "convertlinks", -1 },
177     { "content-disposition", 0, OPT_BOOLEAN, "contentdisposition", -1 },
178     { "content-on-error", 0, OPT_BOOLEAN, "contentonerror", -1 },
179     { "cookies", 0, OPT_BOOLEAN, "cookies", -1 },
180     { "cut-dirs", 0, OPT_VALUE, "cutdirs", -1 },
181     { "debug", 'd', OPT_BOOLEAN, "debug", -1 },
182     { "default-page", 0, OPT_VALUE, "defaultpage", -1 },
183     { "delete-after", 0, OPT_BOOLEAN, "deleteafter", -1 },
184     { "directories", 0, OPT_BOOLEAN, "dirstruct", -1 },
185     { "directory-prefix", 'P', OPT_VALUE, "dirprefix", -1 },
186     { "dns-cache", 0, OPT_BOOLEAN, "dnscache", -1 },
187     { "dns-timeout", 0, OPT_VALUE, "dnstimeout", -1 },
188     { "domains", 'D', OPT_VALUE, "domains", -1 },
189     { "dont-remove-listing", 0, OPT__DONT_REMOVE_LISTING, NULL, no_argument },
190     { "dot-style", 0, OPT_VALUE, "dotstyle", -1 }, /* deprecated */
191     { "egd-file", 0, OPT_VALUE, "egdfile", -1 },
192     { "exclude-directories", 'X', OPT_VALUE, "excludedirectories", -1 },
193     { "exclude-domains", 0, OPT_VALUE, "excludedomains", -1 },
194     { "execute", 'e', OPT__EXECUTE, NULL, required_argument },
195     { "follow-ftp", 0, OPT_BOOLEAN, "followftp", -1 },
196     { "follow-tags", 0, OPT_VALUE, "followtags", -1 },
197     { "force-directories", 'x', OPT_BOOLEAN, "dirstruct", -1 },
198     { "force-html", 'F', OPT_BOOLEAN, "forcehtml", -1 },
199     { "ftp-password", 0, OPT_VALUE, "ftppassword", -1 },
200 #ifdef __VMS
201     { "ftp-stmlf", 0, OPT_BOOLEAN, "ftpstmlf", -1 },
202 #endif /* def __VMS */
203     { "ftp-user", 0, OPT_VALUE, "ftpuser", -1 },
204     { "glob", 0, OPT_BOOLEAN, "glob", -1 },
205     { "header", 0, OPT_VALUE, "header", -1 },
206     { "help", 'h', OPT_FUNCALL, (void *)print_help, no_argument },
207     { "host-directories", 0, OPT_BOOLEAN, "addhostdir", -1 },
208     { "html-extension", 'E', OPT_BOOLEAN, "adjustextension", -1 }, /* deprecated */
209     { "htmlify", 0, OPT_BOOLEAN, "htmlify", -1 },
210     { "http-keep-alive", 0, OPT_BOOLEAN, "httpkeepalive", -1 },
211     { "http-passwd", 0, OPT_VALUE, "httppassword", -1 }, /* deprecated */
212     { "http-password", 0, OPT_VALUE, "httppassword", -1 },
213     { "http-user", 0, OPT_VALUE, "httpuser", -1 },
214     { IF_SSL ("https-only"), 0, OPT_BOOLEAN, "httpsonly", -1 },
215     { "ignore-case", 0, OPT_BOOLEAN, "ignorecase", -1 },
216     { "ignore-length", 0, OPT_BOOLEAN, "ignorelength", -1 },
217     { "ignore-tags", 0, OPT_VALUE, "ignoretags", -1 },
218     { "include-directories", 'I', OPT_VALUE, "includedirectories", -1 },
219 #ifdef ENABLE_IPV6
220     { "inet4-only", '4', OPT_BOOLEAN, "inet4only", -1 },
221     { "inet6-only", '6', OPT_BOOLEAN, "inet6only", -1 },
222 #endif
223     { "input-file", 'i', OPT_VALUE, "input", -1 },
224     { "iri", 0, OPT_BOOLEAN, "iri", -1 },
225     { "keep-session-cookies", 0, OPT_BOOLEAN, "keepsessioncookies", -1 },
226     { "level", 'l', OPT_VALUE, "reclevel", -1 },
227     { "limit-rate", 0, OPT_VALUE, "limitrate", -1 },
228     { "load-cookies", 0, OPT_VALUE, "loadcookies", -1 },
229     { "local-encoding", 0, OPT_VALUE, "localencoding", -1 },
230     { "max-redirect", 0, OPT_VALUE, "maxredirect", -1 },
231     { "method", 0, OPT_VALUE, "method", -1 },
232     { "mirror", 'm', OPT_BOOLEAN, "mirror", -1 },
233     { "no", 'n', OPT__NO, NULL, required_argument },
234     { "no-clobber", 0, OPT_BOOLEAN, "noclobber", -1 },
235     { "no-config", 0, OPT_BOOLEAN, "noconfig", -1},
236     { "no-parent", 0, OPT_BOOLEAN, "noparent", -1 },
237     { "output-document", 'O', OPT_VALUE, "outputdocument", -1 },
238     { "output-file", 'o', OPT_VALUE, "logfile", -1 },
239     { "page-requisites", 'p', OPT_BOOLEAN, "pagerequisites", -1 },
240     { "parent", 0, OPT__PARENT, NULL, optional_argument },
241     { "passive-ftp", 0, OPT_BOOLEAN, "passiveftp", -1 },
242     { "password", 0, OPT_VALUE, "password", -1 },
243     { "post-data", 0, OPT_VALUE, "postdata", -1 },
244     { "post-file", 0, OPT_VALUE, "postfile", -1 },
245     { "prefer-family", 0, OPT_VALUE, "preferfamily", -1 },
246     { "preserve-permissions", 0, OPT_BOOLEAN, "preservepermissions", -1 },
247     { IF_SSL ("private-key"), 0, OPT_VALUE, "privatekey", -1 },
248     { IF_SSL ("private-key-type"), 0, OPT_VALUE, "privatekeytype", -1 },
249     { "progress", 0, OPT_VALUE, "progress", -1 },
250     { "show-progress", 0, OPT_BOOLEAN, "showprogress", -1 },
251     { "protocol-directories", 0, OPT_BOOLEAN, "protocoldirectories", -1 },
252     { "proxy", 0, OPT_BOOLEAN, "useproxy", -1 },
253     { "proxy__compat", 'Y', OPT_VALUE, "useproxy", -1 }, /* back-compatible */
254     { "proxy-passwd", 0, OPT_VALUE, "proxypassword", -1 }, /* deprecated */
255     { "proxy-password", 0, OPT_VALUE, "proxypassword", -1 },
256     { "proxy-user", 0, OPT_VALUE, "proxyuser", -1 },
257     { "quiet", 'q', OPT_BOOLEAN, "quiet", -1 },
258     { "quota", 'Q', OPT_VALUE, "quota", -1 },
259     { "random-file", 0, OPT_VALUE, "randomfile", -1 },
260     { "random-wait", 0, OPT_BOOLEAN, "randomwait", -1 },
261     { "read-timeout", 0, OPT_VALUE, "readtimeout", -1 },
262     { "recursive", 'r', OPT_BOOLEAN, "recursive", -1 },
263     { "referer", 0, OPT_VALUE, "referer", -1 },
264     { "regex-type", 0, OPT_VALUE, "regextype", -1 },
265     { "reject", 'R', OPT_VALUE, "reject", -1 },
266     { "reject-regex", 0, OPT_VALUE, "rejectregex", -1 },
267     { "relative", 'L', OPT_BOOLEAN, "relativeonly", -1 },
268     { "remote-encoding", 0, OPT_VALUE, "remoteencoding", -1 },
269     { "remove-listing", 0, OPT_BOOLEAN, "removelisting", -1 },
270     { "report-speed", 0, OPT_BOOLEAN, "reportspeed", -1 },
271     { "restrict-file-names", 0, OPT_BOOLEAN, "restrictfilenames", -1 },
272     { "retr-symlinks", 0, OPT_BOOLEAN, "retrsymlinks", -1 },
273     { "retry-connrefused", 0, OPT_BOOLEAN, "retryconnrefused", -1 },
274     { "save-cookies", 0, OPT_VALUE, "savecookies", -1 },
275     { "save-headers", 0, OPT_BOOLEAN, "saveheaders", -1 },
276     { IF_SSL ("secure-protocol"), 0, OPT_VALUE, "secureprotocol", -1 },
277     { "server-response", 'S', OPT_BOOLEAN, "serverresponse", -1 },
278     { "span-hosts", 'H', OPT_BOOLEAN, "spanhosts", -1 },
279     { "spider", 0, OPT_BOOLEAN, "spider", -1 },
280     { "start-pos", 0, OPT_VALUE, "startpos", -1 },
281     { "strict-comments", 0, OPT_BOOLEAN, "strictcomments", -1 },
282     { "timeout", 'T', OPT_VALUE, "timeout", -1 },
283     { "timestamping", 'N', OPT_BOOLEAN, "timestamping", -1 },
284     { "tries", 't', OPT_VALUE, "tries", -1 },
285     { "unlink", 0, OPT_BOOLEAN, "unlink", -1 },
286     { "trust-server-names", 0, OPT_BOOLEAN, "trustservernames", -1 },
287     { "use-server-timestamps", 0, OPT_BOOLEAN, "useservertimestamps", -1 },
288     { "user", 0, OPT_VALUE, "user", -1 },
289     { "user-agent", 'U', OPT_VALUE, "useragent", -1 },
290     { "verbose", 'v', OPT_BOOLEAN, "verbose", -1 },
291     { "verbose", 0, OPT_BOOLEAN, "verbose", -1 },
292     { "version", 'V', OPT_FUNCALL, (void *) print_version, no_argument },
293     { "wait", 'w', OPT_VALUE, "wait", -1 },
294     { "waitretry", 0, OPT_VALUE, "waitretry", -1 },
295     { "warc-cdx", 0, OPT_BOOLEAN, "warccdx", -1 },
296 #ifdef HAVE_LIBZ
297     { "warc-compression", 0, OPT_BOOLEAN, "warccompression", -1 },
298 #endif
299     { "warc-dedup", 0, OPT_VALUE, "warccdxdedup", -1 },
300     { "warc-digests", 0, OPT_BOOLEAN, "warcdigests", -1 },
301     { "warc-file", 0, OPT_VALUE, "warcfile", -1 },
302     { "warc-header", 0, OPT_VALUE, "warcheader", -1 },
303     { "warc-keep-log", 0, OPT_BOOLEAN, "warckeeplog", -1 },
304     { "warc-max-size", 0, OPT_VALUE, "warcmaxsize", -1 },
305     { "warc-tempdir", 0, OPT_VALUE, "warctempdir", -1 },
306 #ifdef USE_WATT32
307     { "wdebug", 0, OPT_BOOLEAN, "wdebug", -1 },
308 #endif
309   };
310
311 #undef IF_SSL
312
313 /* Return a string that contains S with "no-" prepended.  The string
314    is NUL-terminated and allocated off static storage at Wget
315    startup.  */
316
317 static char *
318 no_prefix (const char *s)
319 {
320   static char buffer[2048];
321   static char *p = buffer;
322
323   char *cp = p;
324   int size = 3 + strlen (s) + 1;  /* "no-STRING\0" */
325   if (p + size >= buffer + sizeof (buffer))
326     abort ();
327
328   cp[0] = 'n', cp[1] = 'o', cp[2] = '-';
329   strcpy (cp + 3, s);
330   p += size;
331   return cp;
332 }
333
334 /* The arguments that that main passes to getopt_long. */
335 static struct option long_options[2 * countof (option_data) + 1];
336 static char short_options[128];
337
338 /* Mapping between short option chars and option_data indices. */
339 static unsigned char optmap[96];
340
341 /* Marker for `--no-FOO' values in long_options.  */
342 #define BOOLEAN_NEG_MARKER 1024
343
344 /* Initialize the long_options array used by getopt_long from the data
345    in option_data.  */
346
347 static void
348 init_switches (void)
349 {
350   char *p = short_options;
351   size_t i, o = 0;
352   for (i = 0; i < countof (option_data); i++)
353     {
354       struct cmdline_option *opt = &option_data[i];
355       struct option *longopt;
356
357       if (!opt->long_name)
358         /* The option is disabled. */
359         continue;
360
361       longopt = &long_options[o++];
362       longopt->name = opt->long_name;
363       longopt->val = i;
364       if (opt->short_name)
365         {
366           *p++ = opt->short_name;
367           optmap[opt->short_name - 32] = longopt - long_options;
368         }
369       switch (opt->type)
370         {
371         case OPT_VALUE:
372           longopt->has_arg = required_argument;
373           if (opt->short_name)
374             *p++ = ':';
375           break;
376         case OPT_BOOLEAN:
377           /* Specify an optional argument for long options, so that
378              --option=off works the same as --no-option, for
379              compatibility with pre-1.10 Wget.  However, don't specify
380              optional arguments short-option booleans because they
381              prevent combining of short options.  */
382           longopt->has_arg = optional_argument;
383           /* For Boolean options, add the "--no-FOO" variant, which is
384              identical to "--foo", except it has opposite meaning and
385              it doesn't allow an argument.  */
386           longopt = &long_options[o++];
387           longopt->name = no_prefix (opt->long_name);
388           longopt->has_arg = no_argument;
389           /* Mask the value so we'll be able to recognize that we're
390              dealing with the false value.  */
391           longopt->val = i | BOOLEAN_NEG_MARKER;
392           break;
393         default:
394           assert (opt->argtype != -1);
395           longopt->has_arg = opt->argtype;
396           if (opt->short_name)
397             {
398               if (longopt->has_arg == required_argument)
399                 *p++ = ':';
400               /* Don't handle optional_argument */
401             }
402         }
403     }
404   /* Terminate short_options. */
405   *p = '\0';
406   /* No need for xzero(long_options[o]) because its storage is static
407      and it will be zeroed by default.  */
408   assert (o <= countof (long_options));
409 }
410
411 /* Print the usage message.  */
412 static int
413 print_usage (int error)
414 {
415   return fprintf (error ? stderr : stdout,
416                   _("Usage: %s [OPTION]... [URL]...\n"), exec_name);
417 }
418
419 /* Print the help message, describing all the available options.  If
420    you add an option, be sure to update this list.  */
421 static void
422 print_help (void)
423 {
424   /* We split the help text this way to ease translation of individual
425      entries.  */
426   static const char *help[] = {
427     "\n",
428     N_("\
429 Mandatory arguments to long options are mandatory for short options too.\n\n"),
430     N_("\
431 Startup:\n"),
432     N_("\
433   -V,  --version           display the version of Wget and exit.\n"),
434     N_("\
435   -h,  --help              print this help.\n"),
436     N_("\
437   -b,  --background        go to background after startup.\n"),
438     N_("\
439   -e,  --execute=COMMAND   execute a `.wgetrc'-style command.\n"),
440     "\n",
441
442     N_("\
443 Logging and input file:\n"),
444     N_("\
445   -o,  --output-file=FILE    log messages to FILE.\n"),
446     N_("\
447   -a,  --append-output=FILE  append messages to FILE.\n"),
448 #ifdef ENABLE_DEBUG
449     N_("\
450   -d,  --debug               print lots of debugging information.\n"),
451 #endif
452 #ifdef USE_WATT32
453     N_("\
454        --wdebug              print Watt-32 debug output.\n"),
455 #endif
456     N_("\
457   -q,  --quiet               quiet (no output).\n"),
458     N_("\
459   -v,  --verbose             be verbose (this is the default).\n"),
460     N_("\
461   -nv, --no-verbose          turn off verboseness, without being quiet.\n"),
462     N_("\
463        --report-speed=TYPE   Output bandwidth as TYPE.  TYPE can be bits.\n"),
464     N_("\
465   -i,  --input-file=FILE     download URLs found in local or external FILE.\n"),
466     N_("\
467   -F,  --force-html          treat input file as HTML.\n"),
468     N_("\
469   -B,  --base=URL            resolves HTML input-file links (-i -F)\n\
470                              relative to URL.\n"),
471     N_("\
472        --config=FILE         Specify config file to use.\n"),
473     N_("\
474        --no-config           Do not read any config file.\n"),
475     "\n",
476
477     N_("\
478 Download:\n"),
479     N_("\
480   -t,  --tries=NUMBER            set number of retries to NUMBER (0 unlimits).\n"),
481     N_("\
482        --retry-connrefused       retry even if connection is refused.\n"),
483     N_("\
484   -O,  --output-document=FILE    write documents to FILE.\n"),
485     N_("\
486   -nc, --no-clobber              skip downloads that would download to\n\
487                                  existing files (overwriting them).\n"),
488     N_("\
489   -c,  --continue                resume getting a partially-downloaded file.\n"),
490     N_("\
491        --start-pos=OFFSET        start downloading from zero-based position OFFSET.\n"),
492     N_("\
493        --progress=TYPE           select progress gauge type.\n"),
494     N_("\
495        --show-progress           display the progress bar in any verbosity mode.\n"),
496     N_("\
497   -N,  --timestamping            don't re-retrieve files unless newer than\n\
498                                  local.\n"),
499     N_("\
500   --no-use-server-timestamps     don't set the local file's timestamp by\n\
501                                  the one on the server.\n"),
502     N_("\
503   -S,  --server-response         print server response.\n"),
504     N_("\
505        --spider                  don't download anything.\n"),
506     N_("\
507   -T,  --timeout=SECONDS         set all timeout values to SECONDS.\n"),
508     N_("\
509        --dns-timeout=SECS        set the DNS lookup timeout to SECS.\n"),
510     N_("\
511        --connect-timeout=SECS    set the connect timeout to SECS.\n"),
512     N_("\
513        --read-timeout=SECS       set the read timeout to SECS.\n"),
514     N_("\
515   -w,  --wait=SECONDS            wait SECONDS between retrievals.\n"),
516     N_("\
517        --waitretry=SECONDS       wait 1..SECONDS between retries of a retrieval.\n"),
518     N_("\
519        --random-wait             wait from 0.5*WAIT...1.5*WAIT secs between retrievals.\n"),
520     N_("\
521        --no-proxy                explicitly turn off proxy.\n"),
522     N_("\
523   -Q,  --quota=NUMBER            set retrieval quota to NUMBER.\n"),
524     N_("\
525        --bind-address=ADDRESS    bind to ADDRESS (hostname or IP) on local host.\n"),
526     N_("\
527        --limit-rate=RATE         limit download rate to RATE.\n"),
528     N_("\
529        --no-dns-cache            disable caching DNS lookups.\n"),
530     N_("\
531        --restrict-file-names=OS  restrict chars in file names to ones OS allows.\n"),
532     N_("\
533        --ignore-case             ignore case when matching files/directories.\n"),
534 #ifdef ENABLE_IPV6
535     N_("\
536   -4,  --inet4-only              connect only to IPv4 addresses.\n"),
537     N_("\
538   -6,  --inet6-only              connect only to IPv6 addresses.\n"),
539     N_("\
540        --prefer-family=FAMILY    connect first to addresses of specified family,\n\
541                                  one of IPv6, IPv4, or none.\n"),
542 #endif
543     N_("\
544        --user=USER               set both ftp and http user to USER.\n"),
545     N_("\
546        --password=PASS           set both ftp and http password to PASS.\n"),
547     N_("\
548        --ask-password            prompt for passwords.\n"),
549     N_("\
550        --no-iri                  turn off IRI support.\n"),
551     N_("\
552        --local-encoding=ENC      use ENC as the local encoding for IRIs.\n"),
553     N_("\
554        --remote-encoding=ENC     use ENC as the default remote encoding.\n"),
555     N_("\
556        --unlink                  remove file before clobber.\n"),
557     "\n",
558
559     N_("\
560 Directories:\n"),
561     N_("\
562   -nd, --no-directories           don't create directories.\n"),
563     N_("\
564   -x,  --force-directories        force creation of directories.\n"),
565     N_("\
566   -nH, --no-host-directories      don't create host directories.\n"),
567     N_("\
568        --protocol-directories     use protocol name in directories.\n"),
569     N_("\
570   -P,  --directory-prefix=PREFIX  save files to PREFIX/...\n"),
571     N_("\
572        --cut-dirs=NUMBER          ignore NUMBER remote directory components.\n"),
573     "\n",
574
575     N_("\
576 HTTP options:\n"),
577     N_("\
578        --http-user=USER        set http user to USER.\n"),
579     N_("\
580        --http-password=PASS    set http password to PASS.\n"),
581     N_("\
582        --no-cache              disallow server-cached data.\n"),
583     N_ ("\
584        --default-page=NAME     Change the default page name (normally\n\
585                                this is `index.html'.).\n"),
586     N_("\
587   -E,  --adjust-extension      save HTML/CSS documents with proper extensions.\n"),
588     N_("\
589        --ignore-length         ignore `Content-Length' header field.\n"),
590     N_("\
591        --header=STRING         insert STRING among the headers.\n"),
592     N_("\
593        --max-redirect          maximum redirections allowed per page.\n"),
594     N_("\
595        --proxy-user=USER       set USER as proxy username.\n"),
596     N_("\
597        --proxy-password=PASS   set PASS as proxy password.\n"),
598     N_("\
599        --referer=URL           include `Referer: URL' header in HTTP request.\n"),
600     N_("\
601        --save-headers          save the HTTP headers to file.\n"),
602     N_("\
603   -U,  --user-agent=AGENT      identify as AGENT instead of Wget/VERSION.\n"),
604     N_("\
605        --no-http-keep-alive    disable HTTP keep-alive (persistent connections).\n"),
606     N_("\
607        --no-cookies            don't use cookies.\n"),
608     N_("\
609        --load-cookies=FILE     load cookies from FILE before session.\n"),
610     N_("\
611        --save-cookies=FILE     save cookies to FILE after session.\n"),
612     N_("\
613        --keep-session-cookies  load and save session (non-permanent) cookies.\n"),
614     N_("\
615        --post-data=STRING      use the POST method; send STRING as the data.\n"),
616     N_("\
617        --post-file=FILE        use the POST method; send contents of FILE.\n"),
618     N_("\
619        --method=HTTPMethod     use method \"HTTPMethod\" in the header.\n"),
620     N_("\
621        --body-data=STRING      Send STRING as data. --method MUST be set.\n"),
622     N_("\
623        --body-file=FILE        Send contents of FILE. --method MUST be set.\n"),
624     N_("\
625        --content-disposition   honor the Content-Disposition header when\n\
626                                choosing local file names (EXPERIMENTAL).\n"),
627     N_("\
628        --content-on-error      output the received content on server errors.\n"),
629     N_("\
630        --auth-no-challenge     send Basic HTTP authentication information\n\
631                                without first waiting for the server's\n\
632                                challenge.\n"),
633     "\n",
634
635 #ifdef HAVE_SSL
636     N_("\
637 HTTPS (SSL/TLS) options:\n"),
638     N_("\
639        --secure-protocol=PR     choose secure protocol, one of auto, SSLv2,\n\
640                                 SSLv3, TLSv1 and PFS.\n"),
641     N_("\
642        --https-only             only follow secure HTTPS links\n"),
643     N_("\
644        --no-check-certificate   don't validate the server's certificate.\n"),
645     N_("\
646        --certificate=FILE       client certificate file.\n"),
647     N_("\
648        --certificate-type=TYPE  client certificate type, PEM or DER.\n"),
649     N_("\
650        --private-key=FILE       private key file.\n"),
651     N_("\
652        --private-key-type=TYPE  private key type, PEM or DER.\n"),
653     N_("\
654        --ca-certificate=FILE    file with the bundle of CA's.\n"),
655     N_("\
656        --ca-directory=DIR       directory where hash list of CA's is stored.\n"),
657     N_("\
658        --random-file=FILE       file with random data for seeding the SSL PRNG.\n"),
659     N_("\
660        --egd-file=FILE          file naming the EGD socket with random data.\n"),
661     "\n",
662 #endif /* HAVE_SSL */
663
664     N_("\
665 FTP options:\n"),
666 #ifdef __VMS
667     N_("\
668        --ftp-stmlf             Use Stream_LF format for all binary FTP files.\n"),
669 #endif /* def __VMS */
670     N_("\
671        --ftp-user=USER         set ftp user to USER.\n"),
672     N_("\
673        --ftp-password=PASS     set ftp password to PASS.\n"),
674     N_("\
675        --no-remove-listing     don't remove `.listing' files.\n"),
676     N_("\
677        --no-glob               turn off FTP file name globbing.\n"),
678     N_("\
679        --no-passive-ftp        disable the \"passive\" transfer mode.\n"),
680     N_("\
681        --preserve-permissions  preserve remote file permissions.\n"),
682     N_("\
683        --retr-symlinks         when recursing, get linked-to files (not dir).\n"),
684     "\n",
685
686     N_("\
687 WARC options:\n"),
688     N_("\
689        --warc-file=FILENAME      save request/response data to a .warc.gz file.\n"),
690     N_("\
691        --warc-header=STRING      insert STRING into the warcinfo record.\n"),
692     N_("\
693        --warc-max-size=NUMBER    set maximum size of WARC files to NUMBER.\n"),
694     N_("\
695        --warc-cdx                write CDX index files.\n"),
696     N_("\
697        --warc-dedup=FILENAME     do not store records listed in this CDX file.\n"),
698 #ifdef HAVE_LIBZ
699     N_("\
700        --no-warc-compression     do not compress WARC files with GZIP.\n"),
701 #endif
702     N_("\
703        --no-warc-digests         do not calculate SHA1 digests.\n"),
704     N_("\
705        --no-warc-keep-log        do not store the log file in a WARC record.\n"),
706     N_("\
707        --warc-tempdir=DIRECTORY  location for temporary files created by the\n\
708                                  WARC writer.\n"),
709     "\n",
710
711     N_("\
712 Recursive download:\n"),
713     N_("\
714   -r,  --recursive          specify recursive download.\n"),
715     N_("\
716   -l,  --level=NUMBER       maximum recursion depth (inf or 0 for infinite).\n"),
717     N_("\
718        --delete-after       delete files locally after downloading them.\n"),
719     N_("\
720   -k,  --convert-links      make links in downloaded HTML or CSS point to\n\
721                             local files.\n"),
722     N_("\
723   --backups=N   before writing file X, rotate up to N backup files.\n"),
724
725 #ifdef __VMS
726     N_("\
727   -K,  --backup-converted   before converting file X, back up as X_orig.\n"),
728 #else /* def __VMS */
729     N_("\
730   -K,  --backup-converted   before converting file X, back up as X.orig.\n"),
731 #endif /* def __VMS [else] */
732     N_("\
733   -m,  --mirror             shortcut for -N -r -l inf --no-remove-listing.\n"),
734     N_("\
735   -p,  --page-requisites    get all images, etc. needed to display HTML page.\n"),
736     N_("\
737        --strict-comments    turn on strict (SGML) handling of HTML comments.\n"),
738     "\n",
739
740     N_("\
741 Recursive accept/reject:\n"),
742     N_("\
743   -A,  --accept=LIST               comma-separated list of accepted extensions.\n"),
744     N_("\
745   -R,  --reject=LIST               comma-separated list of rejected extensions.\n"),
746     N_("\
747        --accept-regex=REGEX        regex matching accepted URLs.\n"),
748     N_("\
749        --reject-regex=REGEX        regex matching rejected URLs.\n"),
750 #ifdef HAVE_LIBPCRE
751     N_("\
752        --regex-type=TYPE           regex type (posix|pcre).\n"),
753 #else
754     N_("\
755        --regex-type=TYPE           regex type (posix).\n"),
756 #endif
757     N_("\
758   -D,  --domains=LIST              comma-separated list of accepted domains.\n"),
759     N_("\
760        --exclude-domains=LIST      comma-separated list of rejected domains.\n"),
761     N_("\
762        --follow-ftp                follow FTP links from HTML documents.\n"),
763     N_("\
764        --follow-tags=LIST          comma-separated list of followed HTML tags.\n"),
765     N_("\
766        --ignore-tags=LIST          comma-separated list of ignored HTML tags.\n"),
767     N_("\
768   -H,  --span-hosts                go to foreign hosts when recursive.\n"),
769     N_("\
770   -L,  --relative                  follow relative links only.\n"),
771     N_("\
772   -I,  --include-directories=LIST  list of allowed directories.\n"),
773     N_("\
774   --trust-server-names             use the name specified by the redirection\n\
775                                    url last component.\n"),
776     N_("\
777   -X,  --exclude-directories=LIST  list of excluded directories.\n"),
778     N_("\
779   -np, --no-parent                 don't ascend to the parent directory.\n"),
780     "\n",
781     N_("Mail bug reports and suggestions to <bug-wget@gnu.org>.\n")
782   };
783
784   size_t i;
785
786   if (printf (_("GNU Wget %s, a non-interactive network retriever.\n"),
787               version_string) < 0)
788     exit (3);
789   if (print_usage (0) < 0)
790     exit (3);
791
792   for (i = 0; i < countof (help); i++)
793     if (fputs (_(help[i]), stdout) < 0)
794       exit (3);
795
796   exit (0);
797 }
798
799 /* Return a human-readable printed representation of INTERVAL,
800    measured in seconds.  */
801
802 static char *
803 secs_to_human_time (double interval)
804 {
805   static char buf[32];
806   int secs = (int) (interval + 0.5);
807   int hours, mins, days;
808
809   days = secs / 86400, secs %= 86400;
810   hours = secs / 3600, secs %= 3600;
811   mins = secs / 60, secs %= 60;
812
813   if (days)
814     sprintf (buf, "%dd %dh %dm %ds", days, hours, mins, secs);
815   else if (hours)
816     sprintf (buf, "%dh %dm %ds", hours, mins, secs);
817   else if (mins)
818     sprintf (buf, "%dm %ds", mins, secs);
819   else
820     sprintf (buf, "%ss", print_decimal (interval));
821
822   return buf;
823 }
824
825 static char *
826 prompt_for_password (void)
827 {
828   if (opt.user)
829     fprintf (stderr, _("Password for user %s: "), quote (opt.user));
830   else
831     fprintf (stderr, _("Password: "));
832   return getpass("");
833 }
834
835 /* Function that prints the line argument while limiting it
836    to at most line_length. prefix is printed on the first line
837    and an appropriate number of spaces are added on subsequent
838    lines.*/
839 static int
840 format_and_print_line (const char *prefix, const char *line,
841                        int line_length)
842 {
843   int remaining_chars;
844   char *line_dup, *token;
845
846   assert (prefix != NULL);
847   assert (line != NULL);
848   assert (line_length > TABULATION);
849
850   line_dup = xstrdup (line);
851
852   if (printf ("%s", prefix) < 0)
853     return -1;
854
855   /* Wrap to new line after prefix. */
856   remaining_chars = 0;
857
858   /* We break on spaces. */
859   token = strtok (line_dup, " ");
860   while (token != NULL)
861     {
862       /* If however a token is much larger than the maximum
863          line length, all bets are off and we simply print the
864          token on the next line. */
865       if (remaining_chars <= (int) strlen (token))
866         {
867           if (printf ("\n%*c", TABULATION, ' ') < 0)
868             return -1;
869           remaining_chars = line_length - TABULATION;
870         }
871       if (printf ("%s ", token) < 0)
872         return -1;
873       remaining_chars -= strlen (token) + 1;  /* account for " " */
874       token = strtok (NULL, " ");
875     }
876
877   if (printf ("\n") < 0)
878     return -1;
879
880   xfree (line_dup);
881   return 0;
882 }
883
884 static void
885 print_version (void)
886 {
887   const char *wgetrc_title  = _("Wgetrc: ");
888   const char *locale_title  = _("Locale: ");
889   const char *compile_title = _("Compile: ");
890   const char *link_title    = _("Link: ");
891   char *env_wgetrc, *user_wgetrc;
892   int i;
893
894   if (printf (_("GNU Wget %s built on %s.\n\n"), version_string, OS_TYPE) < 0)
895     exit (3);
896
897   for (i = 0; compiled_features[i] != NULL; )
898     {
899       int line_length = MAX_CHARS_PER_LINE;
900       while ((line_length > 0) && (compiled_features[i] != NULL))
901         {
902           if (printf ("%s ", compiled_features[i]) < 0)
903             exit (3);
904           line_length -= strlen (compiled_features[i]) + 2;
905           i++;
906         }
907       if (printf ("\n") < 0)
908         exit (3);
909     }
910   if (printf ("\n") < 0)
911     exit (3);
912
913   /* Handle the case when $WGETRC is unset and $HOME/.wgetrc is
914      absent. */
915   if (printf ("%s\n", wgetrc_title) < 0)
916     exit (3);
917
918   env_wgetrc = wgetrc_env_file_name ();
919   if (env_wgetrc && *env_wgetrc)
920     {
921       if (printf (_("    %s (env)\n"), env_wgetrc) < 0)
922         exit (3);
923       xfree (env_wgetrc);
924     }
925   user_wgetrc = wgetrc_user_file_name ();
926   if (user_wgetrc)
927     {
928       if (printf (_("    %s (user)\n"), user_wgetrc) < 0)
929         exit (3);
930       xfree (user_wgetrc);
931     }
932 #ifdef SYSTEM_WGETRC
933   if (printf (_("    %s (system)\n"), SYSTEM_WGETRC) < 0)
934     exit (3);
935 #endif
936
937 #ifdef ENABLE_NLS
938   if (format_and_print_line (locale_title,
939                              LOCALEDIR,
940                              MAX_CHARS_PER_LINE) < 0)
941     exit (3);
942 #endif /* def ENABLE_NLS */
943
944   if (compilation_string != NULL)
945     if (format_and_print_line (compile_title,
946                                compilation_string,
947                                MAX_CHARS_PER_LINE) < 0)
948       exit (3);
949
950   if (link_string != NULL)
951     if (format_and_print_line (link_title,
952                                link_string,
953                                MAX_CHARS_PER_LINE) < 0)
954       exit (3);
955
956   if (printf ("\n") < 0)
957     exit (3);
958
959   /* TRANSLATORS: When available, an actual copyright character
960      (circle-c) should be used in preference to "(C)". */
961   if (printf (_("\
962 Copyright (C) %s Free Software Foundation, Inc.\n"), "2014") < 0)
963     exit (3);
964   if (fputs (_("\
965 License GPLv3+: GNU GPL version 3 or later\n\
966 <http://www.gnu.org/licenses/gpl.html>.\n\
967 This is free software: you are free to change and redistribute it.\n\
968 There is NO WARRANTY, to the extent permitted by law.\n"), stdout) < 0)
969     exit (3);
970   /* TRANSLATORS: When available, please use the proper diacritics for
971      names such as this one. See en_US.po for reference. */
972   if (fputs (_("\nOriginally written by Hrvoje Niksic <hniksic@xemacs.org>.\n"),
973              stdout) < 0)
974     exit (3);
975   if (fputs (_("Please send bug reports and questions to <bug-wget@gnu.org>.\n"),
976              stdout) < 0)
977     exit (3);
978
979   exit (0);
980 }
981
982 char *program_name; /* Needed by lib/error.c. */
983 char *program_argstring; /* Needed by wget_warc.c. */
984
985 int
986 main (int argc, char **argv)
987 {
988   char **url, **t;
989   int i, ret, longindex;
990   int nurl;
991   bool append_to_log = false;
992
993   total_downloaded_bytes = 0;
994
995   program_name = argv[0];
996
997   struct ptimer *timer = ptimer_new ();
998   double start_time = ptimer_measure (timer);
999
1000   i18n_initialize ();
1001
1002   /* Construct the name of the executable, without the directory part.  */
1003 #ifdef __VMS
1004   /* On VMS, lose the "dev:[dir]" prefix and the ".EXE;nnn" suffix. */
1005   exec_name = vms_basename (argv[0]);
1006 #else /* def __VMS */
1007   exec_name = strrchr (argv[0], PATH_SEPARATOR);
1008   if (!exec_name)
1009     exec_name = argv[0];
1010   else
1011     ++exec_name;
1012 #endif /* def __VMS [else] */
1013
1014 #ifdef WINDOWS
1015   /* Drop extension (typically .EXE) from executable filename. */
1016   windows_main ((char **) &exec_name);
1017 #endif
1018
1019   /* Construct the arguments string. */
1020   int argstring_length = 1;
1021   for (i = 1; i < argc; i++)
1022     argstring_length += strlen (argv[i]) + 2 + 1;
1023   char *p = program_argstring = malloc (argstring_length * sizeof (char));
1024   if (p == NULL)
1025     {
1026       fprintf (stderr, _("Memory allocation problem\n"));
1027       exit (2);
1028     }
1029   for (i = 1; i < argc; i++)
1030     {
1031       *p++ = '"';
1032       int arglen = strlen (argv[i]);
1033       memcpy (p, argv[i], arglen);
1034       p += arglen;
1035       *p++ = '"';
1036       *p++ = ' ';
1037     }
1038   *p = '\0';
1039
1040   /* Load the hard-coded defaults.  */
1041   defaults ();
1042
1043   init_switches ();
1044
1045   /* This separate getopt_long is needed to find the user config file
1046      option ("--config") and parse it before the other user options. */
1047   longindex = -1;
1048   int retconf;
1049   bool use_userconfig = false;
1050   bool noconfig = false;
1051
1052   while ((retconf = getopt_long (argc, argv,
1053                                 short_options, long_options, &longindex)) != -1)
1054     {
1055       int confval;
1056       struct cmdline_option *config_opt;
1057
1058       /* There is no short option for "--config". */
1059       if (longindex >= 0)
1060         {
1061           confval = long_options[longindex].val;
1062           config_opt = &option_data[confval & ~BOOLEAN_NEG_MARKER];
1063           if (strcmp (config_opt->long_name, "no-config") == 0)
1064             {
1065               noconfig = true;
1066               break;
1067             }
1068           else if (strcmp (config_opt->long_name, "config") == 0)
1069             {
1070               bool userrc_ret = true;
1071               userrc_ret &= run_wgetrc (optarg);
1072               use_userconfig = true;
1073               if (userrc_ret)
1074                 break;
1075               else
1076                 {
1077                   fprintf (stderr, _("Exiting due to error in %s\n"), optarg);
1078                   exit (2);
1079                 }
1080             }
1081         }
1082     }
1083
1084   /* If the user did not specify a config, read the system wgetrc and ~/.wgetrc. */
1085   if (noconfig == false && use_userconfig == false)
1086     initialize ();
1087
1088   opterr = 0;
1089   optind = 0;
1090
1091   longindex = -1;
1092   while ((ret = getopt_long (argc, argv,
1093                              short_options, long_options, &longindex)) != -1)
1094     {
1095       int val;
1096       struct cmdline_option *opt;
1097
1098       /* If LONGINDEX is unchanged, it means RET is referring a short
1099          option.  */
1100       if (longindex == -1)
1101         {
1102           if (ret == '?')
1103             {
1104               print_usage (1);
1105               fprintf (stderr, "\n");
1106               fprintf (stderr, _("Try `%s --help' for more options.\n"),
1107                        exec_name);
1108               exit (2);
1109             }
1110           /* Find the short option character in the mapping.  */
1111           longindex = optmap[ret - 32];
1112         }
1113       val = long_options[longindex].val;
1114
1115       /* Use the retrieved value to locate the option in the
1116          option_data array, and to see if we're dealing with the
1117          negated "--no-FOO" variant of the boolean option "--foo".  */
1118       opt = &option_data[val & ~BOOLEAN_NEG_MARKER];
1119       switch (opt->type)
1120         {
1121         case OPT_VALUE:
1122           setoptval (opt->data, optarg, opt->long_name);
1123           break;
1124         case OPT_BOOLEAN:
1125           if (optarg)
1126             /* The user has specified a value -- use it. */
1127             setoptval (opt->data, optarg, opt->long_name);
1128           else
1129             {
1130               /* NEG is true for `--no-FOO' style boolean options. */
1131               bool neg = !!(val & BOOLEAN_NEG_MARKER);
1132               setoptval (opt->data, neg ? "0" : "1", opt->long_name);
1133             }
1134           break;
1135         case OPT_FUNCALL:
1136           {
1137             void (*func) (void) = (void (*) (void)) opt->data;
1138             func ();
1139           }
1140           break;
1141         case OPT__APPEND_OUTPUT:
1142           setoptval ("logfile", optarg, opt->long_name);
1143           append_to_log = true;
1144           break;
1145         case OPT__EXECUTE:
1146           run_command (optarg);
1147           break;
1148         case OPT__NO:
1149           {
1150             /* We support real --no-FOO flags now, but keep these
1151                short options for convenience and backward
1152                compatibility.  */
1153             char *p;
1154             for (p = optarg; p && *p; p++)
1155               switch (*p)
1156                 {
1157                 case 'v':
1158                   setoptval ("verbose", "0", opt->long_name);
1159                   break;
1160                 case 'H':
1161                   setoptval ("addhostdir", "0", opt->long_name);
1162                   break;
1163                 case 'd':
1164                   setoptval ("dirstruct", "0", opt->long_name);
1165                   break;
1166                 case 'c':
1167                   setoptval ("noclobber", "1", opt->long_name);
1168                   break;
1169                 case 'p':
1170                   setoptval ("noparent", "1", opt->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 (opt->type == OPT__PARENT ? "noparent" : "noclobber",
1195                        flag ? "0" : "1", opt->long_name);
1196             break;
1197           }
1198         case OPT__DONT_REMOVE_LISTING:
1199           setoptval ("removelisting", "0", opt->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),
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));
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  */