]> sjero.net Git - wget/blobdiff - src/init.c
[svn] Added reordering of addresses to try IPv4 first and the associated
[wget] / src / init.c
index 6ece81cd80f5e44a8c5118a2a720ba48ed529f04..8ab1bec3bfd43eed6d4ed7ffe0b96ed9c2c9747a 100644 (file)
@@ -1,6 +1,5 @@
 /* Reading/parsing the initialization file.
-   Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2003
-   Free Software Foundation, Inc.
+   Copyright (C) 2005 Free Software Foundation, Inc.
 
 This file is part of GNU Wget.
 
@@ -53,16 +52,15 @@ so, delete this exception statement from your version.  */
 #include "init.h"
 #include "host.h"
 #include "netrc.h"
-#include "cookies.h"           /* for cookie_jar_delete */
 #include "progress.h"
 #include "recur.h"             /* for INFINITE_RECURSION */
+#include "convert.h"           /* for convert_cleanup */
+#include "res.h"               /* for res_cleanup */
 
 #ifndef errno
 extern int errno;
 #endif
 
-extern struct cookie_jar *wget_cookie_jar;
-
 /* We want tilde expansion enabled only when reading `.wgetrc' lines;
    otherwise, it will be performed by the shell.  This variable will
    be set by the wgetrc-reading function.  */
@@ -90,6 +88,7 @@ CMD_DECLARE (cmd_spec_dirstruct);
 CMD_DECLARE (cmd_spec_header);
 CMD_DECLARE (cmd_spec_htmlify);
 CMD_DECLARE (cmd_spec_mirror);
+CMD_DECLARE (cmd_spec_prefer_family);
 CMD_DECLARE (cmd_spec_progress);
 CMD_DECLARE (cmd_spec_recursive);
 CMD_DECLARE (cmd_spec_restrict_file_names);
@@ -104,7 +103,7 @@ CMD_DECLARE (cmd_spec_useragent);
    cleanup() function below. */
 
 static struct {
-  char *name;
+  const char *name;
   void *closure;
   int (*action) PARAMS ((const char *, const char *, void *));
 } commands[] = {
@@ -143,6 +142,7 @@ static struct {
   { "followftp",       &opt.follow_ftp,        cmd_boolean },
   { "followtags",      &opt.follow_tags,       cmd_vector },
   { "forcehtml",       &opt.force_html,        cmd_boolean },
+  { "ftppasswd",       &opt.ftp_pass,          cmd_string },
   { "ftpproxy",                &opt.ftp_proxy,         cmd_string },
   { "glob",            &opt.ftp_glob,          cmd_boolean },
   { "header",          &opt.user_headers,      cmd_spec_header },
@@ -176,9 +176,9 @@ static struct {
   { "outputdocument",  &opt.output_document,   cmd_file },
   { "pagerequisites",  &opt.page_requisites,   cmd_boolean },
   { "passiveftp",      &opt.ftp_pasv,          cmd_lockable_boolean },
-  { "passwd",          &opt.ftp_pass,          cmd_string },
   { "postdata",                &opt.post_data,         cmd_string },
   { "postfile",                &opt.post_file_name,    cmd_file },
+  { "preferfamily",    NULL,                   cmd_spec_prefer_family },
   { "preservepermissions", &opt.preserve_perm, cmd_boolean },
   { "progress",                &opt.progress_type,     cmd_spec_progress },
   { "protocoldirectories", &opt.protocol_directories, cmd_boolean },
@@ -287,6 +287,7 @@ defaults (void)
   opt.dots_in_line = 50;
 
   opt.dns_cache = 1;
+  opt.ftp_pasv = 1;
 
   /* The default for file name restriction defaults to the OS type. */
 #if !defined(WINDOWS) && !defined(__CYGWIN__)
@@ -314,9 +315,9 @@ home_dir (void)
        return NULL;
       home = pwd->pw_dir;
 #else  /* WINDOWS */
-      home = "C:\\";
-      /* #### Maybe I should grab home_dir from registry, but the best
-        that I could get from there is user's Start menu.  It sucks!  */
+      /* Under Windows, if $HOME isn't defined, use the directory where
+         `wget.exe' resides.  */
+      home = ws_mypath ();
 #endif /* WINDOWS */
     }
 
@@ -347,27 +348,24 @@ wgetrc_file_name (void)
       return xstrdup (env);
     }
 
-#ifndef WINDOWS
   /* If that failed, try $HOME/.wgetrc.  */
   home = home_dir ();
   if (home)
-    {
-      file = (char *)xmalloc (strlen (home) + 1 + strlen (".wgetrc") + 1);
-      sprintf (file, "%s/.wgetrc", home);
-    }
+    file = aprintf ("%s/.wgetrc", home);
   xfree_null (home);
-#else  /* WINDOWS */
-  /* Under Windows, "home" is (for the purposes of this function) the
-     directory where `wget.exe' resides, and `wget.ini' will be used
-     as file name.  SYSTEM_WGETRC should not be defined under WINDOWS.
 
-     It is not as trivial as I assumed, because on 95 argv[0] is full
-     path, but on NT you get what you typed in command line.  --dbudor */
-  home = ws_mypath ();
-  if (home)
+#ifdef WINDOWS
+  /* Under Windows, if we still haven't found .wgetrc, look for the file
+     `wget.ini' in the directory where `wget.exe' resides; we do this for
+     backward compatibility with previous versions of Wget.
+     SYSTEM_WGETRC should not be defined under WINDOWS.  */
+  if (!file || !file_exists_p (file))
     {
-      file = (char *)xmalloc (strlen (home) + strlen ("wget.ini") + 1);
-      sprintf (file, "%swget.ini", home);
+      xfree_null (file);
+      file = NULL;
+      home = ws_mypath ();
+      if (home)
+       file = aprintf ("%s/wget.ini", home);
     }
 #endif /* WINDOWS */
 
@@ -402,7 +400,7 @@ run_wgetrc (const char *file)
     }
   enable_tilde_expansion = 1;
   ln = 1;
