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