diff -urN squid-2.4-200208062300/src/cf.data.pre squid-2.4-hosts_hack/src/cf.data.pre
--- squid-2.4-200208062300/src/cf.data.pre	Sun Jun 23 22:10:16 2002
+++ squid-2.4-hosts_hack/src/cf.data.pre	Thu Aug  8 00:04:02 2002
@@ -1053,6 +1053,29 @@
 	Example: dns_nameservers 10.0.0.1 192.172.0.4
 DOC_END
 
+NAME: hosts_file
+TYPE: string
+DEFAULT: /etc/hosts
+LOC: Config.etcHostsPath
+DOC_START
+        Location of the host-local IP name-address associations
+        database.  Most Operating Systems have such a file: under
+        Un*X it's by default in /etc/hosts MS-Windows NT/2000 places
+        that in %SystemRoot%(by default
+        c:\winnt)\system32\drivers\etc\hosts, while Windows 9x/ME
+        places that in %windir%(usually c:\windows)\hosts
+
+        The file contains newline-separated definitions, in the
+        form ip_address_in_dotted_form name [name ...] names are
+        whitespace-separated.  lines beginnng with an hash (#)
+        character are comments.
+
+        The file is checked at startup and upon configuration.  If
+        set to 'none', it won't be checked.  If append_domain is
+        used, that domain will be added to domain-local (i.e. not
+        containing any dot character) host definitions.
+DOC_END
+
 NAME: diskd_program
 TYPE: string
 DEFAULT: @DEFAULT_DISKD@
diff -urN squid-2.4-200208062300/src/fqdncache.c squid-2.4-hosts_hack/src/fqdncache.c
--- squid-2.4-200208062300/src/fqdncache.c	Fri Jan 12 01:51:47 2001
+++ squid-2.4-hosts_hack/src/fqdncache.c	Thu Aug  8 00:21:33 2002
@@ -54,6 +54,7 @@
     unsigned short locks;
     struct {
 	unsigned int negcached:1;
+	unsigned int fromhosts:1;
     } flags;
 };
 
@@ -153,6 +154,26 @@
     debug(35, 9) ("fqdncache_purgelru: removed %d entries\n", removed);
 }
 
+static void
+purge_entries_fromhosts(void)
+{
+    dlink_node *m = lru_list.head;
+    fqdncache_entry *i = NULL;
+    fqdncache_entry *t;
+    while (m) {
+        if (i != NULL) {        /* need to delay deletion */
+            fqdncacheRelease(i);        /* we just override locks */
+            i = NULL;
+        }
+        t = m->data;
+        if (t->flags.fromhosts)
+            i = t;
+        m = m->next;
+    }
+    if (i != NULL)
+        fqdncacheRelease(i);
+}
+
 /* create blank fqdncache_entry */
 static fqdncache_entry *
 fqdncacheCreateEntry(const char *name)
@@ -458,10 +479,11 @@
 
     hash_first(fqdn_table);
     while ((f = (fqdncache_entry *) hash_next(fqdn_table))) {
-	ttl = (f->expires - squid_curtime);
-	storeAppendPrintf(sentry, " %-32.32s %c %6d %d",
+        ttl = (f->flags.fromhosts ? -1 : (f->expires - squid_curtime));
+	storeAppendPrintf(sentry, " %-32.32s %c%c %6d %d",
 	    hashKeyStr(&f->hash),
 	    f->flags.negcached ? 'N' : ' ',
+	    f->flags.fromhosts ? 'H' : ' ',
 	    ttl,
 	    (int) f->name_count);
 	for (k = 0; k < (int) f->name_count; k++)
@@ -533,6 +555,41 @@
 	    (float) FQDN_HIGH_WATER) / (float) 100);
     fqdncache_low = (long) (((float) Config.fqdncache.size *
 	    (float) FQDN_LOW_WATER) / (float) 100);
+    purge_entries_fromhosts();
+}
+
+/*
+ *  adds a "static" entry from /etc/hosts.  the worldist is to be
+ *  managed by the caller, including pointed-to strings
+ */
+void
+fqdncacheAddEntryFromHosts(char *addr, wordlist * hostnames)
+{
+    fqdncache_entry *fce;
+    int j = 0;
+    if ((fce = fqdncache_get(addr))) {
+        if (1 == fce->flags.fromhosts) {
+            fqdncacheUnlockEntry(fce);
+        } else if (fce->locks > 0) {
+            debug(35, 1) ("fqdncacheAddEntryFromHosts: can't add static entry for locked address '%s'\n", addr);
+            return;
+        } else {
+            fqdncacheRelease(fce);
+        }
+    }
+    fce = fqdncacheCreateEntry(addr);
+    while (hostnames) {
+        fce->names[j] = xstrdup(hostnames->key);
+        j++;
+        hostnames = hostnames->next;
+        if (j >= FQDN_MAX_NAMES)
+            break;
+    }
+    fce->name_count = j;
+    fce->names[j] = NULL;       /* it's safe */
+    fce->flags.fromhosts = 1;
+    fqdncacheAddEntry(fce);
+    fqdncacheLockEntry(fce);
 }
 
 #ifdef SQUID_SNMP
