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