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