diff -urN squid-2.4-200208062300/src/ipcache.c squid-2.4-hosts_hack/src/ipcache.c
--- squid-2.4-200208062300/src/ipcache.c	Fri Jan 12 01:51:49 2001
+++ squid-2.4-hosts_hack/src/ipcache.c	Thu Aug  8 00:12:14 2002
@@ -50,6 +50,7 @@
     unsigned short locks;
     struct {
 	unsigned int negcached:1;
+	unsigned int fromhosts:1;
     } flags;
 };
 
@@ -163,6 +164,26 @@
     debug(14, 9) ("ipcache_purgelru: removed %d entries\n", removed);
 }
 
+/* purges entries added from /etc/hosts (or whatever). */
+static void
+purge_entries_fromhosts(void)
+{
+    dlink_node *m = lru_list.head;
+    ipcache_entry *i = NULL, *t;
+    while (m) {
+        if (i != NULL) {        /* need to delay deletion */
+            ipcacheRelease(i);  /* we just override locks */
+            i = NULL;
+        }
+        t = m->data;
+        if (t->flags.fromhosts)
+            i = t;
+        m = m->next;
+    }
+    if (i != NULL)
+        ipcacheRelease(i);
+}
+
 /* create blank ipcache_entry */
 static ipcache_entry *
 ipcacheCreateEntry(const char *name)
@@ -489,9 +510,10 @@
     int k;
     storeAppendPrintf(sentry, " %-32.32s  %c %6d %6d %2d(%2d)",
 	hashKeyStr(&i->hash),
+	i->flags.fromhosts ? 'H' : ' ',
 	i->flags.negcached ? 'N' : ' ',
 	(int) (squid_curtime - i->lastref),
-	(int) (i->expires - squid_curtime),
+        (int) ((i->flags.fromhosts ? -1 : i->expires - squid_curtime)),
 	(int) i->addrs.count,
 	(int) i->addrs.badcount);
     for (k = 0; k < (int) i->addrs.count; k++) {
@@ -694,6 +716,50 @@
 	    (float) Config.ipcache.high) / (float) 100);
     ipcache_low = (long) (((float) Config.ipcache.size *
 	    (float) Config.ipcache.low) / (float) 100);
+    purge_entries_fromhosts();
+}
+
+/*
+ *  adds a "static" entry from /etc/hosts.
+ *  returns 0 upon success, 1 if the ip address is invalid
+ */
+int
+ipcacheAddEntryFromHosts(const char *name, const char *ipaddr)
+{
+    ipcache_entry *i;
+    struct in_addr ip;
+    if (!safe_inet_addr(ipaddr, &ip)) {
+        if (strchr(ipaddr, ':') && strspn(ipaddr, "0123456789abcdefABCDEF:") == strlen(ipaddr)) {
+            debug(14, 3) ("ipcacheAddEntryFromHosts: Skipping IPv6 address '%s'\n", ipaddr);
+        } else {
+            debug(14, 1) ("ipcacheAddEntryFromHosts: Bad IP address '%s'\n",
+                ipaddr);
+        }
+        return 1;
+    }
+    if ((i = ipcache_get(name))) {
+        if (1 == i->flags.fromhosts) {
+            ipcacheUnlockEntry(i);
+        } else if (i->locks > 0) {
+            debug(14, 1) ("ipcacheAddEntryFromHosts: can't add static entry"
+                " for locked name '%s'\n", name);
+            return 1;
+        } else {
+            ipcacheRelease(i);
+        }
+    }
+    i = ipcacheCreateEntry(name);
+    i->addrs.count = 1;
+    i->addrs.cur = 0;
+    i->addrs.badcount = 0;
+    i->addrs.in_addrs = xcalloc(1, sizeof(struct in_addr));
+    i->addrs.bad_mask = xcalloc(1, sizeof(unsigned char));
+    i->addrs.in_addrs[0].s_addr = ip.s_addr;
+    i->addrs.bad_mask[0] = FALSE;
+    i->flags.fromhosts = 1;
+    ipcacheAddEntry(i);
+    ipcacheLockEntry(i);
+    return 0;
 }
 
 #ifdef SQUID_SNMP
diff -urN squid-2.4-200208062300/src/main.c squid-2.4-hosts_hack/src/main.c
--- squid-2.4-200208062300/src/main.c	Sun May 20 02:09:59 2001
+++ squid-2.4-hosts_hack/src/main.c	Wed Aug  7 23:44:44 2002
@@ -351,6 +351,7 @@
     _db_init(Config.Log.log, Config.debugOptions);
     ipcache_restart();		/* clear stuck entries */
     fqdncache_restart();	/* sigh, fqdncache too */
+    parseEtcHosts();
     errorInitialize();		/* reload error pages */
 #if USE_DNSSERVERS
     dnsInit();
