~ubuntu-branches/ubuntu/trusty/wget/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/CVE-2010-2252/src/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-05-17 19:46:25 UTC
  • mfrom: (2.1.10 sid)
  • Revision ID: james.westby@ubuntu.com-20110517194625-awyf9lkvyohk71ni
Tags: 1.12-3.1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add wget-udeb to ship wget.gnu as alternative to busybox wget
    implementation.
  - Keep build dependencies in main:
    + debian/control: remove info2man build-dep
    + debian/patches/series: disable wget-infopod_generated_manpage
  - Depend on libssl-dev 0.9.8k-7ubuntu4 (LP: #503339)
  - Mark wget Multi-Arch: foreign, so packages that aren't of the same arch
    can depend on it.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Command line parsing.
 
2
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
 
3
   2004, 2005, 2006, 2007, 2008, 2009 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 3 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, see <http://www.gnu.org/licenses/>.
 
19
 
 
20
Additional permission under GNU GPL version 3 section 7
 
21
 
 
22
If you modify this program, or any covered work, by linking or
 
23
combining it with the OpenSSL project's OpenSSL library (or a
 
24
modified version of that library), containing parts covered by the
 
25
terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
 
26
grants you additional permission to convey the resulting work.
 
27
Corresponding Source for a non-source form of such a combination
 
28
shall include the source code for the parts of OpenSSL used as well
 
29
as that of the covered work.  */
 
30
 
 
31
#include "wget.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 <string.h>
 
39
#include <signal.h>
 
40
#ifdef ENABLE_NLS
 
41
# include <locale.h>
 
42
#endif
 
43
#include <assert.h>
 
44
#include <errno.h>
 
45
#include <time.h>
 
46
 
 
47
#include "exits.h"
 
48
#include "utils.h"
 
49
#include "init.h"
 
50
#include "retr.h"
 
51
#include "recur.h"
 
52
#include "host.h"
 
53
#include "url.h"
 
54
#include "progress.h"           /* for progress_handle_sigwinch */
 
55
#include "convert.h"
 
56
#include "spider.h"
 
57
#include "http.h"               /* for save_cookies */
 
58
 
 
59
#include <getopt.h>
 
60
#include <getpass.h>
 
61
#include <quote.h>
 
62
 
 
63
#ifdef __VMS
 
64
#include "vms.h"
 
65
#endif /* __VMS */
 
66
 
 
67
#ifndef PATH_SEPARATOR
 
68
# define PATH_SEPARATOR '/'
 
69
#endif
 
70
 
 
71
struct options opt;
 
72
 
 
73
/* defined in version.c */
 
74
extern char *version_string;
 
75
extern char *compilation_string;
 
76
extern char *system_getrc;
 
77
extern char *link_string;
 
78
/* defined in build_info.c */
 
79
extern char *compiled_features[];
 
80
/* Used for --version output in print_version */
 
81
#define MAX_CHARS_PER_LINE      72
 
82
#define TABULATION              4
 
83
 
 
84
#if defined(SIGHUP) || defined(SIGUSR1)
 
85
static void redirect_output_signal (int);
 
86
#endif
 
87
 
 
88
const char *exec_name;
 
89
 
 
90
/* Number of successfully downloaded URLs */
 
91
int numurls = 0;
 
92
 
 
93
#ifndef TESTING
 
94
/* Initialize I18N/L10N.  That amounts to invoking setlocale, and
 
95
   setting up gettext's message catalog using bindtextdomain and
 
96
   textdomain.  Does nothing if NLS is disabled or missing.  */
 
97
 
 
98
static void
 
99
i18n_initialize (void)
 
100
{
 
101
  /* ENABLE_NLS implies existence of functions invoked here.  */
 
102
#ifdef ENABLE_NLS
 
103
  /* Set the current locale.  */
 
104
  setlocale (LC_ALL, "");
 
105
  /* Set the text message domain.  */
 
106
  bindtextdomain ("wget", LOCALEDIR);
 
107
  textdomain ("wget");
 
108
#endif /* ENABLE_NLS */
 
109
}
 
110
 
 
111
/* Definition of command-line options. */
 
112
 
 
113
static void print_help (void);
 
114
static void print_version (void);
 
115
 
 
116
#ifdef HAVE_SSL
 
117
# define IF_SSL(x) x
 
118
#else
 
119
# define IF_SSL(x) NULL
 
120
#endif
 
121
 
 
122
#ifdef ENABLE_DEBUG
 
123
# define WHEN_DEBUG(x) x
 
124
#else
 
125
# define WHEN_DEBUG(x) NULL
 
126
#endif
 
127
 
 
128
struct cmdline_option {
 
129
  const char *long_name;
 
130
  char short_name;
 
131
  enum {
 
132
    OPT_VALUE,
 
133
    OPT_BOOLEAN,
 
134
    OPT_FUNCALL,
 
135
    /* Non-standard options that have to be handled specially in
 
136
       main().  */
 
137
    OPT__APPEND_OUTPUT,
 
138
    OPT__CLOBBER,
 
139
    OPT__DONT_REMOVE_LISTING,
 
140
    OPT__EXECUTE,
 
141
    OPT__NO,
 
142
    OPT__PARENT
 
143
  } type;
 
144
  const void *data;             /* for standard options */
 
145
  int argtype;                  /* for non-standard options */
 
146
};
 
147
 
 
148
static struct cmdline_option option_data[] =
 
