]> sjero.net Git - wget/blobdiff - src/main.c
mass change: update copyright years.
[wget] / src / main.c
index b30fc3f2d9ab97104073deedb2282a7bfaed82b1..81277c35742b63c474937b00e43f528f68d814db 100644 (file)
@@ -1,6 +1,7 @@
 /* Command line parsing.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+   Inc.
 
 This file is part of GNU Wget.
 
@@ -32,9 +33,7 @@ as that of the covered work.  */
 
 #include <stdio.h>
 #include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
+#include <unistd.h>
 #include <string.h>
 #include <signal.h>
 #ifdef ENABLE_NLS
@@ -44,6 +43,7 @@ as that of the covered work.  */
 #include <errno.h>
 #include <time.h>
 
+#include "exits.h"
 #include "utils.h"
 #include "init.h"
 #include "retr.h"
@@ -54,11 +54,16 @@ as that of the covered work.  */
 #include "convert.h"
 #include "spider.h"
 #include "http.h"               /* for save_cookies */
+#include "ptimer.h"
 
 #include <getopt.h>
 #include <getpass.h>
 #include <quote.h>
 
+#ifdef __VMS
+#include "vms.h"
+#endif /* __VMS */
+
 #ifndef PATH_SEPARATOR
 # define PATH_SEPARATOR '/'
 #endif
@@ -71,17 +76,19 @@ extern char *compilation_string;
 extern char *system_getrc;
 extern char *link_string;
 /* defined in build_info.c */
-extern char *compiled_features[];
-extern char *system_wgetrc;
-extern char *locale_dir;
+extern const char *compiled_features[];
 /* Used for --version output in print_version */
-static const int max_chars_per_line = 72;
+#define MAX_CHARS_PER_LINE      72
+#define TABULATION              4
 
 #if defined(SIGHUP) || defined(SIGUSR1)
 static void redirect_output_signal (int);
 #endif
 
 const char *exec_name;
+
+/* Number of successfully downloaded URLs */
+int numurls = 0;
 \f
 #ifndef TESTING
 /* Initialize I18N/L10N.  That amounts to invoking setlocale, and
@@ -141,6 +148,7 @@ struct cmdline_option {
 static struct cmdline_option option_data[] =
   {
     { "accept", 'A', OPT_VALUE, "accept", -1 },
+    { "adjust-extension", 'E', OPT_BOOLEAN, "adjustextension", -1 },
     { "append-output", 'a', OPT__APPEND_OUTPUT, NULL, required_argument },
     { "ask-password", 0, OPT_BOOLEAN, "askpassword", -1 },
     { "auth-no-challenge", 0, OPT_BOOLEAN, "authnochallenge", -1 },
@@ -156,6 +164,7 @@ static struct cmdline_option option_data[] =
     { IF_SSL ("certificate-type"), 0, OPT_VALUE, "certificatetype", -1 },
     { IF_SSL ("check-certificate"), 0, OPT_BOOLEAN, "checkcertificate", -1 },
     { "clobber", 0, OPT__CLOBBER, NULL, optional_argument },
+    { "config", 0, OPT_VALUE, "chooseconfig", -1 },
     { "connect-timeout", 0, OPT_VALUE, "connecttimeout", -1 },
     { "continue", 'c', OPT_BOOLEAN, "continue", -1 },
     { "convert-links", 'k', OPT_BOOLEAN, "convertlinks", -1 },
@@ -171,7 +180,7 @@ static struct cmdline_option option_data[] =
     { "dns-timeout", 0, OPT_VALUE, "dnstimeout", -1 },
     { "domains", 'D', OPT_VALUE, "domains", -1 },
     { "dont-remove-listing", 0, OPT__DONT_REMOVE_LISTING, NULL, no_argument },
-    { "dot-style", 0, OPT_VALUE, "dotstyle", -1 },
+    { "dot-style", 0, OPT_VALUE, "dotstyle", -1 }, /* deprecated */
     { "egd-file", 0, OPT_VALUE, "egdfile", -1 },
     { "exclude-directories", 'X', OPT_VALUE, "excludedirectories", -1 },
     { "exclude-domains", 0, OPT_VALUE, "excludedomains", -1 },
@@ -181,12 +190,15 @@ static struct cmdline_option option_data[] =
     { "force-directories", 'x', OPT_BOOLEAN, "dirstruct", -1 },
     { "force-html", 'F', OPT_BOOLEAN, "forcehtml", -1 },
     { "ftp-password", 0, OPT_VALUE, "ftppassword", -1 },
+#ifdef __VMS
+    { "ftp-stmlf", 0, OPT_BOOLEAN, "ftpstmlf", -1 },
+#endif /* def __VMS */
     { "ftp-user", 0, OPT_VALUE, "ftpuser", -1 },
     { "glob", 0, OPT_BOOLEAN, "glob", -1 },
     { "header", 0, OPT_VALUE, "header", -1 },
     { "help", 'h', OPT_FUNCALL, (void *)print_help, no_argument },
     { "host-directories", 0, OPT_BOOLEAN, "addhostdir", -1 },
