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