rem: LogError("gethostbyaddr");
add: LogError("gethostbyaddr", h_errno);
context: static GetProc GetHost;static int DnsGet(GetProc *getProc, Ns_DString *dsPtr,	Ns_Cache **cachePtr, char *key);static void LogError(char *func);/* *---------------------------------------------------------------------- * Ns_GetHostByAddr, Ns_GetAddrByHost -- * *      Convert an IP address to a hostname or vice versa. * * Results: *	See DnsGet(). * * Side effects: *      A new entry is entered into the hash table. * *---------------------------------------------------------------------- */intNs_GetHostByAddr(Ns_DString *dsPtr, char *addr){    return DnsGet(GetHost, dsPtr, &hostCache, addr);}intNs_GetAddrByHost(Ns_DString *dsPtr, char *host){    return DnsGet(GetAddr, dsPtr, &addrCache, host);}static intDnsGet(GetProc *getProc, Ns_DString *dsPtr, Ns_Cache **cachePtr, char *key){    int             status = NS_FALSE, new, timeout;    Value   	   *vPtr  = NULL;    Ns_Entry       *ePtr  = NULL;    Ns_Cache	   *cache = NULL;    time_t	    now;    /*     * Get the cache, if enabled.     */    Ns_MutexLock(&lock);    cache = *cachePtr;    timeout = cachetimeout;    Ns_MutexUnlock(&lock);    /*     * Call getProc directly or through cache.     */    if (cache == NULL) {        status = (*getProc)(dsPtr, key);    } else {	time(&now);	Ns_CacheLock(cache);	ePtr = Ns_CacheCreateEntry(cache, key, &new);	if (!new) {	    while (ePtr != NULL &&		    (vPtr = Ns_CacheGetValue(ePtr)) == NULL) {		Ns_CacheWait(cache);		ePtr = Ns_CacheFindEntry(cache, key);	    }	    if (ePtr == NULL) {	        status = NS_FALSE;	    } else if (vPtr->expires < now) {		Ns_CacheUnsetValue(ePtr);		new = 1;	    } else {		Ns_DStringAppend(dsPtr, vPtr->value);		status = NS_TRUE;	    }	}	if (new) {	    Ns_CacheUnlock(cache);	    status = (*getProc)(dsPtr, key);	    Ns_CacheLock(cache);	    ePtr = Ns_CacheCreateEntry(cache, key, &new);	    if (status != NS_TRUE) {		Ns_CacheFlushEntry(ePtr);	    } else {	    	Ns_CacheUnsetValue(ePtr);		vPtr = ns_malloc(sizeof(Value) + dsPtr->length);		vPtr->expires = now + timeout;		strcpy(vPtr->value, dsPtr->string);		Ns_CacheSetValueSz(ePtr, vPtr, 1);	    }	    Ns_CacheBroadcast(cache);	}	Ns_CacheUnlock(cache);    }    return status;}/* *---------------------------------------------------------------------- * NsEnableDNSCache -- * *      Enable DNS results caching. * * Results: *      None. * * Side effects: *	Futher DNS lookups will be cached up to given timeout. * *---------------------------------------------------------------------- */voidNsEnableDNSCache(int timeout, int maxentries){    Ns_MutexSetName(&lock, "ns:dns");    Ns_MutexLock(&lock);    cachetimeout = timeout;    hostCache = Ns_CacheCreateSz("ns:dnshost", TCL_STRING_KEYS,	(size_t) maxentries, ns_free);    addrCache = Ns_CacheCreateSz("ns:dnsaddr", TCL_STRING_KEYS,	(size_t) maxentries, ns_free);    Ns_MutexUnlock(&lock);}/* *---------------------------------------------------------------------- * GetHost, GetAddr -- * *      Perform the actual lookup by host or address. * *	NOTE: A critical section is used instead of a mutex *	to ensure waiting on a condition and not mutex spin waiting. * * Results: *      If a name can be found, the function returns NS_TRUE; otherwise,  *	it returns NS_FALSE. * * Side effects: *      Result is appended to dsPtr. * *---------------------------------------------------------------------- */static intGetHost(Ns_DString *dsPtr, char *addr){    struct hostent *he;    struct sockaddr_in sa;    static Ns_Cs cs;    int status = NS_FALSE;    sa.sin_addr.s_addr = inet_addr(addr);    if (sa.sin_addr.s_addr != INADDR_NONE) {	Ns_CsEnter(&cs);        he = gethostbyaddr((char *) &sa.sin_addr,			   sizeof(struct in_addr), AF_INET);	if (he == NULL) {	    LogError("gethostbyaddr");	} else if (he->h_name != NULL) {	    Ns_DStringAppend(dsPtr, he->h_name);	    status = NS_TRUE;	}	Ns_CsLeave(&cs);    }    return status;}