-    { "html-extension", 'E', OPT_BOOLEAN, "htmlextension", -1 },
+    { "html-extension", 'E', OPT_BOOLEAN, "adjustextension", -1 }, /* deprecated */
     { "htmlify", 0, OPT_BOOLEAN, "htmlify", -1 },
     { "http-keep-alive", 0, OPT_BOOLEAN, "httpkeepalive", -1 },
     { "http-passwd", 0, OPT_VALUE, "httppassword", -1 }, /* deprecated */
@@ -201,10 +213,12 @@ static struct cmdline_option option_data[] =
     { "inet6-only", '6', OPT_BOOLEAN, "inet6only", -1 },
 #endif
     { "input-file", 'i', OPT_VALUE, "input", -1 },
+    { "iri", 0, OPT_BOOLEAN, "iri", -1 },
     { "keep-session-cookies", 0, OPT_BOOLEAN, "keepsessioncookies", -1 },
     { "level", 'l', OPT_VALUE, "reclevel", -1 },
     { "limit-rate", 0, OPT_VALUE, "limitrate", -1 },
     { "load-cookies", 0, OPT_VALUE, "loadcookies", -1 },
+    { "local-encoding", 0, OPT_VALUE, "localencoding", -1 },
     { "max-redirect", 0, OPT_VALUE, "maxredirect", -1 },
     { "mirror", 'm', OPT_BOOLEAN, "mirror", -1 },
     { "no", 'n', OPT__NO, NULL, required_argument },
@@ -219,7 +233,7 @@ static struct cmdline_option option_data[] =
     { "post-data", 0, OPT_VALUE, "postdata", -1 },
     { "post-file", 0, OPT_VALUE, "postfile", -1 },
     { "prefer-family", 0, OPT_VALUE, "preferfamily", -1 },
-    { "preserve-permissions", 0, OPT_BOOLEAN, "preservepermissions", -1 },
+    { "preserve-permissions", 0, OPT_BOOLEAN, "preservepermissions", -1 }, /* deprecated */
     { IF_SSL ("private-key"), 0, OPT_VALUE, "privatekey", -1 },
     { IF_SSL ("private-key-type"), 0, OPT_VALUE, "privatekeytype", -1 },
     { "progress", 0, OPT_VALUE, "progress", -1 },
@@ -238,6 +252,7 @@ static struct cmdline_option option_data[] =
     { "referer", 0, OPT_VALUE, "referer", -1 },
     { "reject", 'R', OPT_VALUE, "reject", -1 },
     { "relative", 'L', OPT_BOOLEAN, "relativeonly", -1 },
+    { "remote-encoding", 0, OPT_VALUE, "remoteencoding", -1 },
     { "remove-listing", 0, OPT_BOOLEAN, "removelisting", -1 },
     { "restrict-file-names", 0, OPT_BOOLEAN, "restrictfilenames", -1 },
     { "retr-symlinks", 0, OPT_BOOLEAN, "retrsymlinks", -1 },
@@ -252,6 +267,9 @@ static struct cmdline_option option_data[] =
     { "timeout", 'T', OPT_VALUE, "timeout", -1 },
     { "timestamping", 'N', OPT_BOOLEAN, "timestamping", -1 },
     { "tries", 't', OPT_VALUE, "tries", -1 },
+    { "unlink", 0, OPT_BOOLEAN, "unlink", -1 },
+    { "trust-server-names", 0, OPT_BOOLEAN, "trustservernames", -1 },
+    { "use-server-timestamps", 0, OPT_BOOLEAN, "useservertimestamps", -1 },
     { "user", 0, OPT_VALUE, "user", -1 },
     { "user-agent", 'U', OPT_VALUE, "useragent", -1 },
     { "verbose", 'v', OPT_BOOLEAN, "verbose", -1 },
@@ -259,7 +277,7 @@ static struct cmdline_option option_data[] =
     { "version", 'V', OPT_FUNCALL, (void *) print_version, no_argument },
     { "wait", 'w', OPT_VALUE, "wait", -1 },
     { "waitretry", 0, OPT_VALUE, "waitretry", -1 },
-#ifdef MSDOS
+#ifdef USE_WATT32
     { "wdebug", 0, OPT_BOOLEAN, "wdebug", -1 },
 #endif
   };
@@ -367,9 +385,10 @@ init_switches (void)
 
 /* Print the usage message.  */
 static void