149
  {
 
150
    { "accept", 'A', OPT_VALUE, "accept", -1 },
 
151
    { "adjust-extension", 'E', OPT_BOOLEAN, "adjustextension", -1 },
 
152
    { "append-output", 'a', OPT__APPEND_OUTPUT, NULL, required_argument },
 
153
    { "ask-password", 0, OPT_BOOLEAN, "askpassword", -1 },
 
154
    { "auth-no-challenge", 0, OPT_BOOLEAN, "authnochallenge", -1 },
 
155
    { "background", 'b', OPT_BOOLEAN, "background", -1 },
 
156
    { "backup-converted", 'K', OPT_BOOLEAN, "backupconverted", -1 },
 
157
    { "backups", 0, OPT_BOOLEAN, "backups", -1 },
 
158
    { "base", 'B', OPT_VALUE, "base", -1 },
 
159
    { "bind-address", 0, OPT_VALUE, "bindaddress", -1 },
 
160
    { IF_SSL ("ca-certificate"), 0, OPT_VALUE, "cacertificate", -1 },
 
161
    { IF_SSL ("ca-directory"), 0, OPT_VALUE, "cadirectory", -1 },
 
162
    { "cache", 0, OPT_BOOLEAN, "cache", -1 },
 
163
    { IF_SSL ("certificate"), 0, OPT_VALUE, "certificate", -1 },
 
164
    { IF_SSL ("certificate-type"), 0, OPT_VALUE, "certificatetype", -1 },
 
165
    { IF_SSL ("check-certificate"), 0, OPT_BOOLEAN, "checkcertificate", -1 },
 
166
    { "clobber", 0, OPT__CLOBBER, NULL, optional_argument },
 
167
    { "connect-timeout", 0, OPT_VALUE, "connecttimeout", -1 },
 
168
    { "continue", 'c', OPT_BOOLEAN, "continue", -1 },
 
169
    { "convert-links", 'k', OPT_BOOLEAN, "convertlinks", -1 },
 
170
    { "content-disposition", 0, OPT_BOOLEAN, "contentdisposition", -1 },
 
171
    { "cookies", 0, OPT_BOOLEAN, "cookies", -1 },
 
172
    { "cut-dirs", 0, OPT_VALUE, "cutdirs", -1 },
 
173
    { WHEN_DEBUG ("debug"), 'd', OPT_BOOLEAN, "debug", -1 },
 
174
    { "default-page", 0, OPT_VALUE, "defaultpage", -1 },
 
175
    { "delete-after", 0, OPT_BOOLEAN, "deleteafter", -1 },
 
176
    { "directories", 0, OPT_BOOLEAN, "dirstruct", -1 },
 
177
    { "directory-prefix", 'P', OPT_VALUE, "dirprefix", -1 },
 
178
    { "dns-cache", 0, OPT_BOOLEAN, "dnscache", -1 },
 
179
    { "dns-timeout", 0, OPT_VALUE, "dnstimeout", -1 },
 
180
    { "domains", 'D', OPT_VALUE, "domains", -1 },
 
181
    { "dont-remove-listing", 0, OPT__DONT_REMOVE_LISTING, NULL, no_argument },
 
182
    { "dot-style", 0, OPT_VALUE, "dotstyle", -1 }, /* deprecated */
 
183
    { "egd-file", 0, OPT_VALUE, "egdfile", -1 },
 
184
    { "exclude-directories", 'X', OPT_VALUE, "excludedirectories", -1 },
 
185
    { "exclude-domains", 0, OPT_VALUE, "excludedomains", -1 },
 
186
    { "execute", 'e', OPT__EXECUTE, NULL, required_argument },
 
187
    { "follow-ftp", 0, OPT_BOOLEAN, "followftp", -1 },
 
188
    { "follow-tags", 0, OPT_VALUE, "followtags", -1 },
 
189
    { "force-directories", 'x', OPT_BOOLEAN, "dirstruct", -1 },
 
190
    { "force-html", 'F', OPT_BOOLEAN, "forcehtml", -1 },
 
191
    { "ftp-password", 0, OPT_VALUE, "ftppassword", -1 },
 
192
#ifdef __VMS
 
193
    { "ftp-stmlf", 0, OPT_BOOLEAN, "ftpstmlf", -1 },
 
194
#endif /* def __VMS */
 
195
    { "ftp-user", 0, OPT_VALUE, "ftpuser", -1 },
 
196
    { "glob", 0, OPT_BOOLEAN, "glob", -1 },
 
197
    { "header", 0, OPT_VALUE, "header", -1 },
 
198
    { "help", 'h', OPT_FUNCALL, (void *)print_help, no_argument },
 
199
    { "host-directories", 0, OPT_BOOLEAN, "addhostdir", -1 },
 
200
    { "html-extension", 'E', OPT_BOOLEAN, "adjustextension", -1 }, /* deprecated */
 
201
    { "htmlify", 0, OPT_BOOLEAN, "htmlify", -1 },
 
202
    { "http-keep-alive", 0, OPT_BOOLEAN, "httpkeepalive", -1 },
 
203
    { "http-passwd", 0, OPT_VALUE, "httppassword", -1 }, /* deprecated */
 
204
    { "http-password", 0, OPT_VALUE, "httppassword", -1 },
 
205
    { "http-user", 0, OPT_VALUE, "httpuser", -1 },
 
206
    { "ignore-case", 0, OPT_BOOLEAN, "ignorecase", -1 },
 
207
    { "ignore-length", 0, OPT_BOOLEAN, "ignorelength", -1 },
 
208
    { "ignore-tags", 0, OPT_VALUE, "ignoretags", -1 },
 
209
    { "include-directories", 'I', OPT_VALUE, "includedirectories", -1 },
 
210
#ifdef ENABLE_IPV6
 
211
    { "inet4-only", '4', OPT_BOOLEAN, "inet4only", -1 },
 
212
    { "inet6-only", '6', OPT_BOOLEAN, "inet6only", -1 },
 
213
#endif
 
214
    { "input-file", 'i', OPT_VALUE, "input", -1 },
 
215
    { "iri", 0, OPT_BOOLEAN, "iri", -1 },
 
216
    { "keep-session-cookies", 0, OPT_BOOLEAN, "keepsessioncookies", -1 },
 
217
    { "level", 'l', OPT_VALUE, "reclevel", -1 },
 
218
    { "limit-rate", 0, OPT_VALUE, "limitrate", -1 },
 
219
    { "load-cookies", 0, OPT_VALUE, "loadcookies", -1 },
 
220
    { "local-encoding", 0, OPT_VALUE, "localencoding", -1 },
 
221
    { "max-redirect", 0, OPT_VALUE, "maxredirect", -1 },
 
222
    { "mirror", 'm', OPT_BOOLEAN, "mirror", -1 },
 
223
    { "no", 'n', OPT__NO, NULL, required_argument },
 
224
    { "no-clobber", 0, OPT_BOOLEAN, "noclobber", -1 },
 
225
    { "no-parent", 0, OPT_BOOLEAN, "noparent", -1 },
 
226
    { "output-document", 'O', OPT_VALUE, "outputdocument", -1 },
 
227
    { "output-file", 'o', OPT_VALUE, "logfile", -1 },
 
228
    { "page-requisites", 'p', OPT_BOOLEAN, "pagerequisites", -1 },
 
229
    { "parent", 0, OPT__PARENT, NULL, optional_argument },
 
230
    { "passive-ftp", 0, OPT_BOOLEAN, "passiveftp", -1 },
 
231
    { "password", 0, OPT_VALUE, "password", -1 },
 
232
    { "post-data", 0, OPT_VALUE, "postdata", -1 },
 
233
    { "post-file", 0, OPT_VALUE, "postfile", -1 },
 
234
    { "prefer-family", 0, OPT_VALUE, "preferfamily", -1 },
 
235
    { "preserve-permissions", 0, OPT_BOOLEAN, "preservepermissions", -1 }, /* deprecated */
 
236
    { IF_SSL ("private-key"), 0, OPT_VALUE, "privatekey", -1 },
 
237
    { IF_SSL ("private-key-type"), 0, OPT_VALUE, "privatekeytype", -1 },
 
238
    { "progress", 0, OPT_VALUE, "progress", -1 },
 
239
    { "protocol-directories", 0, OPT_BOOLEAN, "protocoldirectories", -1 },
 
240
    { "proxy", 0, OPT_BOOLEAN, "useproxy", -1 },
 
241
    { "proxy__compat", 'Y', OPT_VALUE, "useproxy", -1 }, /* back-compatible */
 
242
    { "proxy-passwd", 0, OPT_VALUE, "proxypassword", -1 }, /* deprecated */
 
243
    { "proxy-password", 0, OPT_VALUE, "proxypassword", -1 },
 
244
    { "proxy-user", 0, OPT_VALUE, "proxyuser", -1 },
 
245
    { "quiet", 'q', OPT_BOOLEAN, "quiet", -1 },
 
246
    { "quota", 'Q', OPT_VALUE, "quota", -1 },
 
247
    { "random-file", 0, OPT_VALUE, "randomfile", -1 },
 
248
    { "random-wait", 0, OPT_BOOLEAN, "randomwait", -1 },
 
249
    { "read-timeout", 0, OPT_VALUE, "readtimeout", -1 },
 
250
    { "recursive", 'r', OPT_BOOLEAN, "recursive", -1 },
 
251
    { "referer", 0, OPT_VALUE, "referer", -1 },
 
252
    { "reject", 'R', OPT_VALUE, "reject", -1 },
 
253
    { "relative", 'L', OPT_BOOLEAN, "relativeonly", -1 },
 
254
    { "remote-encoding", 0, OPT_VALUE, "remoteencoding", -1 },
 
255
    { "remove-listing", 0, OPT_BOOLEAN, "removelisting", -1 },
 
256
    { "restrict-file-names", 0, OPT_BOOLEAN, "restrictfilenames", -1 },
 
257
    { "retr-symlinks", 0, OPT_BOOLEAN, "retrsymlinks", -1 },
 
258
    { "retry-connrefused", 0, OPT_BOOLEAN, "retryconnrefused", -1 },
 
259
    { "save-cookies", 0, OPT_VALUE, "savecookies", -1 },
 
260
    { "save-headers", 0, OPT_BOOLEAN, "saveheaders", -1 },
 
261
    { IF_SSL ("secure-protocol"), 0, OPT_VALUE, "secureprotocol", -1 },
 
262
    { "server-response", 'S', OPT_BOOLEAN, "serverresponse", -1 },
 
263
    { "span-hosts", 'H', OPT_BOOLEAN, "spanhosts", -1 },
 
264
    { "spider", 0, OPT_BOOLEAN, "spider", -1 },
 
265
    { "strict-comments", 0, OPT_BOOLEAN, "strictcomments", -1 },
 
266
    { "timeout", 'T', OPT_VALUE, "timeout", -1 },
 
267
    { "timestamping", 'N', OPT_BOOLEAN, "timestamping", -1 },
 
268
    { "tries", 't', OPT_VALUE, "tries", -1 },
 
269
    { "user", 0, OPT_VALUE, "user", -1 },
 
270
    { "user-agent", 'U', OPT_VALUE, "useragent", -1 },
 
271
    { "verbose", 'v', OPT_BOOLEAN, "verbose", -1 },
 
272
    { "verbose", 0, OPT_BOOLEAN, "verbose", -1 },
 
273
    { "version", 'V', OPT_FUNCALL, (void *) print_version, no_argument },
 
274
    { "wait", 'w', OPT_VALUE, "wait", -1 },
 
275
    { "waitretry", 0, OPT_VALUE, "waitretry", -1 },
 
276
#ifdef USE_WATT32
 
277
    { "wdebug", 0, OPT_BOOLEAN, "wdebug", -1 },
 
278
#endif
 
279
  };
 
