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