-print_usage (void)
+print_usage (int error)
 {
-  printf (_("Usage: %s [OPTION]... [URL]...\n"), exec_name);
+  fprintf (error ? stderr : stdout, _("Usage: %s [OPTION]... [URL]...\n"),
+           exec_name);
 }
 
 /* Print the help message, describing all the available options.  If
@@ -405,7 +424,7 @@ Logging and input file:\n"),
     N_("\
   -d,  --debug               print lots of debugging information.\n"),
 #endif
-#ifdef MSDOS
+#ifdef USE_WATT32
     N_("\
        --wdebug              print Watt-32 debug output.\n"),
 #endif
@@ -420,7 +439,10 @@ Logging and input file:\n"),
     N_("\
   -F,  --force-html          treat input file as HTML.\n"),
     N_("\
-  -B,  --base=URL            prepends URL to relative links in -F -i file.\n"),
+  -B,  --base=URL            resolves HTML input-file links (-i -F)\n\
+                             relative to URL.\n"),
+    N_("\
+       --config=FILE         Specify config file to use.\n"), 
     "\n",
 
     N_("\
@@ -433,7 +455,7 @@ Download:\n"),
   -O,  --output-document=FILE    write documents to FILE.\n"),
     N_("\
   -nc, --no-clobber              skip downloads that would download to\n\
-                                 existing files.\n"),
+                                 existing files (overwriting them).\n"),
     N_("\
   -c,  --continue                resume getting a partially-downloaded file.\n"),
     N_("\
@@ -442,6 +464,9 @@ Download:\n"),
   -N,  --timestamping            don't re-retrieve files unless newer than\n\
                                  local.\n"),
     N_("\
+  --no-use-server-timestamps     don't set the local file's timestamp by\n\
+                                 the one on the server.\n"),
+    N_("\
   -S,  --server-response         print server response.\n"),
     N_("\
        --spider                  don't download anything.\n"),
@@ -458,7 +483,7 @@ Download:\n"),
     N_("\
        --waitretry=SECONDS       wait 1..SECONDS between retries of a retrieval.\n"),
     N_("\
-       --random-wait             wait from 0...2*WAIT secs between retrievals.\n"),
+       --random-wait             wait from 0.5*WAIT...1.5*WAIT secs between retrievals.\n"),
     N_("\
        --no-proxy                explicitly turn off proxy.\n"),
     N_("\
@@ -488,6 +513,14 @@ Download:\n"),
        --password=PASS           set both ftp and http password to PASS.\n"),
     N_("\
        --ask-password            prompt for passwords.\n"),
+    N_("\
+       --no-iri                  turn off IRI support.\n"),
+    N_("\
+       --local-encoding=ENC      use ENC as the local encoding for IRIs.\n"),
+    N_("\
+       --remote-encoding=ENC     use ENC as the default remote encoding.\n"),
+    N_("\
+       --unlink                  remove file before clobber.\n"),
     "\n",
 
     N_("\
@@ -518,7 +551,7 @@ HTTP options:\n"),
        --default-page=NAME     Change the default page name (normally\n\
                                this is `index.html'.).\n"),
     N_("\
-  -E,  --html-extension        save HTML documents with `.html' extension.\n"),
+  -E,  --adjust-extension      save HTML/CSS documents with proper extensions.\n"),
     N_("\
        --ignore-length         ignore `Content-Length' header field.\n"),
     N_("\
@@ -553,7 +586,7 @@ HTTP options:\n"),
        --content-disposition   honor the Content-Disposition header when\n\
                                choosing local file names (EXPERIMENTAL).\n"),
     N_("\
-       --auth-no-challenge     Send Basic HTTP authentication information\n\
+       --auth-no-challenge     send Basic HTTP authentication information\n\
                                without first waiting for the server's\n\
                                challenge.\n"),
     "\n",
@@ -587,6 +620,10 @@ HTTPS (SSL/TLS) options:\n"),
 
     N_("\
 FTP options:\n"),
+#ifdef __VMS
+    N_("\
+       --ftp-stmlf             Use Stream_LF format for all binary FTP files.\n"),
+#endif /* def __VMS */
     N_("\
        --ftp-user=USER         set ftp user to USER.\n"),
     N_("\
@@ -599,8 +636,6 @@ FTP options:\n"),
        --no-passive-ftp        disable the \"passive\" transfer mode.\n"),
     N_("\
        --retr-symlinks         when recursing, get linked-to files (not dir).\n"),
-    N_("\
-       --preserve-permissions  preserve remote file permissions.\n"),
     "\n",
 
     N_("\
@@ -614,8 +649,13 @@ Recursive download:\n"),
     N_("\
   -k,  --convert-links      make links in downloaded HTML or CSS point to\n\
                             local files.\n"),
+#ifdef __VMS
+    N_("\
+  -K,  --backup-converted   before converting file X, back up as X_orig.\n"),
+#else /* def __VMS */
     N_("\
   -K,  --backup-converted   before converting file X, back up as X.orig.\n"),