280
 
 
281
#undef WHEN_DEBUG
 
282
#undef IF_SSL
 
283
 
 
284
/* Return a string that contains S with "no-" prepended.  The string
 
285
   is NUL-terminated and allocated off static storage at Wget
 
286
   startup.  */
 
287
 
 
288
static char *
 
289
no_prefix (const char *s)
 
290
{
 
291
  static char buffer[1024];
 
292
  static char *p = buffer;
 
293
 
 
294
  char *cp = p;
 
295
  int size = 3 + strlen (s) + 1;  /* "no-STRING\0" */
 
296
  if (p + size >= buffer + sizeof (buffer))
 
297
    abort ();
 
298
 
 
299
  cp[0] = 'n', cp[1] = 'o', cp[2] = '-';
 
300
  strcpy (cp + 3, s);
 
301
  p += size;
 
302
  return cp;
 
303
}
 
304
 
 
305
/* The arguments that that main passes to getopt_long. */
 
306
static struct option long_options[2 * countof (option_data) + 1];
 
307
static char short_options[128];
 
308
 
 
309
/* Mapping between short option chars and option_data indices. */
 
310
static unsigned char optmap[96];
 
311
 
 
312
/* Marker for `--no-FOO' values in long_options.  */
 
313
#define BOOLEAN_NEG_MARKER 1024
 
314
 
 
315
/* Initialize the long_options array used by getopt_long from the data
 
316
   in option_data.  */
 
317
 
 
318
static void
 
319
init_switches (void)
 
320
{
 
321
  char *p = short_options;
 
322
  size_t i, o = 0;
 
323
  for (i = 0; i < countof (option_data); i++)
 
324
    {
 
325
      struct cmdline_option *opt = &option_data[i];
 
326
      struct option *longopt;
 
327
 
 
328
      if (!opt->long_name)
 
329
        /* The option is disabled. */
 
330
        continue;
 
331
 
 
332
      longopt = &long_options[o++];
 
333
      longopt->name = opt->long_name;
 
334
      longopt->val = i;
 
335
      if (opt->short_name)
 
336
        {
 
337
          *p++ = opt->short_name;
 
338
          optmap[opt->short_name - 32] = longopt - long_options;
 
339
        }
 
340
      switch (opt->type)
 
341
        {
 
342
        case OPT_VALUE:
 
343
          longopt->has_arg = required_argument;
 
344
          if (opt->short_name)
 
345
            *p++ = ':';
 
346
          break;
 
347
        case OPT_BOOLEAN:
 
348
          /* Specify an optional argument for long options, so that
 
349
             --option=off works the same as --no-option, for
 
350
             compatibility with pre-1.10 Wget.  However, don't specify
 
351
             optional arguments short-option booleans because they
 
352
             prevent combining of short options.  */
 
353
          longopt->has_arg = optional_argument;
 
354
          /* For Boolean options, add the "--no-FOO" variant, which is
 
355
             identical to "--foo", except it has opposite meaning and
 
356
             it doesn't allow an argument.  */
 
357
          longopt = &long_options[o++];
 
358
          longopt->name = no_prefix (opt->long_name);
 
359
          longopt->has_arg = no_argument;
 
360
          /* Mask the value so we'll be able to recognize that we're
 
361
             dealing with the false value.  */
 
362
          longopt->val = i | BOOLEAN_NEG_MARKER;
 
363
          break;
 
364
        default:
 
365
          assert (opt->argtype != -1);
 
366
          longopt->has_arg = opt->argtype;
 
367
          if (opt->short_name)
 
368
            {
 
369
              if (longopt->has_arg == required_argument)
 
370
                *p++ = ':';
 
371
              /* Don't handle optional_argument */
 
372
            }
 
373
        }
 
374
    }
 
375
  /* Terminate short_options. */
 
376
  *p = '\0';
 
377
  /* No need for xzero(long_options[o]) because its storage is static
 
378
     and it will be zeroed by default.  */
 
379
  assert (o <= countof (long_options));
 
380
}
 
381
 
 
382
/* Print the usage message.  */
 
383
static void
 
384
print_usage (void)
 
385
{
 
386
  printf (_("Usage: %s [OPTION]... [URL]...\n"), exec_name);
 
387
}
 
388
 
 
389
/* Print the help message, describing all the available options.  If
 
390
   you add an option, be sure to update this list.  */
 
391
static void
 
392
print_help (void)
 