@@ -482,6 +483,7 @@
 	disk_init();		/* disk_init must go before ipcache_init() */
     ipcache_init();
     fqdncache_init();
+    parseEtcHosts();
 #if USE_DNSSERVERS
     dnsInit();
 #else
diff -urN squid-2.4-200208062300/src/protos.h squid-2.4-hosts_hack/src/protos.h
--- squid-2.4-200208062300/src/protos.h	Sun Jun 23 22:01:03 2002
+++ squid-2.4-hosts_hack/src/protos.h	Thu Aug  8 00:02:09 2002
@@ -259,6 +259,7 @@
 extern void fqdncacheFreeMemory(void);
 extern void fqdncache_restart(void);
 extern EVH fqdncache_purgelru;
+extern void fqdncacheAddEntryFromHosts(char *addr, wordlist * hostnames);
 
 extern void ftpStart(FwdState *);
 extern char *ftpUrlWith2f(const request_t *);
@@ -558,6 +559,7 @@
 extern void ipcacheFreeMemory(void);
 extern ipcache_addrs *ipcacheCheckNumeric(const char *name);
 extern void ipcache_restart(void);
+extern int ipcacheAddEntryFromHosts(const char *name, const char *ipaddr);
 
 /* MemBuf */
 /* init with specific sizes */
@@ -1087,6 +1089,7 @@
 extern void *linklistShift(link_list **);
 extern int xrename(const char *from, const char *to);
 extern int isPowTen(int);
+extern void parseEtcHosts(void);
 
 #if USE_HTCP
 extern void htcpInit(void);
diff -urN squid-2.4-200208062300/src/structs.h squid-2.4-hosts_hack/src/structs.h
--- squid-2.4-200208062300/src/structs.h	Sun Jun 23 22:10:17 2002
+++ squid-2.4-hosts_hack/src/structs.h	Wed Aug  7 23:48:28 2002
@@ -342,6 +342,7 @@
     char *debugOptions;
     char *pidFilename;
     char *mimeTablePathname;
+    char *etcHostsPath;
     char *visibleHostname;
     char *uniqueHostname;
     wordlist *hostnameAliases;
diff -urN squid-2.4-200208062300/src/tools.c squid-2.4-hosts_hack/src/tools.c
--- squid-2.4-200208062300/src/tools.c	Sat Aug 11 20:32:43 2001
+++ squid-2.4-hosts_hack/src/tools.c	Wed Aug  7 23:47:35 2002
@@ -934,3 +934,67 @@
 	return 0;
     return 1;
 }
+
+void
+parseEtcHosts(void)
+{
+    FILE *fp;
+    char buf[1024];
+    char buf2[512];
+    char *nt = buf;
+    char *lt = buf;
+
+    if (NULL == Config.etcHostsPath)
+        return;
+    if (0 == strcmp(Config.etcHostsPath, "none"))
+        return;
+    fp = fopen(Config.etcHostsPath, "r");
+    if (fp == NULL) {
+        debug(1, 1) ("parseEtcHosts: %s: %s\n",
+            Config.etcHostsPath, xstrerror());
+        return;
+    }
+#if defined(_SQUID_MSWIN_) || defined(_SQUID_CYGWIN_)
+    setmode(fileno(fp), O_TEXT);
+#endif
+    while (fgets(buf, 1024, fp)) {      /* for each line */
+        wordlist *hosts = NULL;
+        char *addr;
+        if (buf[0] == '#')      /* MS-windows likes to add comments */
+            continue;
+        lt = buf;
+        addr = buf;
+        debug(1, 5) ("etc_hosts: line is '%s'\n", buf);
+        nt = strpbrk(lt, w_space);
+        if (nt == NULL)         /* empty line */
+            continue;
+        *nt = '\0';             /* null-terminate the address */
+        debug(1, 5) ("etc_hosts: address is '%s'\n", addr);
+        lt = nt + 1;
+        while ((nt = strpbrk(lt, w_space))) {
+            char *host = NULL;
+            if (nt == lt) {     /* multiple spaces */
+                debug(1, 5) ("etc_hosts: multiple spaces, skipping\n");
+                lt = nt + 1;
+                continue;
+            }
+            *nt = '\0';
+            debug(1, 5) ("etc_hosts: got hostname '%s'\n", lt);
+            if (Config.appendDomain && !strchr(lt, '.')) {
+                /* I know it's ugly, but it's only at reconfig */
+                strncpy(buf2, lt, 512);
+                strncat(buf2, Config.appendDomain, 512 - strlen(lt));
+                host = buf2;
+            } else {
+                host = lt;
+            }
+            if (ipcacheAddEntryFromHosts(host, addr) != 0)
+                goto skip;      /* invalid address, continuing is useless */
+            wordlistAdd(&hosts, host);
+            lt = nt + 1;
+        }
+        fqdncacheAddEntryFromHosts(addr, hosts);
+      skip:
+        wordlistDestroy(&hosts);
+    }
+}

