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