393
{
 
394
  /* We split the help text this way to ease translation of individual
 
395
     entries.  */
 
396
  static const char *help[] = {
 
397
    "\n",
 
398
    N_("\
 
399
Mandatory arguments to long options are mandatory for short options too.\n\n"),
 
400
    N_("\
 
401
Startup:\n"),
 
402
    N_("\
 
403
  -V,  --version           display the version of Wget and exit.\n"),
 
404
    N_("\
 
405
  -h,  --help              print this help.\n"),
 
406
    N_("\
 
407
  -b,  --background        go to background after startup.\n"),
 
408
    N_("\
 
409
  -e,  --execute=COMMAND   execute a `.wgetrc'-style command.\n"),
 
410
    "\n",
 
411
 
 
412
    N_("\
 
413
Logging and input file:\n"),
 
414
    N_("\
 
415
  -o,  --output-file=FILE    log messages to FILE.\n"),
 
416
    N_("\
 
417
  -a,  --append-output=FILE  append messages to FILE.\n"),
 
418
#ifdef ENABLE_DEBUG
 
419
    N_("\
 
420
  -d,  --debug               print lots of debugging information.\n"),
 
421
#endif
 
422
#ifdef USE_WATT32
 
423
    N_("\
 
424
       --wdebug              print Watt-32 debug output.\n"),
 
425
#endif
 
426
    N_("\
 
427
  -q,  --quiet               quiet (no output).\n"),
 
428
    N_("\
 
429
  -v,  --verbose             be verbose (this is the default).\n"),
 
430
    N_("\
 
431
  -nv, --no-verbose          turn off verboseness, without being quiet.\n"),
 
432
    N_("\
 
433
  -i,  --input-file=FILE     download URLs found in local or external FILE.\n"),
 
434
    N_("\
 
435
  -F,  --force-html          treat input file as HTML.\n"),
 
436
    N_("\
 
437
  -B,  --base=URL            resolves HTML input-file links (-i -F)\n\
 
438
                             relative to URL.\n"),
 
439
    "\n",
 
440
 
 
441
    N_("\
 
442
Download:\n"),
 
443
    N_("\
 
444
  -t,  --tries=NUMBER            set number of retries to NUMBER (0 unlimits).\n"),
 
445
    N_("\
 
446
       --retry-connrefused       retry even if connection is refused.\n"),
 
447
    N_("\
 
448
  -O,  --output-document=FILE    write documents to FILE.\n"),
 
449
    N_("\
 
450
  -nc, --no-clobber              skip downloads that would download to\n\
 
451
                                 existing files.\n"),
 
452
    N_("\
 
453
  -c,  --continue                resume getting a partially-downloaded file.\n"),
 
454
    N_("\
 
455
       --progress=TYPE           select progress gauge type.\n"),
 
456
    N_("\
 
457
  -N,  --timestamping            don't re-retrieve files unless newer than\n\
 
458
                                 local.\n"),
 
459
    N_("\
 
460
  -S,  --server-response         print server response.\n"),
 
461
    N_("\
 
462
       --spider                  don't download anything.\n"),
 
463
    N_("\
 
464
  -T,  --timeout=SECONDS         set all timeout values to SECONDS.\n"),
 
465
    N_("\
 
466
       --dns-timeout=SECS        set the DNS lookup timeout to SECS.\n"),
 
467
    N_("\
 
468
       --connect-timeout=SECS    set the connect timeout to SECS.\n"),
 
469
    N_("\
 
470
       --read-timeout=SECS       set the read timeout to SECS.\n"),
 
471
    N_("\
 
472
  -w,  --wait=SECONDS            wait SECONDS between retrievals.\n"),
 
473
    N_("\
 
474
       --waitretry=SECONDS       wait 1..SECONDS between retries of a retrieval.\n"),
 
475
    N_("\
 
476
       --random-wait             wait from 0...2*WAIT secs between retrievals.\n"),
 
477
    N_("\
 
478
       --no-proxy                explicitly turn off proxy.\n"),
 
479
    N_("\
 
480
  -Q,  --quota=NUMBER            set retrieval quota to NUMBER.\n"),
 
481
    N_("\
 
482
       --bind-address=ADDRESS    bind to ADDRESS (hostname or IP) on local host.\n"),
 
483
    N_("\
 
484
       --limit-rate=RATE         limit download rate to RATE.\n"),
 
485
    N_("\
 
486
       --no-dns-cache            disable caching DNS lookups.\n"),
 
487
    N_("\
 
488
       --restrict-file-names=OS  restrict chars in file names to ones OS allows.\n"),
 
489
    N_("\
 
490
       --ignore-case             ignore case when matching files/directories.\n"),
 
491
#ifdef ENABLE_IPV6
 
492
    N_("\
 
493
  -4,  --inet4-only              connect only to IPv4 addresses.\n"),
 
494
    N_("\
 
495
  -6,  --inet6-only              connect only to IPv6 addresses.\n"),
 
496
    N_("\
 
497
       --prefer-family=FAMILY    connect first to addresses of specified family,\n\
 
498
                                 one of IPv6, IPv4, or none.\n"),
 
499
#endif
 
500
    N_("\
 
501
       --user=USER               set both ftp and http user to USER.\n"),
 
502
    N_("\
 
503
       --password=PASS           set both ftp and http password to PASS.\n"),
 
504
    N_("\
 
505
       --ask-password            prompt for passwords.\n"),
 
506
    N_("\
 
507
       --no-iri                  turn off IRI support.\n"),
 
508
    N_("\
 
509
       --local-encoding=ENC      use ENC as the local encoding for IRIs.\n"),
 
510
    N_("\
 
511
       --remote-encoding=ENC     use ENC as the default remote encoding.\n"),
 
512
    "\n",
 
513
 
 
514
    N_("\
 
515
Directories:\n"),
 
516
    N_("\
 
517
  -nd, --no-directories           don't create directories.\n"),
 
518
    N_("\
 
519
  -x,  --force-directories        force creation of directories.\n"),
 
520
    N_("\
 
521
  -nH, --no-host-directories      don't create host directories.\n"),
 
522
    N_("\
 
523
       --protocol-directories     use protocol name in directories.\n"),
 
524
    N_("\
 
525
  -P,  --directory-prefix=PREFIX  save files to PREFIX/...\n"),
 
526
    N_("\
 
527
       --cut-dirs=NUMBER          ignore NUMBER remote directory components.\n"),
 
528
    "\n",
 
529
 
 
530
    N_("\
 
531
HTTP options:\n"),
 
532
    N_("\
 
533
       --http-user=USER        set http user to USER.\n"),
 
534
    N_("\
 
535
       --http-password=PASS    set http password to PASS.\n"),
 
536
    N_("\
 
537
       --no-cache              disallow server-cached data.\n"),
 
538
    N_ ("\
 
539
       --default-page=NAME     Change the default page name (normally\n\
 
540
                               this is `index.html'.).\n"),
 
541
    N_("\
 
542
  -E,  --adjust-extension      save HTML/CSS documents with proper extensions.\n"),
 
543
    N_("\
 
544
       --ignore-length         ignore `Content-Length' header field.\n"),
 
545
    N_("\
 
546
       --header=STRING         insert STRING among the headers.\n"),
 
547
    N_("\
 
548
       --max-redirect          maximum redirections allowed per page.\n"),
 
549
    N_("\
 
550
       --proxy-user=USER       set USER as proxy username.\n"),
 
551
    N_("\
 
552
       --proxy-password=PASS   set PASS as proxy password.\n"),
 
553
    N_("\
 
554
       --referer=URL           include `Referer: URL' header in HTTP request.\n"),
 
555
    N_("\
 
556
       --save-headers          save the HTTP headers to file.\n"),
 
557
    N_("\
 
558
  -U,  --user-agent=AGENT      identify as AGENT instead of Wget/VERSION.\n"),
 
559
    N_("\
 
560
       --no-http-keep-alive    disable HTTP keep-alive (persistent connections).\n"),
 
561
    N_("\
 
562
       --no-cookies            don't use cookies.\n"),
 
563
    N_("\
 
564
       --load-cookies=FILE     load cookies from FILE before session.\n"),
 
565
    N_("\
 
566
       --save-cookies=FILE     save cookies to FILE after session.\n"),
 
567
    N_("\
 
568
       --keep-session-cookies  load and save session (non-permanent) cookies.\n"),
 
569
    N_("\
 
570
       --post-data=STRING      use the POST method; send STRING as the data.\n"),
 
571
    N_("\
 
572
       --post-file=FILE        use the POST method; send contents of FILE.\n"),
 
573
    N_("\
 
574
       --content-disposition   honor the Content-Disposition header when\n\
 
575
                               choosing local file names (EXPERIMENTAL).\n"),
 
576
    N_("\
 
577
       --auth-no-challenge     send Basic HTTP authentication information\n\
 
578
                               without first waiting for the server's\n\
 
579
                               challenge.\n"),
 
580
    "\n",
 
581
 
 
582
#ifdef HAVE_SSL
 
583
    N_("\
 
584
HTTPS (SSL/TLS) options:\n"),
 
585
    N_("\
 
586
       --secure-protocol=PR     choose secure protocol, one of auto, SSLv2,\n\
 
587
                                SSLv3, and TLSv1.\n"),
 
588
    N_("\
 
589
       --no-check-certificate   don't validate the server's certificate.\n"),
 
590
    N_("\
 
591
       --certificate=FILE       client certificate file.\n"),
 
592
    N_("\
 
593
       --certificate-type=TYPE  client certificate type, PEM or DER.\n"),
 
594
    N_("\
 
595
       --private-key=FILE       private key file.\n"),
 
596
    N_("\
 
597
       --private-key-type=TYPE  private key type, PEM or DER.\n"),
 
598
    N_("\
 
599
       --ca-certificate=FILE    file with the bundle of CA's.\n"),
 
600
    N_("\
 
601
       --ca-directory=DIR       directory where hash list of CA's is stored.\n"),
 
602
    N_("\
 
603
       --random-file=FILE       file with random data for seeding the SSL PRNG.\n"),
 
604
    N_("\
 
605
       --egd-file=FILE          file naming the EGD socket with random data.\n"),
 
606
    "\n",
 
607
#endif /* HAVE_SSL */
 
608
 
 
609
    N_("\
 
610
FTP options:\n"),
 
611
#ifdef __VMS
 
612
    N_("\
 
613
       --ftp-stmlf             Use Stream_LF format for all binary FTP files.\n"),
 
614
#endif /* def __VMS */
 
615
    N_("\
 
616
       --ftp-user=USER         set ftp user to USER.\n"),
 
617
    N_("\
 
618
       --ftp-password=PASS     set ftp password to PASS.\n"),
 
619
    N_("\
 
620
       --no-remove-listing     don't remove `.listing' files.\n"),
 
621
    N_("\
 
622
       --no-glob               turn off FTP file name globbing.\n"),
 
623
    N_("\
 
624
       --no-passive-ftp        disable the \"passive\" transfer mode.\n"),
 
625
    N_("\
 
626
       --retr-symlinks         when recursing, get linked-to files (not dir).\n"),
 
627
    "\n",
 
628
 
 
629
    N_("\
 
630
Recursive download:\n"),
 
631
    N_("\
 
632
  -r,  --recursive          specify recursive download.\n"),
 
633
    N_("\
 
634
  -l,  --level=NUMBER       maximum recursion depth (inf or 0 for infinite).\n"),
 
635
    N_("\
 
636
       --delete-after       delete files locally after downloading them.\n"),
 
637
    N_("\
 
638
  -k,  --convert-links      make links in downloaded HTML or CSS point to\n\
 
639
                            local files.\n"),
 
640
#ifdef __VMS
 
641
    N_("\
 
642
  -K,  --backup-converted   before converting file X, back up as X_orig.\n"),
 
643
#else /* def __VMS */
 
644
    N_("\
 
645
  -K,  --backup-converted   before converting file X, back up as X.orig.\n"),
 
646
#endif /* def __VMS [else] */
 
647
    N_("\
 
648
  -m,  --mirror             shortcut for -N -r -l inf --no-remove-listing.\n"),
 
649
    N_("\
 
650
  -p,  --page-requisites    get all images, etc. needed to display HTML page.\n"),
 
651
    N_("\
 
652
       --strict-comments    turn on strict (SGML) handling of HTML comments.\n"),
 
653
    "\n",
 
654
 
 
655
    N_("\
 
656
Recursive accept/reject:\n"),
 
657
    N_("\
 
658
  -A,  --accept=LIST               comma-separated list of accepted extensions.\n"),
 
659
    N_("\
 
660
  -R,  --reject=LIST               comma-separated list of rejected extensions.\n"),
 
661
    N_("\
 
662
  -D,  --domains=LIST              comma-separated list of accepted domains.\n"),
 
663
    N_("\
 
664
       --exclude-domains=LIST      comma-separated list of rejected domains.\n"),
 
665
    N_("\
 
666
       --follow-ftp                follow FTP links from HTML documents.\n"),
 
667
    N_("\
 
668
       --follow-tags=LIST          comma-separated list of followed HTML tags.\n"),
 
669
    N_("\
 
670
       --ignore-tags=LIST          comma-separated list of ignored HTML tags.\n"),
 
671
    N_("\
 
672
  -H,  --span-hosts                go to foreign hosts when recursive.\n"),
 
673
    N_("\
 
674
  -L,  --relative                  follow relative links only.\n"),
 
675
    N_("\
 
676
  -I,  --include-directories=LIST  list of allowed directories.\n"),
 
677
    N_("\
 
678
  -X,  --exclude-directories=LIST  list of excluded directories.\n"),
 
679
    N_("\
 
680
  -np, --no-parent                 don't ascend to the parent directory.\n"),
 
681
    "\n",
 
682
 
 
683
    N_("Mail bug reports and suggestions to <bug-wget@gnu.org>.\n")
 
684
  };
 
685
 
 
686
  size_t i;
 
687
 
 
688
  printf (_("GNU Wget %s, a non-interactive network retriever.\n"),
 
689
          version_string);
 
690
  print_usage ();
 
691
 
 
692
  for (i = 0; i < countof (help); i++)
 
693
    fputs (_(help[i]), stdout);
 
694
 
 
695
  exit (0);
 
696
}
 
697
 
 
698
/* Return a human-readable printed representation of INTERVAL,
 
699
   measured in seconds.  */
 
700
 
 
701
static char *
 
702
secs_to_human_time (double interval)
 
703
{
 
704
  static char buf[32];
 
705
  int secs = (int) (interval + 0.5);
 
706
  int hours, mins, days;
 
707
 
 
708
  days = secs / 86400, secs %= 86400;
 
709
  hours = secs / 3600, secs %= 3600;
 
710
  mins = secs / 60, secs %= 60;
 
711
 
 
712
  if (days)
 
713
    sprintf (buf, "%dd %dh %dm %ds", days, hours, mins, secs);
 
714
  else if (hours)
 
715
    sprintf (buf, "%dh %dm %ds", hours, mins, secs);
 
716
  else if (mins)
 
717
    sprintf (buf, "%dm %ds", mins, secs);
 
718
  else
 
719
    sprintf (buf, "%ss", print_decimal (interval));
 
720
 
 
721
  return buf;
 
722
}
 
723
 
 
724
static char *
 
725
prompt_for_password (void)
 
726
{
 
727
  if (opt.user)
 
728
    printf (_("Password for user %s: "), quote (opt.user));
 
729
  else
 
730
    printf (_("Password: "));
 
731
  return getpass("");
 
732
}
 
733
 
 
734
/* Function that prints the line argument while limiting it
 
735
   to at most line_length. prefix is printed on the first line
 
736
   and an appropriate number of spaces are added on subsequent
 
737
   lines.*/
 
738
static void
 
739
format_and_print_line (const char *prefix, const char *line,
 
740
                       int line_length)
 
741
{
 
742
  int remaining_chars;
 
743
  char *line_dup, *token;
 
744
 
 
745
  assert (prefix != NULL);
 
746
  assert (line != NULL);
 
747
 
 
748
  line_dup = xstrdup (line);
 
749
 
 
750
  if (line_length <= 0)
 
751
    line_length = MAX_CHARS_PER_LINE - TABULATION;
 
752
 
 
753
  printf ("%s", prefix);
 
754
  remaining_chars = line_length;
 
755
  /* We break on spaces. */
 
756
  token = strtok (line_dup, " ");
 
757
  while (token != NULL)
 
758
    {
 
759
      /* If however a token is much larger than the maximum
 
760
         line length, all bets are off and we simply print the
 
761
         token on the next line. */
 
762
      if (remaining_chars <= strlen (token))
 
763
        {
 
764
          printf ("\n%*c", TABULATION, ' ');
 
765
          remaining_chars = line_length - TABULATION;
 
766
        }
 
767
      printf ("%s ", token);
 
768
      remaining_chars -= strlen (token) + 1;  /* account for " " */
 
769
      token = strtok (NULL, " ");
 
770
    }
 
771
 
 
772
  printf ("\n");
 
773
 
 
774
  xfree (line_dup);
 
775
}
 
776
 
 
777
static void
 
778
print_version (void)
 
779
{
 
780
  const char *wgetrc_title  = _("Wgetrc: ");
 
781
  const char *locale_title  = _("Locale: ");
 
782
  const char *compile_title = _("Compile: ");
 
783
  const char *link_title    = _("Link: ");
 
784
  char *line;
 
785
  char *env_wgetrc, *user_wgetrc;
 
786
  int i;
 
787
 
 
788
#ifdef __VMS
 
789
  printf (_("GNU Wget %s built on VMS %s %s.\n\n"),
 
790
   version_string, vms_arch(), vms_vers());
 
791
#else /* def __VMS */
 
792
  printf (_("GNU Wget %s built on %s.\n\n"), version_string, OS_TYPE);
 
793
#endif /* def __VMS */
 
794
  /* compiled_features is a char*[]. We limit the characters per
 
795
     line to MAX_CHARS_PER_LINE and prefix each line with a constant
 
796
     number of spaces for proper alignment. */
 
797
  for (i = 0; compiled_features[i] != NULL; )
 
798
    {
 
799
      int line_length = MAX_CHARS_PER_LINE;
 
800
      while ((line_length > 0) && (compiled_features[i] != NULL))
 
801
        {
 
802
          printf ("%s ", compiled_features[i]);
 
803
          line_length -= strlen (compiled_features[i]) + 2;
 
804
          i++;
 
805
        }
 
806
      printf ("\n");
 
807
    }
 
808
  printf ("\n");
 
809
  /* Handle the case when $WGETRC is unset and $HOME/.wgetrc is
 
810
     absent. */
 
811
  printf ("%s\n", wgetrc_title);
 
812
  env_wgetrc = wgetrc_env_file_name ();
 
813
  if (env_wgetrc && *env_wgetrc)
 
814
    {
 
815
      printf (_("    %s (env)\n"), env_wgetrc);
 
816
      xfree (env_wgetrc);
 
817
    }
 
818
  user_wgetrc = wgetrc_user_file_name ();
 
819
  if (user_wgetrc)
 
820
    {
 
821
      printf (_("    %s (user)\n"), user_wgetrc);
 
822
      xfree (user_wgetrc);
 
823
    }
 
824
#ifdef SYSTEM_WGETRC
 
825
  printf (_("    %s (system)\n"), SYSTEM_WGETRC);
 
826
#endif
 
827
 
 
828
#ifdef ENABLE_NLS
 
829
  format_and_print_line (locale_title,
 
830
                        LOCALEDIR,
 
831
                        MAX_CHARS_PER_LINE);
 
832
#endif /* def ENABLE_NLS */
 
833
 
 
834
  format_and_print_line (compile_title,
 
835
                         compilation_string,
 
836
                         MAX_CHARS_PER_LINE);
 
837
 
 
838
  format_and_print_line (link_title,
 
839
                         link_string,
 
840
                         MAX_CHARS_PER_LINE);
 
841
 
 
842
  printf ("\n");
 
843
  /* TRANSLATORS: When available, an actual copyright character
 
844
     (cirle-c) should be used in preference to "(C)". */
 
845
  fputs (_("\
 
846
Copyright (C) 2009 Free Software Foundation, Inc.\n"), stdout);
 
847
  fputs (_("\
 
848
License GPLv3+: GNU GPL version 3 or later\n\
 
849
<http://www.gnu.org/licenses/gpl.html>.\n\
 
850
This is free software: you are free to change and redistribute it.\n\
 
851
There is NO WARRANTY, to the extent permitted by law.\n"), stdout);
 
852
  /* TRANSLATORS: When available, please use the proper diacritics for
 
853
     names such as this one. See en_US.po for reference. */
 
854
  fputs (_("\nOriginally written by Hrvoje Niksic <hniksic@xemacs.org>.\n"),
 
855
         stdout);
 
856
  fputs (_("Currently maintained by Micah Cowan <micah@cowan.name>.\n"),
 
857
         stdout);
 
858
  fputs (_("Please send bug reports and questions to <bug-wget@gnu.org>.\n"),
 
859
         stdout);
 
860
  exit (0);
 
861
}
 
862
 
 
863
char *program_name; /* Needed by lib/error.c. */
 
864
 
 
865
int
 
866
main (int argc, char **argv)
 
867
{
 
868
  char **url, **t;
 
869
  int i, ret, longindex;
 
870
  int nurl, status;
 
871
  bool append_to_log = false;
 
872
 
 
873
  program_name = argv[0];
 
874
 
 
875
  i18n_initialize ();
 
876
 
 
877
  /* Construct the name of the executable, without the directory part.  */
 
878
  exec_name = strrchr (argv[0], PATH_SEPARATOR);
 
879
  if (!exec_name)
 
880
    exec_name = argv[0];
 
881
  else
 
882
    ++exec_name;
 
883
 
 
884
#ifdef WINDOWS
 
885
  /* Drop extension (typically .EXE) from executable filename. */
 
886
  windows_main ((char **) &exec_name);
 
887
#endif
 
888
 
 
889
  /* Set option defaults; read the system wgetrc and ~/.wgetrc.  */
 
890
  initialize ();
 
891
 
 
892
  init_switches ();
 
893
  longindex = -1;
 
894
  while ((ret = getopt_long (argc, argv,
 
895
                             short_options, long_options, &longindex)) != -1)
 
896
    {
 
897
      int val;
 
898
      struct cmdline_option *opt;
 
899
 
 
900
      /* If LONGINDEX is unchanged, it means RET is referring a short
 
901
         option.  */
 
902
      if (longindex == -1)
 
903
        {
 
904
          if (ret == '?')
 
905
            {
 
906
              print_usage ();
 
907
              printf ("\n");
 
908
              printf (_("Try `%s --help' for more options.\n"), exec_name);
 
909
              exit (2);
 
910
            }
 
911
          /* Find the short option character in the mapping.  */
 
912
          longindex = optmap[ret - 32];
 
913
        }
 
914
      val = long_options[longindex].val;
 
915
 
 
916
      /* Use the retrieved value to locate the option in the
 
917
         option_data array, and to see if we're dealing with the
 
918
         negated "--no-FOO" variant of the boolean option "--foo".  */
 
919
      opt = &option_data[val & ~BOOLEAN_NEG_MARKER];
 
920
      switch (opt->type)
 
921
        {
 
922
        case OPT_VALUE:
 
923
          setoptval (opt->data, optarg, opt->long_name);
 
924
          break;
 
925
        case OPT_BOOLEAN:
 
926
          if (optarg)
 
927
            /* The user has specified a value -- use it. */
 
928
            setoptval (opt->data, optarg, opt->long_name);
 
929
          else
 
930
            {
 
931
              /* NEG is true for `--no-FOO' style boolean options. */
 
932
              bool neg = !!(val & BOOLEAN_NEG_MARKER);
 
933
              setoptval (opt->data, neg ? "0" : "1", opt->long_name);
 
934
            }
 
935
          break;
 
936
        case OPT_FUNCALL:
 
937
          {
 
938
            void (*func) (void) = (void (*) (void)) opt->data;
 
939
            func ();
 
940
          }
 
941
          break;
 
942
        case OPT__APPEND_OUTPUT:
 
943
          setoptval ("logfile", optarg, opt->long_name);
 
944
          append_to_log = true;
 
945
          break;
 
946
        case OPT__EXECUTE:
 
947
          run_command (optarg);
 
948
          break;
 
949
        case OPT__NO:
 
950
          {
 
951
            /* We support real --no-FOO flags now, but keep these
 
952
               short options for convenience and backward
 
953
               compatibility.  */
 
954
            char *p;
 
955
            for (p = optarg; *p; p++)
 
956
              switch (*p)
 
957
                {
 
958
                case 'v':
 
959
                  setoptval ("verbose", "0", opt->long_name);
 
960
                  break;
 
961
                case 'H':
 
962
                  setoptval ("addhostdir", "0", opt->long_name);
 
963
                  break;
 
964
                case 'd':
 
965
                  setoptval ("dirstruct", "0", opt->long_name);
 
966
                  break;
 
967
                case 'c':
 
968
                  setoptval ("noclobber", "1", opt->long_name);
 
969
                  break;
 
970
                case 'p':
 
971
                  setoptval ("noparent", "1", opt->long_name);
 
972
                  break;
 
973
                default:
 
974
                  printf (_("%s: illegal option -- `-n%c'\n"), exec_name, *p);
 
975
                  print_usage ();
 
976
                  printf ("\n");
 
977
                  printf (_("Try `%s --help' for more options.\n"), exec_name);
 
978
                  exit (1);
 
979
                }
 
980
            break;
 
981
          }
 
982
        case OPT__PARENT:
 
983
        case OPT__CLOBBER:
 
984
          {
 
985
            /* The wgetrc commands are named noparent and noclobber,
 
986
               so we must revert the meaning of the cmdline options
 
987
               before passing the value to setoptval.  */
 
988
            bool flag = true;
 
989
            if (optarg)
 
990
              flag = (*optarg == '1' || c_tolower (*optarg) == 'y'
 
991
                      || (c_tolower (optarg[0]) == 'o'
 
992
                          && c_tolower (optarg[1]) == 'n'));
 
993
            setoptval (opt->type == OPT__PARENT ? "noparent" : "noclobber",
 
994
                       flag ? "0" : "1", opt->long_name);
 
995
            break;
 
996
          }
 
997
        case OPT__DONT_REMOVE_LISTING:
 
998
          setoptval ("removelisting", "0", opt->long_name);
 
999
          break;
 
1000
        }
 
1001
 
 
1002
      longindex = -1;
 
1003
    }
 
1004
 
 
1005
  nurl = argc - optind;
 
1006
 
 
1007
  /* All user options have now been processed, so it's now safe to do
 
1008
     interoption dependency checks. */
 
1009
 
 
1010
  if (opt.reclevel == 0)
 
1011
      opt.reclevel = INFINITE_RECURSION; /* see recur.h for commentary */
 
1012
 
 
1013
  if (opt.spider || opt.delete_after)
 
1014
      opt.no_dirstruct = true;
 
1015
 
 
1016
  if (opt.page_requisites && !opt.recursive)
 
1017
    {
 
1018
      /* Don't set opt.recursive here because it would confuse the FTP
 
1019
         code.  Instead, call retrieve_tree below when either
 
1020
         page_requisites or recursive is requested.  */
 
1021
      opt.reclevel = 0;
 
1022
      if (!opt.no_dirstruct)
 
1023
        opt.dirstruct = 1;      /* normally handled by cmd_spec_recursive() */
 
1024
    }
 
1025
 
 
1026
  if (opt.verbose == -1)
 
1027
    opt.verbose = !opt.quiet;
 
1028
 
 
1029
  /* Sanity checks.  */
 
1030
  if (opt.verbose && opt.quiet)
 
1031
    {
 
1032
      printf (_("Can't be verbose and quiet at the same time.\n"));
 
1033
      print_usage ();
 
1034
      exit (1);
 
1035
    }
 
1036
  if (opt.timestamping && opt.noclobber)
 
1037
    {
 
1038
      printf (_("\
 
1039
Can't timestamp and not clobber old files at the same time.\n"));
 
1040
      print_usage ();
 
1041
      exit (1);
 
1042
    }
 
1043
#ifdef ENABLE_IPV6
 
1044
  if (opt.ipv4_only && opt.ipv6_only)
 
1045
    {
 
1046
      printf (_("Cannot specify both --inet4-only and --inet6-only.\n"));
 
1047
      print_usage ();
 
1048
      exit (1);
 
1049
    }
 
1050
#endif
 
1051
  if (opt.output_document)
 
1052
    {
 
1053
      if (opt.convert_links
 
1054
          && (nurl > 1 || opt.page_requisites || opt.recursive))
 
1055
        {
 
1056
          fputs (_("\
 
1057
Cannot specify both -k and -O if multiple URLs are given, or in combination\n\
 
1058
with -p or -r. See the manual for details.\n\n"), stdout);
 
1059
          print_usage ();
 
1060
          exit (1);
 
1061
        }
 
1062
      if (opt.page_requisites
 
1063
          || opt.recursive)
 
1064
        {
 
1065
          logprintf (LOG_NOTQUIET, "%s", _("\
 
1066
WARNING: combining -O with -r or -p will mean that all downloaded content\n\
 
1067
will be placed in the single file you specified.\n\n"));
 
1068
        }
 
1069
      if (opt.timestamping)
 
1070
        {
 
1071
          logprintf (LOG_NOTQUIET, "%s", _("\
 
1072
WARNING: timestamping does nothing in combination with -O. See the manual\n\
 
1073
for details.\n\n"));
 
1074
          opt.timestamping = false;
 
1075
        }
 
1076
      if (opt.noclobber && file_exists_p(opt.output_document))
 
1077
           {
 
1078
              /* Check if output file exists; if it does, exit. */
 
1079
              logprintf (LOG_VERBOSE, _("File `%s' already there; not retrieving.\n"), opt.output_document);
 
1080
              exit(1);
 
1081
           }
 
1082
    }
 
1083
 
 
1084
  if (opt.ask_passwd && opt.passwd)
 
1085
    {
 
1086
      printf (_("Cannot specify both --ask-password and --password.\n"));
 
1087
      print_usage ();
 
1088
      exit (1);
 
1089
    }
 
1090
 
 
1091
  if (!nurl && !opt.input_filename)
 
1092
    {
 
1093
      /* No URL specified.  */
 
1094
      printf (_("%s: missing URL\n"), exec_name);
 
1095
      print_usage ();
 
1096
      printf ("\n");
 
1097
      /* #### Something nicer should be printed here -- similar to the
 
1098
         pre-1.5 `--help' page.  */
 
1099
      printf (_("Try `%s --help' for more options.\n"), exec_name);
 
1100
      exit (1);
 
1101
    }
 
1102
 
 
1103
#ifdef ENABLE_IRI
 
1104
  if (opt.enable_iri)
 
1105
    {
 
1106
      if (opt.locale && !check_encoding_name (opt.locale))
 
1107
        opt.locale = NULL;
 
1108
 
 
1109
      if (!opt.locale)
 
1110
        opt.locale = find_locale ();
 
1111
 
 
1112
      if (opt.encoding_remote && !check_encoding_name (opt.encoding_remote))
 
1113
        opt.encoding_remote = NULL;
 
1114
    }
 
1115
#else
 
1116
  if (opt.enable_iri || opt.locale || opt.encoding_remote)
 
1117
    {
 
1118
      /* sXXXav : be more specific... */
 
1119
      printf(_("This version does not have support for IRIs\n"));
 
1120
      exit(1);
 
1121
    }
 
1122
#endif
 
1123
 
 
1124
  if (opt.ask_passwd)
 
1125
    {
 
1126
      opt.passwd = prompt_for_password ();
 
1127
 
 
1128
      if (opt.passwd == NULL || opt.passwd[0] == '\0')
 
1129
        exit (1);
 
1130
    }
 
1131
 
 
1132
#ifdef USE_WATT32
 
1133
  if (opt.wdebug)
 
1134
     dbug_init();
 
1135
  sock_init();
 
1136
#else
 
1137
  if (opt.background)
 
1138
    fork_to_background ();
 
1139
#endif
 
1140
 
 
1141
  /* Initialize progress.  Have to do this after the options are
 
1142
     processed so we know where the log file is.  */
 
1143
  if (opt.verbose)
 
1144
    set_progress_implementation (opt.progress_type);
 
1145
 
 
1146
  /* Fill in the arguments.  */
 
1147
  url = alloca_array (char *, nurl + 1);
 
1148
  for (i = 0; i < nurl; i++, optind++)
 
1149
    {
 
1150
      char *rewritten = rewrite_shorthand_url (argv[optind]);
 
1151
      if (rewritten)
 
1152
        url[i] = rewritten;
 
1153
      else
 
1154
        url[i] = xstrdup (argv[optind]);
 
1155
    }
 
1156
  url[i] = NULL;
 
1157
 
 
1158
  /* Initialize logging.  */
 
1159
  log_init (opt.lfilename, append_to_log);
 
1160
 
 
1161
  DEBUGP (("DEBUG output created by Wget %s on %s.\n\n",
 
1162
           version_string, OS_TYPE));
 
1163
 
 
1164
  /* Open the output filename if necessary.  */
 
1165
 
 
1166
/* 2005-04-17 SMS.
 
1167
   Note that having the output_stream ("-O") file opened here for an FTP
 
1168
   URL rather than in getftp() (ftp.c) (and the http equivalent) rather
 
1169
   limits the ability in VMS to open the file differently for ASCII
 
1170
   versus binary FTP there.  (Of course, doing it here allows a open
 
1171
   failure to be detected immediately, without first connecting to the
 
1172
   server.)
 
1173
*/
 
1174
  if (opt.output_document)
 
1175
    {
 
1176
      if (HYPHENP (opt.output_document))
 
1177
        {
 
1178
#ifdef WINDOWS
 
1179
          FILE *result;
 
1180
          result = freopen ("CONOUT$", "wb", stdout);
 
1181
          if (result == NULL)
 
1182
            {
 
1183
              logputs (LOG_NOTQUIET, _("\
 
1184
WARNING: Can't reopen standard output in binary mode;\n\
 
1185
         downloaded file may contain inappropriate line endings.\n"));
 
1186
            }
 
1187
#endif
 
1188
          output_stream = stdout;
 
1189
        }
 
1190
      else
 
1191
        {
 
1192
          struct_fstat st;
 
1193
 
 
1194
#ifdef __VMS
 
1195
/* Common fopen() optional arguments:
 
1196
   sequential access only, access callback function.
 
1197
*/
 
1198
# define FOPEN_OPT_ARGS , "fop=sqo", "acc", acc_cb, &open_id
 
1199
          int open_id = 7;
 
1200
#else /* def __VMS */
 
1201
# define FOPEN_OPT_ARGS
 
1202
#endif /* def __VMS [else] */
 
1203
 
 
1204
          output_stream = fopen (opt.output_document,
 
1205
                                 opt.always_rest ? "ab" : "wb"
 
1206
                                 FOPEN_OPT_ARGS);
 
1207
          if (output_stream == NULL)
 
1208
            {
 
1209
              perror (opt.output_document);
 
1210
              exit (1);
 
1211
            }
 
1212
          if (fstat (fileno (output_stream), &st) == 0 && S_ISREG (st.st_mode))
 
1213
            output_stream_regular = true;
 
1214
        }
 
1215
    }
 
1216
 
 
1217
#ifdef __VMS
 
1218
  /* Set global ODS5 flag according to the specified destination (if
 
1219
     any), otherwise according to the current default device.
 
1220
  */
 
1221
  if (output_stream == NULL)
 
1222
    {
 
1223
      set_ods5_dest( "SYS$DISK");
 
1224
    }
 
1225
  else if (output_stream != stdout)
 
1226
    {
 
1227
      set_ods5_dest( opt.output_document);
 
1228
    }
 
1229
#endif /* def __VMS */
 
1230
 
 
1231
#ifdef WINDOWS
 
1232
  ws_startup ();
 
1233
#endif
 
1234
 
 
1235
#ifdef SIGHUP
 
1236
  /* Setup the signal handler to redirect output when hangup is
 
1237
     received.  */
 
1238
  if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
 
1239
    signal(SIGHUP, redirect_output_signal);
 
1240
#endif
 
1241
  /* ...and do the same for SIGUSR1.  */
 
1242
#ifdef SIGUSR1
 
1243
  signal (SIGUSR1, redirect_output_signal);
 
1244
#endif
 
1245
#ifdef SIGPIPE
 
1246
  /* Writing to a closed socket normally signals SIGPIPE, and the
 
1247
     process exits.  What we want is to ignore SIGPIPE and just check
 
1248
     for the return value of write().  */
 
1249
  signal (SIGPIPE, SIG_IGN);
 
1250
#endif
 
1251
#ifdef SIGWINCH
 
1252
  signal (SIGWINCH, progress_handle_sigwinch);
 
1253
#endif
 
1254
 
 
1255
  status = RETROK;              /* initialize it, just-in-case */
 
1256
  /* Retrieve the URLs from argument list.  */
 
1257
  for (t = url; *t; t++)
 
1258
    {
 
1259
      char *filename = NULL, *redirected_URL = NULL;
 
1260
      int dt, url_err;
 
1261
      /* Need to do a new struct iri every time, because
 
1262
       * retrieve_url may modify it in some circumstances,
 
1263
       * currently. */
 
1264
      struct iri *iri = iri_new ();
 
1265
      struct url *url_parsed;
 
1266
 
 
1267
      set_uri_encoding (iri, opt.locale, true);
 
1268
      url_parsed = url_parse (*t, &url_err, iri, true);
 
1269
 
 
1270
      if (!url_parsed)
 
1271
        {
 
1272
          char *error = url_error (*t, url_err);
 
1273
          logprintf (LOG_NOTQUIET, "%s: %s.\n",*t, error);
 
1274
          xfree (error);
 
1275
          status = URLERROR;
 
1276
        }
 
1277
      else
 
1278
        {
 
1279
          if ((opt.recursive || opt.page_requisites)
 
1280
              && (url_scheme (*t) != SCHEME_FTP || url_uses_proxy (url_parsed)))
 
1281
            {
 
1282
              int old_follow_ftp = opt.follow_ftp;
 
1283
 
 
1284
              /* Turn opt.follow_ftp on in case of recursive FTP retrieval */
 
1285
              if (url_scheme (*t) == SCHEME_FTP)
 
1286
                opt.follow_ftp = 1;
 
1287
 
 
1288
              status = retrieve_tree (url_parsed, NULL);
 
1289
 
 
1290
              opt.follow_ftp = old_follow_ftp;
 
1291
            }
 
1292
          else
 
1293
          {
 
1294
            status = retrieve_url (url_parsed, *t, &filename, &redirected_URL,
 
1295
                                   NULL, &dt, opt.recursive, iri, true);
 
1296
          }
 
1297
 
 
1298
          if (opt.delete_after && file_exists_p(filename))
 
1299
            {
 
1300
              DEBUGP (("Removing file due to --delete-after in main():\n"));
 
1301
              logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
 
1302
              if (unlink (filename))
 
1303
                logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
 
1304
            }
 
1305
          xfree_null (redirected_URL);
 
1306
          xfree_null (filename);
 
1307
          url_free (url_parsed);
 
1308
        }
 
1309
      iri_free (iri);
 
1310
    }
 
1311
 
 
1312
  /* And then from the input file, if any.  */
 
1313
  if (opt.input_filename)
 
1314
    {
 
1315
      int count;
 
1316
      status = retrieve_from_file (opt.input_filename, opt.force_html, &count);
 
1317
      if (!count)
 
1318
        logprintf (LOG_NOTQUIET, _("No URLs found in %s.\n"),
 
1319
                   opt.input_filename);
 
1320
    }
 
1321
 
 
1322
  /* Print broken links. */
 
1323
  if (opt.recursive && opt.spider)
 
1324
    {
 
1325
      print_broken_links();
 
1326
    }
 
1327
 
 
1328
  /* Print the downloaded sum.  */
 
1329
  if ((opt.recursive || opt.page_requisites
 
1330
       || nurl > 1
 
1331
       || (opt.input_filename && total_downloaded_bytes != 0))
 
1332
      &&
 
1333
      total_downloaded_bytes != 0)
 
1334
    {
 
1335
      logprintf (LOG_NOTQUIET,
 
1336
                 _("FINISHED --%s--\nDownloaded: %d files, %s in %s (%s)\n"),
 
1337
                 datetime_str (time (NULL)),
 
1338
                 numurls,
 
1339
                 human_readable (total_downloaded_bytes),
 
1340
                 secs_to_human_time (total_download_time),
 
1341
                 retr_rate (total_downloaded_bytes, total_download_time));
 
1342
      /* Print quota warning, if exceeded.  */
 
1343
      if (opt.quota && total_downloaded_bytes > opt.quota)
 
1344
        logprintf (LOG_NOTQUIET,
 
1345
                   _("Download quota of %s EXCEEDED!\n"),
 
1346
                   human_readable (opt.quota));
 
1347
    }
 
1348
 
 
1349
  if (opt.cookies_output)
 
1350
    save_cookies ();
 
1351
 
 
1352
  if (opt.convert_links && !opt.delete_after)
 
1353
    convert_all_links ();
 
1354
 
 
1355
  log_close ();
 
1356
  for (i = 0; i < nurl; i++)
 
1357
    xfree (url[i]);
 
1358
  cleanup ();
 
1359
 
 
1360
  return get_exit_status ();
 
1361
}
 
1362
#endif /* TESTING */
 
1363
 
 
1364
#if defined(SIGHUP) || defined(SIGUSR1)
 
1365
 
 
1366
/* So the signal_name check doesn't blow when only one is available. */
 
1367
#ifndef SIGHUP
 
1368
# define SIGHUP -1
 
1369
#endif
 
1370
#ifndef SIGUSR1
 
1371
# define SIGUSR1 -1
 
1372
#endif
 
1373
 
 
1374
/* Hangup signal handler.  When wget receives SIGHUP or SIGUSR1, it
 
1375
   will proceed operation as usual, trying to write into a log file.
 
1376
   If that is impossible, the output will be turned off.  */
 
1377
 
 
1378
static void
 
1379
redirect_output_signal (int sig)
 
1380
{
 
1381
  const char *signal_name = (sig == SIGHUP ? "SIGHUP" :
 
1382
                             (sig == SIGUSR1 ? "SIGUSR1" :
 
1383
                              "WTF?!"));
 
1384
  log_request_redirect_output (signal_name);
 
1385
  progress_schedule_redirect ();
 
1386
  signal (sig, redirect_output_signal);
 
1387
}
 
1388
#endif
 
1389
 
 
1390
/*
 
1391
 * vim: et ts=2 sw=2
 
1392
 */