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