-  while ((line = read_whole_line (fp)))
+  while ((line = read_whole_line (fp)) != NULL)
     {
       char *com, *val;
       int comind, status;
@@ -691,7 +689,8 @@ static int simple_atoi PARAMS ((const char *, const char *, int *));
 static int
 cmd_number (const char *com, const char *val, void *closure)
 {
-  if (!simple_atoi (val, val + strlen (val), closure))
+  if (!simple_atoi (val, val + strlen (val), closure)
+      || *(int *) closure < 0)
     {
       fprintf (stderr, _("%s: %s: Invalid number `%s'.\n"),
               exec_name, com, val);
@@ -749,7 +748,6 @@ cmd_file (const char *com, const char *val, void *closure)
     }
   else
     {
-      char *result;
       int homelen;
       char *home = home_dir ();
       if (!home)
@@ -763,12 +761,7 @@ cmd_file (const char *com, const char *val, void *closure)
       for (++val; ISSEP (*val); val++)
        ;
 
-      result = xmalloc (homelen + 1 + strlen (val) + 1);
-      memcpy (result, home, homelen);
-      result[homelen] = '/';
-      strcpy (result + homelen + 1, val);
-
-      *pstring = result;
+      *pstring = concat_strings (home, "/", val, (char *) 0);
     }
 
 #ifdef WINDOWS
@@ -855,8 +848,8 @@ cmd_directory_vector (const char *com, const char *val, void *closure)
 
 static int simple_atof PARAMS ((const char *, const char *, double *));
 
-/* Enginge for cmd_bytes and cmd_bytes_large: converts a string such
-   as "100k" or "2.5G" to a floating point number.  */
+/* Engine for cmd_bytes and cmd_bytes_large: converts a string such as
+   "100k" or "2.5G" to a floating point number.  */
 
 static int
 parse_bytes_helper (const char *val, double *result)
@@ -905,7 +898,7 @@ parse_bytes_helper (const char *val, double *result)
   if (val == end)
     return 0;
 
-  if (!simple_atof (val, end, &number))
+  if (!simple_atof (val, end, &number) || number < 0)
     return 0;
 
   *result = number * mult;
@@ -913,7 +906,7 @@ parse_bytes_helper (const char *val, double *result)
 }
 
 /* Parse VAL as a number and set its value to CLOSURE (which should
-   point to a long int).
+   point to a wgint).
 
    By default, the value is assumed to be in bytes.  If "K", "M", or
    "G" are appended, the value is multiplied with 1<<10, 1<<20, or
@@ -936,7 +929,7 @@ cmd_bytes (const char *com, const char *val, void *closure)
               exec_name, com, val);
       return 0;
     }
-  *(long *)closure = (long)byte_value;
+  *(wgint *)closure = (wgint)byte_value;
   return 1;
 }
 
@@ -1081,6 +1074,32 @@ cmd_spec_mirror (const char *com, const char *val, void *closure)
   return 1;
 }
 
+/* Validate --prefer-family and set the choice.  Allowed values are
+   "IPv4", "IPv6", and "none".  */
+
+static int
+cmd_spec_prefer_family (const char *com, const char *val, void *closure)
+{
+  if (0 == strcasecmp (val, "ipv4"))
+    {
+      opt.prefer_family = prefer_ipv4;
+      return 1;
+    }
+  else if (0 == strcasecmp (val, "ipv6"))
+    {
+      opt.prefer_family = prefer_ipv6;
+      return 1;
+    }
+  else if (0 == strcasecmp (val, "none"))
+    {
+      opt.prefer_family = prefer_none;
+      return 1;
+    }
+  fprintf (stderr, _("%s: %s: Invalid preferred family `%s'.\n"),
+          exec_name, com, val);
+  return 0;
+}
+
 /* Set progress.type to VAL, but verify that it's a valid progress
    implementation before that.  */
 
@@ -1191,21 +1210,46 @@ cmd_spec_useragent (const char *com, const char *val, void *closure)
 \f
 /* Miscellaneous useful routines.  */
 
-/* A very simple atoi clone, more portable than strtol and friends,
-   but reports errors, unlike atoi.  Returns 1 on success, 0 on
-   failure.  In case of success, stores result to *DEST.  */
+/* A very simple atoi clone, more useful than atoi because it works on
+   delimited strings, and has error reportage.  Returns 1 on success,
+   0 on failure.  If successful, stores result to *DEST.  */
 
 static int
 simple_atoi (const char *beg, const char *end, int *dest)
 {
   int result = 0;
-  const char *p;
+  int negative = 0;
+  const char *p = beg;
 
-  if (beg == end)
+  while (p < end && ISSPACE (*p))
+    ++p;
+  if (p < end && (*p == '-' || *p == '+'))
+    {
+      negative = (*p == '-');
+      ++p;
+    }
+  if (p == end)
     return 0;
 
-  for (p = beg; p < end && ISDIGIT (*p); p++)
-    result = (10 * result) + (*p - '0');
+  /* Read negative numbers in a separate loop because the most
+     negative integer cannot be represented as a positive number.  */
+
+  if (!negative)
+    for (; p < end && ISDIGIT (*p); p++)
+      {
+       int next = (10 * result) + (*p - '0');
+       if (next < result)
+         return 0;             /* overflow */
+       result = next;
+      }
+  else
+    for (; p < end && ISDIGIT (*p); p++)
+      {
+       int next = (10 * result) - (*p - '0');
+       if (next > result)
+         return 0;             /* underflow */
+       result = next;
+      }
 
   if (p != end)
     return 0;
@@ -1223,13 +1267,22 @@ simple_atof (const char *beg, const char *end, double *dest)
 {
   double result = 0;
 
+  int negative = 0;
   int seen_dot = 0;
   int seen_digit = 0;
   double divider = 1;
 
-  const char *p;
+  const char *p = beg;
+
+  while (p < end && ISSPACE (*p))
+    ++p;
+  if (p < end && (*p == '-' || *p == '+'))
+    {
+      negative = (*p == '-');
+      ++p;
+    }
 
-  for (p = beg; p < end; p++)
+  for (; p < end; p++)
     {
       char ch = *p;
       if (ISDIGIT (ch))
@@ -1252,6 +1305,8 @@ simple_atof (const char *beg, const char *end, double *dest)
     }
   if (!seen_digit)
     return 0;
+  if (negative)
+    result = -result;
 
   *dest = result;
   return 1;
@@ -1274,8 +1329,6 @@ check_user_specified_header (const char *s)
 }
 \f
 void cleanup_html_url PARAMS ((void));
-void res_cleanup PARAMS ((void));
-void downloaded_files_free PARAMS ((void));
 void http_cleanup PARAMS ((void));
 
 
@@ -1306,10 +1359,8 @@ cleanup (void)
   res_cleanup ();
   http_cleanup ();
   cleanup_html_url ();
-  downloaded_files_free ();
   host_cleanup ();
-  if (wget_cookie_jar)
-    cookie_jar_delete (wget_cookie_jar);
+  log_cleanup ();
 
   {
     extern acc_t *netrc_list;
@@ -1337,7 +1388,7 @@ cleanup (void)
   xfree_null (opt.referer);
   xfree_null (opt.http_user);
   xfree_null (opt.http_passwd);
-  xfree_null (opt.user_header);
+  free_vec (opt.user_headers);
 #ifdef HAVE_SSL
   xfree_null (opt.sslcertkey);
   xfree_null (opt.sslcertfile);