/*
#ident	"@(#)smail/src:RELEASE-3_2_0_120:qualify.c,v 1.17 2004/02/02 03:20:18 woods Exp"
 */

/*
 *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
 *    Copyright (C) 1992  Ronald S. Karr
 * 
 * See the file COPYING, distributed with smail, for restriction
 * and warranty information.
 */

/*
 * qualify.c:
 *      Fully qualify a domain.  In lieu of full qualification rules,
 *      this routine appends the first visible domain.
 *
 *	This source file was contributed by Chip Salzenberg,
 *	chip@ateng.ateng.com.  It has been modified.
 */

#include "defs.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>

#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
#  include <stdlib.h>
# endif
#endif
#ifdef HAVE_STRING_H
# if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
#  include <memory.h>
# endif
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif

#include "smail.h"
#include "alloc.h"
#include "list.h"
#include "main.h"
#include "parse.h"
#include "addr.h"
#include "smailstring.h"
#include "dys.h"
#include "log.h"
#include "smailconf.h"
#include "extern.h"
#include "smailport.h"

struct qualify {
    char    *host;                      /* host name */
    char    *domain;                    /* domain where host lives */
};

static struct qualify *domains = NULL;  /* Array of host/domain pairs */
static unsigned int domain_count = 0;	/* Count of valid pairs */
static unsigned int domain_max = 0;	/* Count of allocated pairs */

char *
read_qualify_file()
{
    FILE *f;
    char *entry;
    struct stat statbuf;

    /*
     * ignore any previously-read qualifier data
     */
    domain_count = 0;

    /*
     * try to open qualifier file, stat file if possible
     */
    if (qualify_file == NULL || EQ(qualify_file, "-")) {
	return NULL;
    }
    f = fopen(qualify_file, "r");
    if (f == NULL) {
	char *emsg = xprintf("cannot open %s: %s", qualify_file, strerror(errno));

	if (require_configs) {
	    return emsg;
	} else if (errno != ENOENT) {
	    write_log(WRITE_LOG_PANIC, "%s", emsg);
	}
	xfree(emsg);

	add_config_stat(qualify_file, (struct stat *) NULL);
	return NULL;
    }

    if (fstat(fileno(f), &statbuf) == -1) {
	char *emsg = xprintf("%s: fstat() failed: %s", qualify_file, strerror(errno));

	/* realistically this could only ever be EIO... */
	if (require_configs) {
	    return emsg;
	} else {
	    write_log(WRITE_LOG_PANIC, "%s", emsg);
	}
	xfree(emsg);
	add_config_stat(qualify_file, (struct stat *) NULL);
	/* ... but go on and try reading from 'f' anyway... */
    } else {
	add_config_stat(qualify_file, &statbuf);
    }

    /* loop and read all of the table entries in the domains file */

    if (!domains) {
	domain_max = 16;
	domains = (struct qualify *) xmalloc((size_t) (domain_max * sizeof(*domains)));
    }
    while ((entry = read_entry(f))) {
	struct attribute *new;
	char *error;

	new = parse_table(entry, &error);
	if (new == NULL) {
	    continue;
	}
	if (domain_count >= domain_max) {
	    domain_max += 16;
	    domains = (struct qualify *) xrealloc((char *) domains,
						  (size_t) (domain_max * sizeof(struct qualify)));
	}
	domains[domain_count].host = new->name;
	domains[domain_count].domain = new->value;
	++domain_count;
	xfree((char *)new);
    }
    (void) fclose(f);

    return NULL;
}

char *
qualify_domain(s)
    char *s;				/* domain to fully qualify */
{
    unsigned int i;

    if (strchr(s, '.') != NULL) {
	return NULL;
    }

    for (i = 0; i < domain_count; ++i) {
	char *host = domains[i].host;

	if (EQIC(host, s) || EQIC(host, "*")) {
	    return domains[i].domain;
	}
    }

    return NULL;
}

void
dump_qualify_config(f)
     FILE * f;
{
    unsigned int i;

    fputs("#\n# -- qualify configuration\n#\n", f);
    for (i = 0; i < domain_count; ++i) {
	fprintf(f, "%s\t%s\n",
		domains[i].host,
		domains[i].domain);
    }
    fputs("#\n# -- end of qualify configuration\n#\n", f);
}

/* 
 * Local Variables:
 * c-file-style: "smail"
 * End:
 */