+#endif /* def __VMS [else] */
     N_("\
   -m,  --mirror             shortcut for -N -r -l inf --no-remove-listing.\n"),
     N_("\
@@ -647,6 +687,9 @@ Recursive accept/reject:\n"),
     N_("\
   -I,  --include-directories=LIST  list of allowed directories.\n"),
     N_("\
+  --trust-server-names             use the name specified by the redirection\n\
+                                   url last component.\n"),
+    N_("\
   -X,  --exclude-directories=LIST  list of excluded directories.\n"),
     N_("\
   -np, --no-parent                 don't ascend to the parent directory.\n"),
@@ -659,7 +702,7 @@ Recursive accept/reject:\n"),
 
   printf (_("GNU Wget %s, a non-interactive network retriever.\n"),
           version_string);
-  print_usage ();
+  print_usage (0);
 
   for (i = 0; i < countof (help); i++)
     fputs (_(help[i]), stdout);
@@ -708,110 +751,109 @@ prompt_for_password (void)
    and an appropriate number of spaces are added on subsequent
    lines.*/
 static void
-format_and_print_line (char* prefix, char* line,
-                      int line_length) 
+format_and_print_line (const char *prefix, const char *line,
+                       int line_length)
 {
+  int remaining_chars;
+  char *line_dup, *token;
+
   assert (prefix != NULL);
   assert (line != NULL);
 
+  line_dup = xstrdup (line);
+
   if (line_length <= 0)
-    line_length = max_chars_per_line;
+    line_length = MAX_CHARS_PER_LINE - TABULATION;
 
-  const int leading_spaces = strlen (prefix);
   printf ("%s", prefix);
-  int remaining_chars = line_length - leading_spaces;
+  remaining_chars = line_length;
   /* We break on spaces. */
-  char* token = strtok (line, " ");
-  while (token != NULL) 
+  token = strtok (line_dup, " ");
+  while (token != NULL)
     {
       /* If however a token is much larger than the maximum
          line length, all bets are off and we simply print the
          token on the next line. */
-      if (remaining_chars <= strlen (token)) 
+      if (remaining_chars <= strlen (token))
         {
-          printf ("\n");
-          int j = 0;
-          for (j = 0; j < leading_spaces; j++) 
-            {
-              printf (" ");
-            }
-          remaining_chars = line_length - leading_spaces;
+          printf ("\n%*c", TABULATION, ' ');
+          remaining_chars = line_length - TABULATION;
         }
       printf ("%s ", token);
-      remaining_chars -= strlen (token) + 1;  // account for " "
+      remaining_chars -= strlen (token) + 1;  /* account for " " */
       token = strtok (NULL, " ");
     }
 
   printf ("\n");
-  xfree (prefix);
-  xfree (line);
+
+  xfree (line_dup);
 }
 
 static void
 print_version (void)
 {
-  const char *options_title = "Options    : ";
-  const char *wgetrc_title  = "Wgetrc     : ";
-  const char *locale_title  = "Locale     : ";
-  const char *compile_title = "Compile    : ";
-  const char *link_title    = "Link       : ";
-  const char *prefix_spaces = "             ";
-  const int prefix_space_length = strlen (prefix_spaces);
-
-  printf ("GNU Wget %s\n", version_string);
-  printf (options_title);
-  /* compiled_features is a char*[]. We limit the characters per
-     line to max_chars_per_line and prefix each line with a constant
-     number of spaces for proper alignment. */
-  int i =0;
-  for (i = 0; compiled_features[i] != NULL; ) 
+  const char *wgetrc_title  = _("Wgetrc: ");
+  const char *locale_title  = _("Locale: ");
+  const char *compile_title = _("Compile: ");
+  const char *link_title    = _("Link: ");
+  char *env_wgetrc, *user_wgetrc;
+  int i;
+
+  printf (_("GNU Wget %s built on %s.\n\n"), version_string, OS_TYPE);
+
+  for (i = 0; compiled_features[i] != NULL; )
     {
-      int line_length = max_chars_per_line - prefix_space_length;
-      while ((line_length > 0) && (compiled_features[i] != NULL)) 
+      int line_length = MAX_CHARS_PER_LINE;
+      while ((line_length > 0) && (compiled_features[i] != NULL))
         {
           printf ("%s ", compiled_features[i]);
           line_length -= strlen (compiled_features[i]) + 2;
           i++;
         }
       printf ("\n");
-      if (compiled_features[i] != NULL) 
-        {
-         printf (prefix_spaces);
-        }
     }
-  /* Handle the case when $WGETRC is unset and $HOME/.wgetrc is 
+  printf ("\n");
+
+  /* Handle the case when $WGETRC is unset and $HOME/.wgetrc is
      absent. */
-  printf (wgetrc_title);
-  char *env_wgetrc = wgetrc_env_file_name ();
-  if (env_wgetrc && *env_wgetrc) 
+  printf ("%s\n", wgetrc_title);
+  env_wgetrc = wgetrc_env_file_name ();
+  if (env_wgetrc && *env_wgetrc)
     {
-      printf ("%s (env)\n%s", env_wgetrc, prefix_spaces);
+      printf (_("    %s (env)\n"), env_wgetrc);
       xfree (env_wgetrc);
     }
-  char *user_wgetrc = wgetrc_user_file_name ();
-  if (user_wgetrc) 
+  user_wgetrc = wgetrc_user_file_name ();
+  if (user_wgetrc)
     {
-      printf ("%s (user)\n%s", user_wgetrc, prefix_spaces);
+      printf (_("    %s (user)\n"), user_wgetrc);
       xfree (user_wgetrc);
     }
-  printf ("%s (system)\n", system_wgetrc);
-
-  format_and_print_line (strdup (locale_title),
-                        strdup (locale_dir), 
-                        max_chars_per_line);
-  
-  format_and_print_line (strdup (compile_title),
-                        strdup (compilation_string),
-                        max_chars_per_line);
-
-  format_and_print_line (strdup (link_title),
-                        strdup (link_string),
-                        max_chars_per_line);
+#ifdef SYSTEM_WGETRC
+  printf (_("    %s (system)\n"), SYSTEM_WGETRC);
+#endif
+
+#ifdef ENABLE_NLS
+  format_and_print_line (locale_title,
+                        LOCALEDIR,
+                        MAX_CHARS_PER_LINE);
+#endif /* def ENABLE_NLS */
+
+  if (compilation_string != NULL)
+    format_and_print_line (compile_title,
+                           compilation_string,
+                           MAX_CHARS_PER_LINE);
+
+  if (link_string != NULL)
+    format_and_print_line (link_title,
+                           link_string,
+                           MAX_CHARS_PER_LINE);
+
   printf ("\n");
   /* TRANSLATORS: When available, an actual copyright character
      (cirle-c) should be used in preference to "(C)". */
   fputs (_("\
-Copyright (C) 2008 Free Software Foundation, Inc.\n"), stdout);
+Copyright (C) 2009 Free Software Foundation, Inc.\n"), stdout);
   fputs (_("\
 License GPLv3+: GNU GPL version 3 or later\n\
 <http://www.gnu.org/licenses/gpl.html>.\n\
@@ -821,7 +863,7 @@ There is NO WARRANTY, to the extent permitted by law.\n"), stdout);
      names such as this one. See en_US.po for reference. */
   fputs (_("\nOriginally written by Hrvoje Niksic <hniksic@xemacs.org>.\n"),
          stdout);
-  fputs (_("Currently maintained by Micah Cowan <micah@cowan.name>.\n"),
+  fputs (_("Please send bug reports and questions to <bug-wget@gnu.org>.\n"),
          stdout);
   exit (0);
 }
@@ -833,29 +875,75 @@ main (int argc, char **argv)
 {
   char **url, **t;
   int i, ret, longindex;
-  int nurl, status;
+  int nurl;
   bool append_to_log = false;
 
+  total_downloaded_bytes = 0;
+
   program_name = argv[0];
 
+  struct ptimer *timer = ptimer_new ();
+  double start_time = ptimer_measure (timer);
+
   i18n_initialize ();
 
   /* Construct the name of the executable, without the directory part.  */
+#ifdef __VMS
+  /* On VMS, lose the "dev:[dir]" prefix and the ".EXE;nnn" suffix. */
+  exec_name = vms_basename (argv[0]);
+#else /* def __VMS */
   exec_name = strrchr (argv[0], PATH_SEPARATOR);
   if (!exec_name)
     exec_name = argv[0];
   else
     ++exec_name;
+#endif /* def __VMS [else] */
 
 #ifdef WINDOWS
   /* Drop extension (typically .EXE) from executable filename. */
   windows_main ((char **) &exec_name);
 #endif
 
-  /* Set option defaults; read the system wgetrc and ~/.wgetrc.  */
-  initialize ();
+  /* Load the hard-coded defaults.  */
+  defaults ();
 
   init_switches ();
+
+  /* This seperate getopt_long is needed to find the user config
+     and parse it before the other user options. */
+  longindex = -1;
+  int retconf;
+  bool use_userconfig = false;
+
+  while ((retconf = getopt_long (argc, argv,
+                                short_options, long_options, &longindex)) != -1)
+    {
+      int confval;
+      bool userrc_ret = true;
+      struct cmdline_option *config_opt;
+      confval = long_options[longindex].val;
+      config_opt = &option_data[confval & ~BOOLEAN_NEG_MARKER];
+      if (strcmp (config_opt->long_name, "config") == 0)
+        {
+          userrc_ret &= run_wgetrc (optarg);
+          use_userconfig = true;
+        }
+      if (!userrc_ret)
+        {
+          printf ("Exiting due to error in %s\n", optarg);
+          exit (2);
+        }
+      else
+        break;
+    }
+
+  /* If the user did not specify a config, read the system wgetrc and ~/.wgetrc. */
+  if (use_userconfig == false)
+    initialize ();
+
+  opterr = 0;
+  optind = 0;
+
   longindex = -1;
   while ((ret = getopt_long (argc, argv,
                              short_options, long_options, &longindex)) != -1)
@@ -869,7 +957,7 @@ main (int argc, char **argv)
         {
           if (ret == '?')
             {
-              print_usage ();
+              print_usage (0);
               printf ("\n");
               printf (_("Try `%s --help' for more options.\n"), exec_name);
               exit (2);
@@ -918,7 +1006,7 @@ main (int argc, char **argv)
                short options for convenience and backward
                compatibility.  */
             char *p;
-            for (p = optarg; *p; p++)
+            for (p = optarg; p && *p; p++)
               switch (*p)
                 {
                 case 'v':
@@ -937,10 +1025,12 @@ main (int argc, char **argv)
                   setoptval ("noparent", "1", opt->long_name);
                   break;
                 default:
-                  printf (_("%s: illegal option -- `-n%c'\n"), exec_name, *p);
-                  print_usage ();
-                  printf ("\n");
-                  printf (_("Try `%s --help' for more options.\n"), exec_name);
+                  fprintf (stderr, _("%s: illegal option -- `-n%c'\n"),
+                           exec_name, *p);
+                  print_usage (1);
+                  fprintf (stderr, "\n");
+                  fprintf (stderr, _("Try `%s --help' for more options.\n"),
+                           exec_name);
                   exit (1);
                 }
             break;
@@ -973,6 +1063,14 @@ main (int argc, char **argv)
   /* All user options have now been processed, so it's now safe to do
      interoption dependency checks. */
 
+  if (opt.noclobber && opt.convert_links)
+    {
+      fprintf (stderr,
+               _("Both --no-clobber and --convert-links were specified,"
+                 "only --convert-links will be used.\n"));
+      opt.noclobber = false;
+    }
+
   if (opt.reclevel == 0)
       opt.reclevel = INFINITE_RECURSION; /* see recur.h for commentary */
 
@@ -995,34 +1093,35 @@ main (int argc, char **argv)
   /* Sanity checks.  */
   if (opt.verbose && opt.quiet)
     {
-      printf (_("Can't be verbose and quiet at the same time.\n"));
-      print_usage ();
+      fprintf (stderr, _("Can't be verbose and quiet at the same time.\n"));
+      print_usage (1);
       exit (1);
     }
   if (opt.timestamping && opt.noclobber)
     {
-      printf (_("\
+      fprintf (stderr, _("\
 Can't timestamp and not clobber old files at the same time.\n"));
-      print_usage ();
+      print_usage (1);
       exit (1);
     }
 #ifdef ENABLE_IPV6
   if (opt.ipv4_only && opt.ipv6_only)
     {
-      printf (_("Cannot specify both --inet4-only and --inet6-only.\n"));
-      print_usage ();
+      fprintf (stderr,
+               _("Cannot specify both --inet4-only and --inet6-only.\n"));
+      print_usage (1);
       exit (1);
     }
 #endif
   if (opt.output_document)
     {
-      if (opt.convert_links 
+      if (opt.convert_links
           && (nurl > 1 || opt.page_requisites || opt.recursive))
         {
           fputs (_("\
 Cannot specify both -k and -O if multiple URLs are given, or in combination\n\
-with -p or -r. See the manual for details.\n\n"), stdout);
-          print_usage ();
+with -p or -r. See the manual for details.\n\n"), stderr);
+          print_usage (1);
           exit (1);
         }
       if (opt.page_requisites
@@ -1039,33 +1138,57 @@ WARNING: timestamping does nothing in combination with -O. See the manual\n\
 for details.\n\n"));
           opt.timestamping = false;
         }
-      if (opt.noclobber && file_exists_p(opt.output_document)) 
-           { 
+      if (opt.noclobber && file_exists_p(opt.output_document))
+           {
               /* Check if output file exists; if it does, exit. */
-              logprintf (LOG_VERBOSE, _("File `%s' already there; not retrieving.\n"), opt.output_document);
+              logprintf (LOG_VERBOSE,
+                         _("File `%s' already there; not retrieving.\n"),
+                         opt.output_document);
               exit(1);
-           }  
+           }
     }
 
   if (opt.ask_passwd && opt.passwd)
     {
-      printf (_("Cannot specify both --ask-password and --password.\n"));
-      print_usage ();
+      fprintf (stderr,
+               _("Cannot specify both --ask-password and --password.\n"));
+      print_usage (1);
       exit (1);
     }
 
   if (!nurl && !opt.input_filename)
     {
       /* No URL specified.  */
-      printf (_("%s: missing URL\n"), exec_name);
-      print_usage ();
+      fprintf (stderr, _("%s: missing URL\n"), exec_name);
+      print_usage (1);
       printf ("\n");
       /* #### Something nicer should be printed here -- similar to the
          pre-1.5 `--help' page.  */
-      printf (_("Try `%s --help' for more options.\n"), exec_name);
+      fprintf (stderr, _("Try `%s --help' for more options.\n"), exec_name);
       exit (1);
     }
 
+#ifdef ENABLE_IRI
+  if (opt.enable_iri)
+    {
+      if (opt.locale && !check_encoding_name (opt.locale))
+        opt.locale = NULL;
+
+      if (!opt.locale)
+        opt.locale = find_locale ();
+
+      if (opt.encoding_remote && !check_encoding_name (opt.encoding_remote))
+        opt.encoding_remote = NULL;
+    }
+#else
+  if (opt.enable_iri || opt.locale || opt.encoding_remote)
+    {
+      /* sXXXav : be more specific... */
+      fprintf (stderr, _("This version does not have support for IRIs\n"));
+      exit(1);
+    }
+#endif
+
   if (opt.ask_passwd)
     {
       opt.passwd = prompt_for_password ();
@@ -1074,7 +1197,7 @@ for details.\n\n"));
         exit (1);
     }
 
-#ifdef MSDOS
+#ifdef USE_WATT32
   if (opt.wdebug)
      dbug_init();
   sock_init();
@@ -1103,17 +1226,26 @@ for details.\n\n"));
   /* Initialize logging.  */
   log_init (opt.lfilename, append_to_log);
 
-  DEBUGP (("DEBUG output created by Wget %s on %s.\n\n", version_string,
-           OS_TYPE));
+  DEBUGP (("DEBUG output created by Wget %s on %s.\n\n",
+           version_string, OS_TYPE));
 
   /* Open the output filename if necessary.  */
+
+/* 2005-04-17 SMS.
+   Note that having the output_stream ("-O") file opened here for an FTP
+   URL rather than in getftp() (ftp.c) (and the http equivalent) rather
+   limits the ability in VMS to open the file differently for ASCII
+   versus binary FTP there.  (Of course, doing it here allows a open
+   failure to be detected immediately, without first connecting to the
+   server.)
+*/
   if (opt.output_document)
     {
       if (HYPHENP (opt.output_document))
         {
 #ifdef WINDOWS
           FILE *result;
-          result = freopen (NULL, "wb", stdout);
+          result = freopen ("CONOUT$", "wb", stdout);
           if (result == NULL)
             {
               logputs (LOG_NOTQUIET, _("\
@@ -1126,8 +1258,20 @@ WARNING: Can't reopen standard output in binary mode;\n\
       else
         {
           struct_fstat st;
+
+#ifdef __VMS
+/* Common fopen() optional arguments:
+   sequential access only, access callback function.
+*/
+# define FOPEN_OPT_ARGS , "fop=sqo", "acc", acc_cb, &open_id
+          int open_id = 7;
+#else /* def __VMS */
+# define FOPEN_OPT_ARGS
+#endif /* def __VMS [else] */
+
           output_stream = fopen (opt.output_document,
-                                 opt.always_rest ? "ab" : "wb");
+                                 opt.always_rest ? "ab" : "wb"
+                                 FOPEN_OPT_ARGS);
           if (output_stream == NULL)
             {
               perror (opt.output_document);
@@ -1136,8 +1280,25 @@ WARNING: Can't reopen standard output in binary mode;\n\
           if (fstat (fileno (output_stream), &st) == 0 && S_ISREG (st.st_mode))
             output_stream_regular = true;
         }
+      if (!output_stream_regular && opt.convert_links)
+        {
+          fprintf (stderr, _("-k can be used together with -O only if \
+outputting to a regular file.\n"));
+          print_usage (1);
+          exit(1);
+        }
     }
 
+#ifdef __VMS
+  /* Set global ODS5 flag according to the specified destination (if
+     any), otherwise according to the current default device.
+  */
+  if (output_stream == NULL)
+    set_ods5_dest( "SYS$DISK");
+  else if (output_stream != stdout)
+    set_ods5_dest( opt.output_document);
+#endif /* def __VMS */
+
 #ifdef WINDOWS
   ws_startup ();
 #endif
@@ -1162,46 +1323,66 @@ WARNING: Can't reopen standard output in binary mode;\n\
   signal (SIGWINCH, progress_handle_sigwinch);
 #endif
 
-  status = RETROK;              /* initialize it, just-in-case */
   /* Retrieve the URLs from argument list.  */
   for (t = url; *t; t++)
     {
       char *filename = NULL, *redirected_URL = NULL;
-      int dt;
-
-      if ((opt.recursive || opt.page_requisites)
-          && (url_scheme (*t) != SCHEME_FTP || url_uses_proxy (*t)))
-        {
-          int old_follow_ftp = opt.follow_ftp;
+      int dt, url_err;
+      /* Need to do a new struct iri every time, because
+       * retrieve_url may modify it in some circumstances,
+       * currently. */
+      struct iri *iri = iri_new ();
+      struct url *url_parsed;
 
-          /* Turn opt.follow_ftp on in case of recursive FTP retrieval */
-          if (url_scheme (*t) == SCHEME_FTP) 
-            opt.follow_ftp = 1;
-          
-          status = retrieve_tree (*t);
+      set_uri_encoding (iri, opt.locale, true);
+      url_parsed = url_parse (*t, &url_err, iri, true);
 
-          opt.follow_ftp = old_follow_ftp;
+      if (!url_parsed)
+        {
+          char *error = url_error (*t, url_err);
+          logprintf (LOG_NOTQUIET, "%s: %s.\n",*t, error);
+          xfree (error);
         }
       else
-        status = retrieve_url (*t, &filename, &redirected_URL, NULL, &dt, opt.recursive);
-
-      if (opt.delete_after && file_exists_p(filename))
         {
-          DEBUGP (("Removing file due to --delete-after in main():\n"));
-          logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
-          if (unlink (filename))
-            logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
-        }
+          if ((opt.recursive || opt.page_requisites)
+              && (url_scheme (*t) != SCHEME_FTP || url_uses_proxy (url_parsed)))
+            {
+              int old_follow_ftp = opt.follow_ftp;
+
+              /* Turn opt.follow_ftp on in case of recursive FTP retrieval */
+              if (url_scheme (*t) == SCHEME_FTP)
+                opt.follow_ftp = 1;
 
-      xfree_null (redirected_URL);
-      xfree_null (filename);
+              retrieve_tree (url_parsed, NULL);
+
+              opt.follow_ftp = old_follow_ftp;
+            }
+          else
+          {
+            retrieve_url (url_parsed, *t, &filename, &redirected_URL, NULL,
+                          &dt, opt.recursive, iri, true);
+          }
+
+          if (opt.delete_after && file_exists_p(filename))
+            {
+              DEBUGP (("Removing file due to --delete-after in main():\n"));
+              logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
+              if (unlink (filename))
+                logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
+            }
+          xfree_null (redirected_URL);
+          xfree_null (filename);
+          url_free (url_parsed);
+        }
+      iri_free (iri);
     }
 
   /* And then from the input file, if any.  */
   if (opt.input_filename)
     {
       int count;
-      status = retrieve_from_file (opt.input_filename, opt.force_html, &count);
+      retrieve_from_file (opt.input_filename, opt.force_html, &count);
       if (!count)
         logprintf (LOG_NOTQUIET, _("No URLs found in %s.\n"),
                    opt.input_filename);
@@ -1209,10 +1390,8 @@ WARNING: Can't reopen standard output in binary mode;\n\
 
   /* Print broken links. */
   if (opt.recursive && opt.spider)
-    {
-      print_broken_links();
-    }
-  
+    print_broken_links ();
+
   /* Print the downloaded sum.  */
   if ((opt.recursive || opt.page_requisites
        || nurl > 1
@@ -1220,13 +1399,23 @@ WARNING: Can't reopen standard output in binary mode;\n\
       &&
       total_downloaded_bytes != 0)
     {
+      double end_time = ptimer_measure (timer);
+      ptimer_destroy (timer);
+
+      char *wall_time = xstrdup (secs_to_human_time (end_time - start_time));
+      char *download_time = xstrdup (secs_to_human_time (total_download_time));
       logprintf (LOG_NOTQUIET,
-                 _("FINISHED --%s--\nDownloaded: %d files, %s in %s (%s)\n"),
-                 datetime_str (time (NULL)),
-                 opt.numurls,
-                 human_readable (total_downloaded_bytes),
-                 secs_to_human_time (total_download_time),
-                 retr_rate (total_downloaded_bytes, total_download_time));
+                _("FINISHED --%s--\nTotal wall clock time: %s\n"
+                  "Downloaded: %d files, %s in %s (%s)\n"),
+                datetime_str (time (NULL)),
+                wall_time,
+                numurls,
+                human_readable (total_downloaded_bytes),
+                download_time,
+                retr_rate (total_downloaded_bytes, total_download_time));
+      xfree (wall_time);
+      xfree (download_time);
+
       /* Print quota warning, if exceeded.  */
       if (opt.quota && total_downloaded_bytes > opt.quota)
         logprintf (LOG_NOTQUIET,
@@ -1245,10 +1434,7 @@ WARNING: Can't reopen standard output in binary mode;\n\
     xfree (url[i]);
   cleanup ();
 
-  if (status == RETROK)
-    return 0;
-  else
-    return 1;
+  return get_exit_status ();
 }
 #endif /* TESTING */
 \f