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