source: trunk/essentials/net-misc/wget/src/main.c

Last change on this file was 3440, checked in by bird, 18 years ago

wget 1.10.2

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