int __read_etc_hosts_r(
		parser_t * parser,
		const char *name,
		int type,
		enum etc_hosts_action action,
		struct hostent *result_buf,
		char *buf, size_t buflen,
		struct hostent **result,
		int *h_errnop)
{
	char **tok = NULL;
	struct in_addr *h_addr0 = NULL;
	const size_t aliaslen = INADDROFF +
#ifdef __UCLIBC_HAS_IPV6__
							sizeof(struct in6_addr)
#else
							sizeof(struct in_addr)
#endif
							;
	int ret = HOST_NOT_FOUND;
	/* make sure pointer is aligned */
	int i = ALIGN_BUFFER_OFFSET(buf);
	buf += i;
	buflen -= i;

	*h_errnop = NETDB_INTERNAL;
	if (/* (ssize_t)buflen < 0 || */ buflen < aliaslen
		|| (buflen - aliaslen) < BUFSZ + 1)
		return ERANGE;
	if (parser == NULL)
		parser = __open_etc_hosts();
	if (parser == NULL) {
		*result = NULL;
		return errno;
	}
	/* Layout in buf:
	 * char *alias[MAXTOKENS]  = {address, name, aliases...}
	 * char **h_addr_list[1]   = {*in[6]_addr, NULL}
	 * struct in[6]_addr
	 * char line_buffer[BUFSZ+];
	 */
	parser->data = buf;
	parser->data_len = aliaslen;
	parser->line_len = buflen - aliaslen;
	*h_errnop = HOST_NOT_FOUND;
	/* <ip>[[:space:]][<aliases>] */
	while (config_read(parser, &tok, MAXTOKENS, MINTOKENS, "# \t", PARSE_NORMAL)) {
		result_buf->h_aliases = tok+1;
		if (action == GETHOSTENT) {
			/* Return whatever the next entry happens to be. */
			;
		} else if (action == GET_HOSTS_BYADDR) {
			if (strcmp(name, *tok) != 0)
				continue;
		} else { /* GET_HOSTS_BYNAME */
			int aliases = 0;
			char **alias = tok + 1;
			while (aliases < MAXALIASES) {
				char *tmp = *(alias+aliases++);
				if (tmp && strcasecmp(name, tmp) == 0)
					goto found;
			}
			continue;
		}
found:
		result_buf->h_name = *(result_buf->h_aliases++);
		result_buf->h_addr_list = (char**)(buf + HALISTOFF);
		*(result_buf->h_addr_list + 1) = '\0';
		h_addr0 = (struct in_addr*)(buf + INADDROFF);
		result_buf->h_addr = (char*)h_addr0;
		if (0) /* nothing */;
#ifdef __UCLIBC_HAS_IPV4__
		else if (type == AF_INET
				&& inet_pton(AF_INET, *tok, h_addr0) > 0) {
			DPRINTF("Found INET\n");
			result_buf->h_addrtype = AF_INET;
			result_buf->h_length = sizeof(struct in_addr);
			*result = result_buf;
			ret = NETDB_SUCCESS;
		}
#endif
#ifdef __UCLIBC_HAS_IPV6__
#define in6 ((struct in6_addr *)buf)
		else if (type == AF_INET6
				&& inet_pton(AF_INET6, *tok, h_addr0) > 0) {
			DPRINTF("Found INET6\n");
			result_buf->h_addrtype = AF_INET6;
			result_buf->h_length = sizeof(struct in6_addr);
			*result = result_buf;
			ret = NETDB_SUCCESS;
		}
#endif
		else {
			/* continue parsing in the hope the user has multiple
			 * host types listed in the database like so:
			 * <ipv4 addr> host
			 * <ipv6 addr> host
			 * If looking for an IPv6 addr, don't bail when we got the IPv4
			 */
			DPRINTF("Error: Found host but different address family\n");
			/* NB: gethostbyname2_r depends on this feature
			 * to avoid looking for IPv6 addr of "localhost" etc */
			ret = TRY_AGAIN;
			continue;
		}
		break;
	}
	if (action != GETHOSTENT)
		config_close(parser);
	return ret;
#undef in6
}
int __read_etc_hosts_r(
		parser_t * parser,
		const char *name,
		int type,
		enum etc_hosts_action action,
		struct hostent *result_buf,
		char *buf, size_t buflen,
		struct hostent **result,
		int *h_errnop)
{
	char **tok = NULL;
	struct in_addr *h_addr0 = NULL;
	const size_t aliaslen = INADDROFF +
#ifdef __UCLIBC_HAS_IPV6__
							sizeof(struct in6_addr)
#else
							sizeof(struct in_addr)
#endif
							;
	int ret = HOST_NOT_FOUND;
	 
	int i = ALIGN_BUFFER_OFFSET(buf);
	buf += i;
	buflen -= i;

	*h_errnop = NETDB_INTERNAL;
	if (  buflen < aliaslen
		|| (buflen - aliaslen) < BUFSZ + 1)
		return ERANGE;
	if (parser == NULL)
		parser = __open_etc_hosts();
	if (parser == NULL) {
		*result = NULL;
		return errno;
	}
	 
	parser->data = buf;
	parser->data_len = aliaslen;
	parser->line_len = buflen - aliaslen;
	*h_errnop = HOST_NOT_FOUND;
	 
	while (config_read(parser, &tok, MAXTOKENS, MINTOKENS, "# \t", PARSE_NORMAL)) {
		result_buf->h_aliases = tok+1;
		if (action == GETHOSTENT) {
			 
			;
		} else if (action == GET_HOSTS_BYADDR) {
			if (strcmp(name, *tok) != 0)
				continue;
		} else {  
			int aliases = 0;
			char **alias = tok + 1;
			while (aliases < MAXALIASES) {
				char *tmp = *(alias+aliases++);
				if (tmp && strcasecmp(name, tmp) == 0)
					goto found;
			}
			continue;
		}
found:
		result_buf->h_name = *(result_buf->h_aliases++);
		result_buf->h_addr_list = (char**)(buf + HALISTOFF);
		*(result_buf->h_addr_list + 1) = '\0';
		h_addr0 = (struct in_addr*)(buf + INADDROFF);
		result_buf->h_addr = (char*)h_addr0;
		if (0)  ;
#ifdef __UCLIBC_HAS_IPV4__
		else if (type == AF_INET
				&& inet_pton(AF_INET, *tok, h_addr0) > 0) {
			DPRINTF("Found INET\n");
			result_buf->h_addrtype = AF_INET;
			result_buf->h_length = sizeof(struct in_addr);
			*result = result_buf;
			ret = NETDB_SUCCESS;
		}
#endif
#ifdef __UCLIBC_HAS_IPV6__
#define in6 ((struct in6_addr *)buf)
		else if (type == AF_INET6
				&& inet_pton(AF_INET6, *tok, h_addr0) > 0) {
			DPRINTF("Found INET6\n");
			result_buf->h_addrtype = AF_INET6;
			result_buf->h_length = sizeof(struct in6_addr);
			*result = result_buf;
			ret = NETDB_SUCCESS;
		}
#endif
		else {
			 
			DPRINTF("Error: Found host but different address family\n");
			 
			ret = TRY_AGAIN;
			continue;
		}
		break;
	}
	if (action != GETHOSTENT)
		config_close(parser);
	return ret;
#undef in6
}