]> sjero.net Git - wget/blobdiff - src/host.c
[svn] Treat the "shortcut icon" link as inline.
[wget] / src / host.c
index 691022b0115ec68c8316aea97d274394ed9c7349..ddc04445e0fe2d17909769a33b280a552802889b 100644 (file)
@@ -1,5 +1,5 @@
-/* Dealing with host names.
-   Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc.
+/* Host name resolution and matching.
+   Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU Wget.
 
@@ -59,18 +59,25 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 extern int errno;
 #endif
 
-#define IP4_ADDRESS_LENGTH 4
+#ifndef h_errno
+# ifndef __CYGWIN__
+extern int h_errno;
+# endif
+#endif
+
+/* An IPv4 address is simply a 4-byte quantity. */
+typedef unsigned char ipv4_address[4];
 
 /* Mapping between known hosts and to lists of their addresses. */
 
-struct hash_table *host_name_addresses_map;
+static struct hash_table *host_name_addresses_map;
 \f
 /* Lists of addresses.  This should eventually be extended to handle
    IPv6.  */
 
 struct address_list {
   int count;                   /* number of adrresses */
-  unsigned char *buffer;       /* buffer which holds all of them. */
+  ipv4_address *addresses;     /* pointer to the string of addresses */
 
   int faulty;                  /* number of addresses known not to
                                   work. */
@@ -78,8 +85,6 @@ struct address_list {
                                   not. */
 };
 
-#define ADDR_LOCATION(al, index) ((al)->buffer + index * IP4_ADDRESS_LENGTH)
-
 /* Get the bounds of the address list.  */
 
 void
@@ -96,7 +101,7 @@ address_list_copy_one (struct address_list *al, int index,
                       unsigned char *ip_store)
 {
   assert (index >= al->faulty && index < al->count);
-  memcpy (ip_store, ADDR_LOCATION (al, index), IP4_ADDRESS_LENGTH);
+  memcpy (ip_store, al->addresses + index, sizeof (ipv4_address));
 }
 
 /* Check whether two address lists have all their IPs in common.  */
@@ -108,8 +113,8 @@ address_list_match_all (struct address_list *al1, struct address_list *al2)
     return 1;
   if (al1->count != al2->count)
     return 0;
-  return 0 == memcmp (al1->buffer, al2->buffer,
-                     al1->count * IP4_ADDRESS_LENGTH);
+  return 0 == memcmp (al1->addresses, al2->addresses,
+                     al1->count * sizeof (ipv4_address));
 }
 
 /* Mark the INDEXth element of AL as faulty, so that the next time
@@ -118,6 +123,11 @@ address_list_match_all (struct address_list *al1, struct address_list *al2)
 void
 address_list_set_faulty (struct address_list *al, int index)
 {
+  /* We assume that the address list is traversed in order, so that a
+     "faulty" attempt is always preceded with all-faulty addresses,
+     and this is how Wget uses it.  */
+  assert (index == al->faulty);
+
   ++al->faulty;
   if (al->faulty >= al->count)
     /* All addresses have been proven faulty.  Since there's not much
@@ -140,13 +150,28 @@ address_list_new (char **h_addr_list)
   while (h_addr_list[count])
     ++count;
   assert (count > 0);
-  al->count    = count;
-  al->faulty   = 0;
-  al->buffer   = xmalloc (count * IP4_ADDRESS_LENGTH);
-  al->refcount = 1;
+  al->count     = count;
+  al->faulty    = 0;
+  al->addresses = xmalloc (count * sizeof (ipv4_address));
+  al->refcount  = 1;
 
   for (i = 0; i < count; i++)
-    memcpy (ADDR_LOCATION (al, i), h_addr_list[i], IP4_ADDRESS_LENGTH);
+    memcpy (al->addresses + i, h_addr_list[i], sizeof (ipv4_address));
+
+  return al;
+}
+
+/* Like address_list_new, but initialized with only one address. */
+
+static struct address_list *
+address_list_new_one (const char *addr)
+{
+  struct address_list *al = xmalloc (sizeof (struct address_list));
+  al->count     = 1;
+  al->faulty    = 0;
+  al->addresses = xmalloc (sizeof (ipv4_address));
+  al->refcount  = 1;
+  memcpy (al->addresses, addr, sizeof (ipv4_address));
 
   return al;
 }
@@ -154,7 +179,7 @@ address_list_new (char **h_addr_list)
 static void
 address_list_delete (struct address_list *al)
 {
-  xfree (al->buffer);
+  xfree (al->addresses);
   xfree (al);
 }
 
@@ -174,7 +199,7 @@ address_list_release (struct address_list *al)
    #including the netinet stuff.  */
 
 char *
-pretty_print_address (const unsigned char *addr)
+pretty_print_address (const void *addr)
 {
   return inet_ntoa (*(struct in_addr *)addr);
 }
@@ -198,8 +223,7 @@ cache_host_lookup (const char *host, struct address_list *al)
       int i;
       debug_logprintf ("Caching %s =>", host);
       for (i = 0; i < al->count; i++)
-       debug_logprintf (" %s",
-                        pretty_print_address (ADDR_LOCATION (al, i)));
+       debug_logprintf (" %s", pretty_print_address (al->addresses + i));
       debug_logprintf ("\n");
     }
 #endif
@@ -217,9 +241,6 @@ lookup_host (const char *host, int silent)
   addr = (unsigned long)inet_addr (host);
   if ((int)addr != -1)
     {
-      char tmpstore[IP4_ADDRESS_LENGTH];
-      char *lst[] = { tmpstore, NULL };
-
       /* ADDR is defined to be in network byte order, which is what
         this returns, so we can just copy it to STORE_IP.  However,
         on big endian 64-bit architectures the value will be stored
@@ -227,12 +248,11 @@ lookup_host (const char *host, int silent)
         we copy the correct four bytes.  */
       int offset;
 #ifdef WORDS_BIGENDIAN
-      offset = sizeof (unsigned long) - IP4_ADDRESS_LENGTH;
+      offset = sizeof (unsigned long) - sizeof (ipv4_address);
 #else
       offset = 0;
 #endif
-      memcpy (tmpstore, (char *)&addr + offset, IP4_ADDRESS_LENGTH);
-      return address_list_new (lst);
+      return address_list_new_one ((char *)&addr + offset);
     }
 
   /* By now we know that the host name we got is not of the form
@@ -250,9 +270,7 @@ lookup_host (const char *host, int silent)
   if (!silent)
     logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
 
-  /* Look up the host using gethostbyname().  Note that we use
-     gethostbyname() rather than ngethostbyname(), because we already
-     know that the address is not numerical.  */
+  /* Look up the host using gethostbyname().  */
   hptr = gethostbyname (host);
   if (!hptr)
     {
@@ -264,6 +282,8 @@ lookup_host (const char *host, int silent)
   if (!silent)
     logprintf (LOG_VERBOSE, _("done.\n"));
 
+  /* Do all systems have h_addr_list, or is it a newer thing?  If the
+     latter, use address_list_new_one.  */
   al = address_list_new (hptr->h_addr_list);
 
   /* Cache the lookup information. */