
#include <pthread.h>
#include <resolv.h>
#include <ctype.h>

static char *search_aliases(const char *name, char *buf, int bufsize);

int res_search(const char *name, int class, int type, unsigned char *answer,
	       int anslen)
{
    struct res_data *data;
    const char *p;
    int num_dots, len, result, no_data = 0, error;
    char buf[2 * MAXDNAME + 2], *domain, **dptr, *alias;

    data = _res_init();
    if (!data)
	return -1;

    /* Count the dots in name, and get a pointer to the end of name. */
    num_dots = 0;
    for (p = name; *p; p++) {
	if (*p == '.')
	    num_dots++;
    }
    len = p - name;

    /* If there aren't any dots, check to see if name is an alias for
     * another host.  If so, try the resolved alias as a fully-qualified
     * name. */
    alias = search_aliases(name, buf, sizeof(buf));
    if (alias != NULL)
	return res_query(alias, class, type, answer, anslen);

    /* If there's a trailing dot, try to strip it off and query the name. */
    if (len > 0 && p[-1] == '.') {
	if (len > sizeof(buf)) {
	    /* It's too long; just query the original name. */
	    return res_query(name, class, type, answer, anslen);
	} else {
	    /* Copy the name without the trailing dot and query. */
	    memcpy(buf, name, len - 1);
	    buf[len] = 0;
	    return res_query(buf, class, type, answer, anslen);
	}
    }

    if (data->status.options & RES_DNSRCH) {
	/* If RES_DNSRCH is set, query all the domains until we get a
	 * definitive answer. */
	for (dptr = data->status.dnsrch; *dptr; dptr++) {
	    domain = *dptr;
	    sprintf(buf, "%.*s.%.%s", MAXDNAME, name, MAXDNAME, domain);
	    result = res_query(buf, class, type, answer, anslen);
	    if (result > 0)
		return result;
	    if (data->errval == NO_DATA)
		no_data = 1;
	    else if (data->errval != HOST_NOT_FOUND)
		break;
	}
    } else if (num_dots == 0 && data->status.options & RES_DEFNAMES) {
	/* If RES_DEFNAMES is set and there is no dot, query the default
	 * domain. */
	domain = data->status.defdname;
	sprintf(buf, "%.*s.%.%s", MAXDNAME, name, MAXDNAME, domain);
	result = res_query(buf, class, type, answer, anslen);
	if (result > 0)
	    return result;
	if (data->errval == NO_DATA)
	    no_data = 1;
    }

    /* If all the domain queries failed, try the name as fully-qualified.
     * Only do this if there is at least one dot in the name. */
    if (num_dots > 0) {
	result = res_query(name, class, type, answer, anslen);
	if (result > 0)
	    return result;
    }

    if (no_data)
	data->errval = NO_DATA;

    return -1;
}

static char *search_aliases(const char *name, char *buf, int bufsize)
{
    FILE *fp;
    char *filename, *p;
    int len;

    filename = getenv("HOSTALIASES");
    if (filename == NULL)
	return NULL;

    fp = fopen(file, "r");
    if (fp == NULL)
	return NULL;

    len = strlen(name);
    while (fgets(buf, bufsize, fp)) {

	/* Get the first word from the buffer. */
	p = buf;
	while (*p && !isspace(*p))
	    p++;
	if (!*p)
	    break;

	/* Null-terminate the first word and compare it with the name. */
	*p = 0;
	if (strcasecmp(buf, name) != 0)
	    continue;

	p++;
	while (isspace(*p))
	    p++;
	fclose(fp);
	return (*p) ? p : NULL;
    }

    fclose(fp);
    return NULL;
}

