]> sjero.net Git - wget/blob - src/main.c
[svn] Added reordering of addresses to try IPv4 first and the associated
[wget] / src / main.c
1 /* Command line parsing.
2    Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include <config.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif /* HAVE_UNISTD_H */
37 #include <sys/types.h>
38 #ifdef HAVE_STRING_H
39 # include <string.h>
40 #else
41 # include <strings.h>
42 #endif /* HAVE_STRING_H */
43 #ifdef HAVE_SIGNAL_H
44 # include <signal.h>
45 #endif
46 #ifdef HAVE_NLS
47 #ifdef HAVE_LOCALE_H
48 # include <locale.h>
49 #endif /* HAVE_LOCALE_H */
50 #endif /* HAVE_NLS */
51 #include <assert.h>
52
53 #include <errno.h>
54 #ifndef errno
55 extern int errno;
56 #endif
57
58 #include "wget.h"
59 #include "utils.h"
60 #include "init.h"
61 #include "retr.h"
62 #include "recur.h"
63 #include "host.h"
64 #include "url.h"
65 #include "progress.h"           /* for progress_handle_sigwinch */
66 #include "convert.h"
67
68 /* On GNU system this will include system-wide getopt.h. */
69 #include "getopt.h"
70
71 #ifndef PATH_SEPARATOR
72 # define PATH_SEPARATOR '/'
73 #endif
74
75 struct options opt;
76
77 extern LARGE_INT total_downloaded_bytes;
78 extern char *version_string;
79
80 extern struct cookie_jar *wget_cookie_jar;
81
82 static RETSIGTYPE redirect_output_signal PARAMS ((int));
83
84 const char *exec_name;
85 \f
86 /* Initialize I18N.  The initialization amounts to invoking
87    setlocale(), bindtextdomain() and textdomain().
88    Does nothing if NLS is disabled or missing.  */
89 static void
90 i18n_initialize (void)
91 {
92   /* If HAVE_NLS is defined, assume the existence of the three
93      functions invoked here.  */
94 #ifdef HAVE_NLS
95   /* Set the current locale.  */
96   /* Here we use LC_MESSAGES instead of LC_ALL, for two reasons.
97      First, message catalogs are all of I18N Wget uses anyway.
98      Second, setting LC_ALL has a dangerous potential of messing
99      things up.  For example, when in a foreign locale, Solaris
100      strptime() fails to handle international dates correctly, which
101      makes http_atotm() malfunction.  */
102 #ifdef LC_MESSAGES
103   setlocale (LC_MESSAGES, "");
104   setlocale (LC_CTYPE, "");
105 #else
106   setlocale (LC_ALL, "");
107 #endif
108   /* Set the text message domain.  */
109   bindtextdomain ("wget", LOCALEDIR);
110   textdomain ("wget");
111 #endif /* HAVE_NLS */
112 }
113 \f
114 /* Definition of command-line options. */
115
116 static void print_help PARAMS ((void));
117 static void print_version PARAMS ((void));
118
119 #ifdef HAVE_SSL
120 # define IF_SSL(x) x
121 #else
122 # define IF_SSL(x) NULL
123 #endif
124
125 #ifdef ENABLE_DEBUG
126 # define IF_DEBUG(x) x
127 #else
128 # define IF_DEBUG(x) NULL
129 #endif
130
131 struct cmdline_option {
132   const char *long_name;
133   char short_name;
134   enum {
135     OPT_VALUE,
136     OPT_BOOLEAN,
137     OPT_FUNCALL,
138     /* Non-standard options that have to be handled specially in
139        main().  */
140     OPT__APPEND_OUTPUT,
141     OPT__CLOBBER,
142     OPT__DONT_REMOVE_LISTING,
143     OPT__EXECUTE,
144     OPT__NO,
145     OPT__PARENT,
146   } type;
147   const void *data;             /* for standard options */
148   int argtype;                  /* for non-standard options */
149 };
150
151 struct cmdline_option option_data[] =
152   {
153     { "accept", 'A', OPT_VALUE, "accept", -1 },
154     { "append-output", 'a', OPT__APPEND_OUTPUT, NULL, required_argument },
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     { "cache", 0, OPT_BOOLEAN, "cache", -1 },
161     { "clobber", 0, OPT__CLOBBER, NULL, optional_argument },
162     { "connect-timeout", 0, OPT_VALUE, "connecttimeout", -1 },
163     { "continue", 'c', OPT_BOOLEAN, "continue", -1 },
164     { "convert-links", 'k', OPT_BOOLEAN, "convertlinks", -1 },
165     { "cookies", 0, OPT_BOOLEAN, "cookies", -1 },
166     { "cut-dirs", 0, OPT_VALUE, "cutdirs", -1 },
167     { IF_DEBUG ("debug"), 'd', OPT_BOOLEAN, "debug", -1 },
168     { "delete-after", 0, OPT_BOOLEAN, "deleteafter", -1 },
169     { "directories", 0, OPT_BOOLEAN, "dirstruct", -1 },
170     { "directory-prefix", 'P', OPT_VALUE, "dirprefix", -1 },
171     { "dns-cache", 0, OPT_BOOLEAN, "dnscache", -1 },
172     { "dns-timeout", 0, OPT_VALUE, "dnstimeout", -1 },
173     { "domains", 'D', OPT_VALUE, "domains", -1 },
174     { "dont-remove-listing", 0, OPT__DONT_REMOVE_LISTING, NULL, no_argument },
175     { "dot-style", 0, OPT_VALUE, "dotstyle", -1 },
176     { "egd-file", 0, OPT_VALUE, "egdfile", -1 },
177     { "exclude-directories", 'X', OPT_VALUE, "excludedirectories", -1 },
178     { "exclude-domains", 0, OPT_VALUE, "excludedomains", -1 },
179     { "execute", 'e', OPT__EXECUTE, NULL, required_argument },
180     { "follow-ftp", 0, OPT_BOOLEAN, "followftp", -1 },
181     { "follow-tags", 0, OPT_VALUE, "followtags", -1 },
182     { "force-directories", 'x', OPT_BOOLEAN, "dirstruct", -1 },
183     { "force-html", 'F', OPT_BOOLEAN, "forcehtml", -1 },
184     { "ftp-passwd", 0, OPT_VALUE, "ftppasswd", -1 },
185     { "glob", 0, OPT_BOOLEAN, "glob", -1 },
186     { "header", 0, OPT_VALUE, "header", -1 },
187     { "help", 'h', OPT_FUNCALL, (void *)print_help, no_argument },
188     { "host-directories", 0, OPT_BOOLEAN, "addhostdir", -1 },
189     { "html-extension", 'E', OPT_BOOLEAN, "htmlextension", -1 },
190     { "htmlify", 0, OPT_BOOLEAN, "htmlify", -1 },
191     { "http-keep-alive", 0, OPT_BOOLEAN, "httpkeepalive", -1 },
192     { "http-passwd", 0, OPT_VALUE, "httppasswd", -1 },
193     { "http-user", 0, OPT_VALUE, "httpuser", -1 },
194     { "ignore-length", 0, OPT_BOOLEAN, "ignorelength", -1 },
195     { "ignore-tags", 0, OPT_VALUE, "ignoretags", -1 },
196     { "include-directories", 'I', OPT_VALUE, "includedirectories", -1 },
197 #ifdef ENABLE_IPV6
198     { "inet4-only", '4', OPT_BOOLEAN, "inet4only", -1 },
199     { "inet6-only", '6', OPT_BOOLEAN, "inet6only", -1 },
200 #endif
201     { "input-file", 'i', OPT_VALUE, "input", -1 },
202     { "keep-session-cookies", 0, OPT_BOOLEAN, "keepsessioncookies", -1 },
203     { "level", 'l', OPT_VALUE, "reclevel", -1 },
204     { "limit-rate", 0, OPT_VALUE, "limitrate", -1 },
205     { "load-cookies", 0, OPT_VALUE, "loadcookies", -1 },
206     { "mirror", 'm', OPT_BOOLEAN, "mirror", -1 },
207     { "no", 'n', OPT__NO, NULL, required_argument },
208     { "no-clobber", 0, OPT_BOOLEAN, "noclobber", -1 },
209     { "no-parent", 0, OPT_BOOLEAN, "noparent", -1 },
210     { "output-document", 'O', OPT_VALUE, "outputdocument", -1 },
211     { "output-file", 'o', OPT_VALUE, "logfile", -1 },
212     { "page-requisites", 'p', OPT_BOOLEAN, "pagerequisites", -1 },
213     { "parent", 0, OPT__PARENT, NULL, optional_argument },
214     { "passive-ftp", 0, OPT_BOOLEAN, "passiveftp", -1 },
215     { "post-data", 0, OPT_VALUE, "postdata", -1 },
216     { "post-file", 0, OPT_VALUE, "postfile", -1 },
217     { "prefer-family", 0, OPT_VALUE, "preferfamily", -1 },
218     { "preserve-permissions", 0, OPT_BOOLEAN, "preservepermissions", -1 },
219     { "progress", 0, OPT_VALUE, "progress", -1 },
220     { "protocol-directories", 0, OPT_BOOLEAN, "protocoldirectories", -1 },
221     { "proxy", 'Y', OPT_BOOLEAN, "useproxy", -1 },
222     { "proxy-passwd", 0, OPT_VALUE, "proxypasswd", -1 },
223     { "proxy-user", 0, OPT_VALUE, "proxyuser", -1 },
224     { "quiet", 'q', OPT_BOOLEAN, "quiet", -1 },
225     { "quota", 'Q', OPT_VALUE, "quota", -1 },
226     { "random-wait", 0, OPT_BOOLEAN, "randomwait", -1 },
227     { "read-timeout", 0, OPT_VALUE, "readtimeout", -1 },
228     { "recursive", 'r', OPT_BOOLEAN, "recursive", -1 },
229     { "referer", 0, OPT_VALUE, "referer", -1 },
230     { "reject", 'R', OPT_VALUE, "reject", -1 },
231     { "relative", 'L', OPT_BOOLEAN, "relativeonly", -1 },
232     { "remove-listing", 0, OPT_BOOLEAN, "removelisting", -1 },
233     { "restrict-file-names", 0, OPT_BOOLEAN, "restrictfilenames", -1 },
234     { "retr-symlinks", 0, OPT_BOOLEAN, "retrsymlinks", -1 },
235     { "retry-connrefused", 0, OPT_BOOLEAN, "retryconnrefused", -1 },
236     { "save-cookies", 0, OPT_VALUE, "savecookies", -1 },
237     { "save-headers", 0, OPT_BOOLEAN, "saveheaders", -1 },
238     { "server-response", 'S', OPT_BOOLEAN, "serverresponse", -1 },
239     { "span-hosts", 'H', OPT_BOOLEAN, "spanhosts", -1 },
240     { "spider", 0, OPT_BOOLEAN, "spider", -1 },
241     { IF_SSL ("sslcadir"), 0, OPT_VALUE, "sslcadir", -1 },
242     { IF_SSL ("sslcafile"), 0, OPT_VALUE, "sslcafile", -1 },
243     { IF_SSL ("sslcertfile"), 0, OPT_VALUE, "sslcertfile", -1 },
244     { IF_SSL ("sslcertkey"), 0, OPT_VALUE, "sslcertkey", -1 },
245     { IF_SSL ("sslcerttype"), 0, OPT_VALUE, "sslcerttype", -1 },
246     { IF_SSL ("sslcheckcert"), 0, OPT_VALUE, "sslcheckcert", -1 },
247     { IF_SSL ("sslprotocol"), 0, OPT_VALUE, "sslprotocol", -1 },
248     { "strict-comments", 0, OPT_BOOLEAN, "strictcomments", -1 },
249     { "timeout", 'T', OPT_VALUE, "timeout", -1 },
250     { "timestamping", 'N', OPT_BOOLEAN, "timestamping", -1 },
251     { "tries", 't', OPT_VALUE, "tries", -1 },
252     { "use-proxy", 'Y', OPT_BOOLEAN, "useproxy", -1 },
253     { "user-agent", 'U', OPT_VALUE, "useragent", -1 },
254     { "verbose", 'v', OPT_BOOLEAN, "verbose", -1 },
255     { "verbose", 0, OPT_BOOLEAN, "verbose", -1 },
256     { "version", 'V', OPT_FUNCALL, (void *) print_version, no_argument },
257     { "wait", 'w', OPT_VALUE, "wait", -1 },
258     { "waitretry", 0, OPT_VALUE, "waitretry", -1 },
259   };
260
261 #undef IF_DEBUG
262 #undef IF_SSL
263
264 /* Return a string that contains S with "no-" prepended.  The string
265    is NUL-terminated and allocated off static storage at Wget
266    startup.  */
267
268 static char *
269 no_prefix (const char *s)
270 {
271   static char buffer[1024];
272   static char *p = buffer;
273
274   char *cp = p;
275   int size = 3 + strlen (s) + 1;  /* "no-STRING\0" */
276   if (p + size >= buffer + sizeof (buffer))
277     abort ();
278
279   cp[0] = 'n', cp[1] = 'o', cp[2] = '-';
280   strcpy (cp + 3, s);
281   p += size;
282   return cp;
283 }
284
285 /* The arguments that that main passes to getopt_long. */
286 static struct option long_options[2 * countof (option_data) + 1];
287 static char short_options[128];
288
289 /* Mapping between short option chars and option_data indices. */
290 static unsigned char optmap[96];
291
292 /* Marker for `--no-FOO' values in long_options.  */
293 #define BOOLEAN_NEG_MARKER 1024
294
295 /* Initialize the long_options array used by getopt_long from the data
296    in option_data.  */
297
298 static void
299 init_switches (void)
300 {
301   char *p = short_options;
302   int i, o = 0;
303   for (i = 0; i < countof (option_data); i++)
304     {
305       struct cmdline_option *opt = &option_data[i];
306       struct option *longopt;
307
308       if (!opt->long_name)
309         /* The option is disabled. */
310         continue;
311
312       longopt = &long_options[o++];
313       longopt->name = opt->long_name;
314       longopt->val = i;
315       if (opt->short_name)
316         {
317           *p++ = opt->short_name;
318           optmap[opt->short_name - 32] = longopt - long_options;
319         }
320       switch (opt->type)
321         {
322         case OPT_VALUE:
323           longopt->has_arg = required_argument;
324           if (opt->short_name)
325             *p++ = ':';
326           break;
327         case OPT_BOOLEAN:
328           /* Don't specify optional arguments for boolean short
329              options.  They are evil because they prevent combining of
330              short options.  */
331           longopt->has_arg = optional_argument;
332           /* For Boolean options, add the "--no-FOO" variant, which is
333              identical to "--foo", except it has opposite meaning and
334              it doesn't allow an argument.  */
335           longopt = &long_options[o++];
336           longopt->name = no_prefix (opt->long_name);
337           longopt->has_arg = no_argument;
338           /* Mask the value so we'll be able to recognize that we're
339              dealing with the false value.  */
340           longopt->val = i | BOOLEAN_NEG_MARKER;
341           break;
342         default:
343           assert (opt->argtype != -1);
344           longopt->has_arg = opt->argtype;
345           if (opt->short_name)
346             {
347               if (longopt->has_arg == required_argument)
348                 *p++ = ':';
349               /* Don't handle optional_argument */
350             }
351         }
352     }
353   /* Terminate short_options. */
354   *p = '\0';
355   /* No need for xzero(long_options[o]) because its storage is static
356      and it will be zeroed by default.  */
357   assert (o <= countof (long_options));
358 }
359
360 /* Print the usage message.  */
361 static void
362 print_usage (void)
363 {
364   printf (_("Usage: %s [OPTION]... [URL]...\n"), exec_name);
365 }
366
367 /* Print the help message, describing all the available options.  If
368    you add an option, be sure to update this list.  */
369 static void
370 print_help (void)
371 {
372   /* We split the help text this way to ease translation of individual
373      entries.  */
374   static const char *help[] = {
375     "\n",
376     N_("\
377 Mandatory arguments to long options are mandatory for short options too.\n\n"),
378     N_("\
379 Startup:\n"),
380     N_("\
381   -V,  --version           display the version of Wget and exit.\n"),
382     N_("\
383   -h,  --help              print this help.\n"),
384     N_("\
385   -b,  --background        go to background after startup.\n"),
386     N_("\
387   -e,  --execute=COMMAND   execute a `.wgetrc'-style command.\n"),
388     "\n",
389
390     N_("\
391 Logging and input file:\n"),
392     N_("\
393   -o,  --output-file=FILE    log messages to FILE.\n"),
394     N_("\
395   -a,  --append-output=FILE  append messages to FILE.\n"),
396 #ifdef ENABLE_DEBUG
397     N_("\
398   -d,  --debug               print lots of debugging information.\n"),
399 #endif
400     N_("\
401   -q,  --quiet               quiet (no output).\n"),
402     N_("\
403   -v,  --verbose             be verbose (this is the default).\n"),
404     N_("\
405   -nv, --no-verbose          turn off verboseness, without being quiet.\n"),
406     N_("\
407   -i,  --input-file=FILE     download URLs found in FILE.\n"),
408     N_("\
409   -F,  --force-html          treat input file as HTML.\n"),
410     N_("\
411   -B,  --base=URL            prepends URL to relative links in -F -i file.\n"),
412     "\n",
413
414     N_("\
415 Download:\n"),
416     N_("\
417   -t,  --tries=NUMBER            set number of retries to NUMBER (0 unlimits).\n"),
418     N_("\
419        --retry-connrefused       retry even if connection is refused.\n"),
420     N_("\
421   -O,  --output-document=FILE    write documents to FILE.\n"),
422     N_("\
423   -nc, --no-clobber              skip downloads that would download to\n\
424                                  existing files.\n"),
425     N_("\
426   -c,  --continue                resume getting a partially-downloaded file.\n"),
427     N_("\
428        --progress=TYPE           select progress gauge type.\n"),
429     N_("\
430   -N,  --timestamping            don't re-retrieve files unless newer than\n\
431                                  local.\n"),
432     N_("\
433   -S,  --server-response         print server response.\n"),
434     N_("\
435        --spider                  don't download anything.\n"),
436     N_("\
437   -T,  --timeout=SECONDS         set all timeout values to SECONDS.\n"),
438     N_("\
439        --dns-timeout=SECS        set the DNS lookup timeout to SECS.\n"),
440     N_("\
441        --connect-timeout=SECS    set the connect timeout to SECS.\n"),
442     N_("\
443        --read-timeout=SECS       set the read timeout to SECS.\n"),
444     N_("\
445   -w,  --wait=SECONDS            wait SECONDS between retrievals.\n"),
446     N_("\
447        --waitretry=SECONDS       wait 1..SECONDS between retries of a retrieval.\n"),
448     N_("\
449        --random-wait             wait from 0...2*WAIT secs between retrievals.\n"),
450     N_("\
451   -Y,  --proxy                   explicitly turn on proxy.\n"),
452     N_("\
453        --no-proxy                explicitly turn off proxy.\n"),
454     N_("\
455   -Q,  --quota=NUMBER            set retrieval quota to NUMBER.\n"),
456     N_("\
457        --bind-address=ADDRESS    bind to ADDRESS (hostname or IP) on local host.\n"),
458     N_("\
459        --limit-rate=RATE         limit download rate to RATE.\n"),
460     N_("\
461        --no-dns-cache            disable caching DNS lookups.\n"),
462     N_("\
463        --restrict-file-names=OS  restrict chars in file names to ones OS allows.\n"),
464 #ifdef ENABLE_IPV6
465     N_("\
466   -4,  --inet4-only              connect only to IPv4 addresses.\n"),
467     N_("\
468   -6,  --inet6-only              connect only to IPv6 addresses.\n"),
469     N_("\
470        --prefer-family=FAMILY    connect first to addresses of specified family,\n\
471                                  one of IPv6, IPv4, or none.\n"),
472 #endif
473     "\n",
474
475     N_("\
476 Directories:\n"),
477     N_("\
478   -nd, --no-directories           don't create directories.\n"),
479     N_("\
480   -x,  --force-directories        force creation of directories.\n"),
481     N_("\
482   -nH, --no-host-directories      don't create host directories.\n"),
483     N_("\
484        --protocol-directories     use protocol name in directories.\n"),
485     N_("\
486   -P,  --directory-prefix=PREFIX  save files to PREFIX/...\n"),
487     N_("\
488        --cut-dirs=NUMBER          ignore NUMBER remote directory components.\n"),
489     "\n",
490
491     N_("\
492 HTTP options:\n"),
493     N_("\
494        --http-user=USER        set http user to USER.\n"),
495     N_("\
496        --http-passwd=PASS      set http password to PASS.\n"),
497     N_("\
498        --no-cache              disallow server-cached data.\n"),
499     N_("\
500   -E,  --html-extension        save HTML documents with `.html' extension.\n"),
501     N_("\
502        --ignore-length         ignore `Content-Length' header field.\n"),
503     N_("\
504        --header=STRING         insert STRING among the headers.\n"),
505     N_("\
506        --proxy-user=USER       set USER as proxy username.\n"),
507     N_("\
508        --proxy-passwd=PASS     set PASS as proxy password.\n"),
509     N_("\
510        --referer=URL           include `Referer: URL' header in HTTP request.\n"),
511     N_("\
512        --save-headers          save the HTTP headers to file.\n"),
513     N_("\
514   -U,  --user-agent=AGENT      identify as AGENT instead of Wget/VERSION.\n"),
515     N_("\
516        --no-http-keep-alive    disable HTTP keep-alive (persistent connections).\n"),
517     N_("\
518        --no-cookies            don't use cookies.\n"),
519     N_("\
520        --load-cookies=FILE     load cookies from FILE before session.\n"),
521     N_("\
522        --save-cookies=FILE     save cookies to FILE after session.\n"),
523     N_("\
524        --keep-session-cookies  load and save session (non-permanent) cookies.\n"),
525     N_("\
526        --post-data=STRING      use the POST method; send STRING as the data.\n"),
527     N_("\
528        --post-file=FILE        use the POST method; send contents of FILE.\n"),
529     "\n",
530
531 #ifdef HAVE_SSL
532     N_("\
533 HTTPS (SSL) options:\n"),
534     N_("\
535        --sslcertfile=FILE    optional client certificate.\n"),
536     N_("\
537        --sslcertkey=KEYFILE  optional keyfile for this certificate.\n"),
538     N_("\
539        --sslcadir=DIR        dir where hash list of CA's are stored.\n"),
540     N_("\
541        --sslcafile=FILE      file with bundle of CA's.\n"),
542     N_("\
543        --sslcerttype=0/1     Client-Cert type 0=PEM (default) / 1=ASN1 (DER).\n"),
544     N_("\
545        --sslcheckcert=0/1    Check the server cert against given CA.\n"),
546     N_("\
547        --sslprotocol=0-3     choose SSL protocol; 0=automatic,\n\
548                              1=SSLv2 2=SSLv3 3=TLSv1.\n"),
549     N_("\
550        --egd-file=FILE       file name of the EGD socket.\n"),
551     "\n",
552 #endif /* HAVE_SSL */
553
554     N_("\
555 FTP options:\n"),
556     N_("\
557        --no-remove-listing     don't remove `.listing' files.\n"),
558     N_("\
559        --no-glob               turn off FTP file name globbing.\n"),
560     N_("\
561        --no-passive-ftp        disable the \"passive\" transfer mode.\n"),
562     N_("\
563        --retr-symlinks         when recursing, get linked-to files (not dir).\n"),
564     N_("\
565        --preserve-permissions  preserve remote file permissions.\n"),
566     "\n",
567
568     N_("\
569 Recursive download:\n"),
570     N_("\
571   -r,  --recursive          specify recursive download.\n"),
572     N_("\
573   -l,  --level=NUMBER       maximum recursion depth (inf or 0 for infinite).\n"),
574     N_("\
575        --delete-after       delete files locally after downloading them.\n"),
576     N_("\
577   -k,  --convert-links      make links in downloaded HTML point to local files.\n"),
578     N_("\
579   -K,  --backup-converted   before converting file X, back up as X.orig.\n"),
580     N_("\
581   -m,  --mirror             shortcut option equivalent to -r -N -l inf -nr.\n"),
582     N_("\
583   -p,  --page-requisites    get all images, etc. needed to display HTML page.\n"),
584     N_("\
585        --strict-comments    turn on strict (SGML) handling of HTML comments.\n"),
586     "\n",
587
588     N_("\
589 Recursive accept/reject:\n"),
590     N_("\
591   -A,  --accept=LIST               comma-separated list of accepted extensions.\n"),
592     N_("\
593   -R,  --reject=LIST               comma-separated list of rejected extensions.\n"),
594     N_("\
595   -D,  --domains=LIST              comma-separated list of accepted domains.\n"),
596     N_("\
597        --exclude-domains=LIST      comma-separated list of rejected domains.\n"),
598     N_("\
599        --follow-ftp                follow FTP links from HTML documents.\n"),
600     N_("\
601        --follow-tags=LIST          comma-separated list of followed HTML tags.\n"),
602     N_("\
603        --ignore-tags=LIST          comma-separated list of ignored HTML tags.\n"),
604     N_("\
605   -H,  --span-hosts                go to foreign hosts when recursive.\n"),
606     N_("\
607   -L,  --relative                  follow relative links only.\n"),
608     N_("\
609   -I,  --include-directories=LIST  list of allowed directories.\n"),
610     N_("\
611   -X,  --exclude-directories=LIST  list of excluded directories.\n"),
612     N_("\
613   -np, --no-parent                 don't ascend to the parent directory.\n"),
614     "\n",
615
616     N_("Mail bug reports and suggestions to <bug-wget@gnu.org>.\n")
617   };
618
619   int i;
620
621   printf (_("GNU Wget %s, a non-interactive network retriever.\n"),
622           version_string);
623   print_usage ();
624
625   for (i = 0; i < countof (help); i++)
626     fputs (_(help[i]), stdout);
627
628   exit (0);
629 }
630
631 static void
632 print_version (void)
633 {
634   printf ("GNU Wget %s\n\n", version_string);
635   fputs (_("\
636 Copyright (C) 2005 Free Software Foundation, Inc.\n"), stdout);
637   fputs (_("\
638 This program is distributed in the hope that it will be useful,\n\
639 but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
640 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
641 GNU General Public License for more details.\n"), stdout);
642   fputs (_("\nOriginally written by Hrvoje Niksic <hniksic@xemacs.org>.\n"),
643          stdout);
644   exit (0);
645 }
646 \f
647 int
648 main (int argc, char *const *argv)
649 {
650   char **url, **t;
651   int i, ret, longindex;
652   int nurl, status;
653   int append_to_log = 0;
654
655   i18n_initialize ();
656
657   /* Construct the name of the executable, without the directory part.  */
658   exec_name = strrchr (argv[0], PATH_SEPARATOR);
659   if (!exec_name)
660     exec_name = argv[0];
661   else
662     ++exec_name;
663
664 #ifdef WINDOWS
665   /* Drop extension (typically .EXE) from executable filename. */
666   windows_main (&argc, (char **) argv, (char **) &exec_name);
667 #endif
668
669   /* Set option defaults; read the system wgetrc and ~/.wgetrc.  */
670   initialize ();
671
672   init_switches ();
673   longindex = -1;
674   while ((ret = getopt_long (argc, argv,
675                              short_options, long_options, &longindex)) != -1)
676     {
677       int val;
678       struct cmdline_option *opt;
679
680       /* If LONGINDEX is unchanged, it means RET is referring a short
681          option.  */
682       if (longindex == -1)
683         {
684           if (ret == '?')
685             {
686               print_usage ();
687               printf ("\n");
688               printf (_("Try `%s --help' for more options.\n"), exec_name);
689               exit (2);
690             }
691           /* Find the short option character in the mapping.  */
692           longindex = optmap[ret - 32];
693         }
694       val = long_options[longindex].val;
695
696       /* Use the retrieved value to locate the option in the
697          option_data array, and to see if we're dealing with the
698          negated "--no-FOO" variant of the boolean option "--foo".  */
699       opt = &option_data[val & ~BOOLEAN_NEG_MARKER];
700       switch (opt->type)
701         {
702         case OPT_VALUE:
703           setoptval (opt->data, optarg);
704           break;
705         case OPT_BOOLEAN:
706           if (optarg)
707             /* The user has specified a value -- use it. */
708             setoptval (opt->data, optarg);
709           else
710             {
711               /* NEG is true for `--no-FOO' style boolean options. */
712               int neg = val & BOOLEAN_NEG_MARKER;
713               setoptval (opt->data, neg ? "0" : "1");
714             }
715           break;
716         case OPT_FUNCALL:
717           {
718             void (*func) PARAMS ((void)) = (void (*) PARAMS ((void))) opt->data;
719             func ();
720           }
721           break;
722         case OPT__APPEND_OUTPUT:
723           setoptval ("logfile", optarg);
724           append_to_log = 1;
725           break;
726         case OPT__EXECUTE:
727           run_command (optarg);
728           break;
729         case OPT__NO:
730           {
731             /* We support real --no-FOO flags now, but keep these
732                short options for convenience and backward
733                compatibility.  */
734             char *p;
735             for (p = optarg; *p; p++)
736               switch (*p)
737                 {
738                 case 'v':
739                   setoptval ("verbose", "0");
740                   break;
741                 case 'H':
742                   setoptval ("addhostdir", "0");
743                   break;
744                 case 'd':
745                   setoptval ("dirstruct", "0");
746                   break;
747                 case 'c':
748                   setoptval ("noclobber", "1");
749                   break;
750                 case 'p':
751                   setoptval ("noparent", "1");
752                   break;
753                 default:
754                   printf (_("%s: illegal option -- `-n%c'\n"), exec_name, *p);
755                   print_usage ();
756                   printf ("\n");
757                   printf (_("Try `%s --help' for more options.\n"), exec_name);
758                   exit (1);
759                 }
760             break;
761           }
762         case OPT__PARENT:
763         case OPT__CLOBBER:
764           {
765             /* The wgetrc commands are named noparent and noclobber,
766                so we must revert the meaning of the cmdline options
767                before passing the value to setoptval.  */
768             int flag = 1;
769             if (optarg)
770               flag = (*optarg == '1' || TOLOWER (*optarg) == 'y'
771                       || (TOLOWER (optarg[0]) == 'o'
772                           && TOLOWER (optarg[1]) == 'n'));
773             setoptval (opt->type == OPT__PARENT ? "noparent" : "noclobber",
774                        flag ? "0" : "1");
775             break;
776           }
777         case OPT__DONT_REMOVE_LISTING:
778           setoptval ("removelisting", "0");
779           break;
780         }
781
782       longindex = -1;
783     }
784
785   /* All user options have now been processed, so it's now safe to do
786      interoption dependency checks. */
787
788   if (opt.reclevel == 0)
789     opt.reclevel = INFINITE_RECURSION;  /* see wget.h for commentary on this */
790
791   if (opt.page_requisites && !opt.recursive)
792     {
793       /* Don't set opt.recursive here because it would confuse the FTP
794          code.  Instead, call retrieve_tree below when either
795          page_requisites or recursive is requested.  */
796       opt.reclevel = 0;
797       if (!opt.no_dirstruct)
798         opt.dirstruct = 1;      /* normally handled by cmd_spec_recursive() */
799     }
800
801   if (opt.verbose == -1)
802     opt.verbose = !opt.quiet;
803
804   /* Sanity checks.  */
805   if (opt.verbose && opt.quiet)
806     {
807       printf (_("Can't be verbose and quiet at the same time.\n"));
808       print_usage ();
809       exit (1);
810     }
811   if (opt.timestamping && opt.noclobber)
812     {
813       printf (_("\
814 Can't timestamp and not clobber old files at the same time.\n"));
815       print_usage ();
816       exit (1);
817     }
818 #ifdef ENABLE_IPV6
819   if (opt.ipv4_only && opt.ipv6_only)
820     {
821       printf (_("Cannot specify both --inet4-only and --inet6-only.\n"));
822       print_usage ();
823       exit (1);
824     }
825 #endif
826
827   nurl = argc - optind;
828   if (!nurl && !opt.input_filename)
829     {
830       /* No URL specified.  */
831       printf (_("%s: missing URL\n"), exec_name);
832       print_usage ();
833       printf ("\n");
834       /* #### Something nicer should be printed here -- similar to the
835          pre-1.5 `--help' page.  */
836       printf (_("Try `%s --help' for more options.\n"), exec_name);
837       exit (1);
838     }
839
840   if (opt.background)
841     fork_to_background ();
842
843   /* Initialize progress.  Have to do this after the options are
844      processed so we know where the log file is.  */
845   if (opt.verbose)
846     set_progress_implementation (opt.progress_type);
847
848   /* Fill in the arguments.  */
849   url = alloca_array (char *, nurl + 1);
850   for (i = 0; i < nurl; i++, optind++)
851     {
852       char *rewritten = rewrite_shorthand_url (argv[optind]);
853       if (rewritten)
854         url[i] = rewritten;
855       else
856         url[i] = xstrdup (argv[optind]);
857     }
858   url[i] = NULL;
859
860   /* Initialize logging.  */
861   log_init (opt.lfilename, append_to_log);
862
863   DEBUGP (("DEBUG output created by Wget %s on %s.\n\n", version_string,
864            OS_TYPE));
865
866   /* Open the output filename if necessary.  */
867   if (opt.output_document)
868     {
869       extern FILE *output_stream;
870       extern int output_stream_regular;
871
872       if (HYPHENP (opt.output_document))
873         output_stream = stdout;
874       else
875         {
876           struct_stat st;
877           output_stream = fopen (opt.output_document,
878                                  opt.always_rest ? "ab" : "wb");
879           if (output_stream == NULL)
880             {
881               perror (opt.output_document);
882               exit (1);
883             }
884           if (fstat (fileno (output_stream), &st) == 0 && S_ISREG (st.st_mode))
885             output_stream_regular = 1;
886         }
887     }
888
889 #ifdef WINDOWS
890   ws_startup ();
891 #endif
892
893   /* Setup the signal handler to redirect output when hangup is
894      received.  */
895 #ifdef HAVE_SIGNAL
896   if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
897     signal(SIGHUP, redirect_output_signal);
898   /* ...and do the same for SIGUSR1.  */
899   signal (SIGUSR1, redirect_output_signal);
900   /* Writing to a closed socket normally signals SIGPIPE, and the
901      process exits.  What we want is to ignore SIGPIPE and just check
902      for the return value of write().  */
903   signal (SIGPIPE, SIG_IGN);
904 #ifdef SIGWINCH
905   signal (SIGWINCH, progress_handle_sigwinch);
906 #endif
907 #endif /* HAVE_SIGNAL */
908
909   status = RETROK;              /* initialize it, just-in-case */
910   /* Retrieve the URLs from argument list.  */
911   for (t = url; *t; t++)
912     {
913       char *filename = NULL, *redirected_URL = NULL;
914       int dt;
915
916       if ((opt.recursive || opt.page_requisites)
917           && url_scheme (*t) != SCHEME_FTP)
918         status = retrieve_tree (*t);
919       else
920         status = retrieve_url (*t, &filename, &redirected_URL, NULL, &dt);
921
922       if (opt.delete_after && file_exists_p(filename))
923         {
924           DEBUGP (("Removing file due to --delete-after in main():\n"));
925           logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
926           if (unlink (filename))
927             logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
928         }
929
930       xfree_null (redirected_URL);
931       xfree_null (filename);
932     }
933
934   /* And then from the input file, if any.  */
935   if (opt.input_filename)
936     {
937       int count;
938       status = retrieve_from_file (opt.input_filename, opt.force_html, &count);
939       if (!count)
940         logprintf (LOG_NOTQUIET, _("No URLs found in %s.\n"),
941                    opt.input_filename);
942     }
943   /* Print the downloaded sum.  */
944   if (opt.recursive || opt.page_requisites
945       || nurl > 1
946       || (opt.input_filename && total_downloaded_bytes != 0))
947     {
948       logprintf (LOG_NOTQUIET,
949                  _("\nFINISHED --%s--\nDownloaded: %s bytes in %d files\n"),
950                  time_str (NULL), with_thousand_seps_large (total_downloaded_bytes),
951                  opt.numurls);
952       /* Print quota warning, if exceeded.  */
953       if (opt.quota && total_downloaded_bytes > opt.quota)
954         logprintf (LOG_NOTQUIET,
955                    _("Download quota (%s bytes) EXCEEDED!\n"),
956                    with_thousand_seps_large (opt.quota));
957     }
958
959   if (opt.cookies_output)
960     save_cookies ();
961
962   if (opt.convert_links && !opt.delete_after)
963     convert_all_links ();
964
965   log_close ();
966   for (i = 0; i < nurl; i++)
967     xfree (url[i]);
968   cleanup ();
969
970 #ifdef DEBUG_MALLOC
971   print_malloc_debug_stats ();
972 #endif
973   if (status == RETROK)
974     return 0;
975   else
976     return 1;
977 }
978 \f
979 #ifdef HAVE_SIGNAL
980 /* Hangup signal handler.  When wget receives SIGHUP or SIGUSR1, it
981    will proceed operation as usual, trying to write into a log file.
982    If that is impossible, the output will be turned off.
983
984    #### It is unsafe to do call libc functions from a signal handler.
985    What we should do is, set a global variable, and have the code in
986    log.c pick it up.  */
987
988 static RETSIGTYPE
989 redirect_output_signal (int sig)
990 {
991   const char *signal_name = (sig == SIGHUP ? "SIGHUP" :
992                              (sig == SIGUSR1 ? "SIGUSR1" :
993                               "WTF?!"));
994   log_request_redirect_output (signal_name);
995   progress_schedule_redirect ();
996   signal (sig, redirect_output_signal);
997 }
998 #endif /* HAVE_SIGNAL */