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