
/*
 *  DOMAIN.C
 *
 *  (C) Copyright 1989-1990 by Matthew Dillon,  All Rights Reserved.
 *
 *  Given the first machine in a path scan the domain list and
 *  return the type, class, and address of the resource entry.
 *
 *  AUTOMATIC HACKS:	scans L.sys file and automatically deals
 *			with machine[.UUCP] domain, returning
 *			Type=MD Class=UU Addr=machine.UUCP
 */

#include <proto/all.h>
#include <stdio.h>
#include <stdlib.h>

extern char *DefaultNode;

DomainLookup(name, len, tb, cb, ab)
char *name;
char *tb;
char *cb;
char *ab;
{
    char *dary[16];
    char *tmp = malloc(len + 1);
    char *tbase = tmp;
    short b, i;
    short di;
    FILE *fi;
    short level;	    /*	best domain level found so far */
    static char buf[256];

    for (b = i = di = 0; i < len && name[i] != '!'; ++i) {
	if (name[i] == '.') {
	    if (di == sizeof(dary)/sizeof(dary[0]) - 1) {
		ulog(-1, "DomainLookup, too many domains! %s", name);
		break;
	    }
	    strncpy(tmp, name + b, i - b);
	    tmp[i - b] = 0;
	    dary[di] = tmp;
	    tmp += i - b + 1;
	    b = i + 1;
	    ++di;
	}
    }
    strncpy(tmp, name + b, i - b);
    tmp[i - b] = 0;
    dary[di++] = tmp;

    fi = fopen("UULIB:Domain", "r");
    level = 0;
    if (fi) {
	while (fgets(buf, sizeof(buf), fi)) {
	    short l2;
	    short di2 = 0;
	    char *dary2[16];

	    if (buf[0] == ' ' || buf[0] == 9 || buf[0] == '\n' || buf[0] == '#')
		continue;
	    for (b = i = 0; buf[i] && buf[i] != ' ' && buf[i] != 9; ++i) {
		if (buf[i] == '.') {
		    if (di2 == sizeof(dary2)/sizeof(dary2[0]) - 1) {
			ulog(-1, "UULIB:Domain, entry has too many subdomains: %s", buf);
			break;
		    }
		    dary2[di2++] = buf + b;
		    buf[i] = 0;
		    b = i + 1;
		}
	    }
	    buf[i] = 0;
	    dary2[di2++] = buf + b;

	    buf[i] = 0; 	/*  get domain name/wildcard		*/

	    l2 = CompareDomain(dary, di, dary2, di2);
	    if (l2 > level) {   /*  better domain then what we have     */
		sscanf(buf + i + 1, "%s %s %s", tb, cb, ab);
		level = l2;
	    }
	}
	fclose(fi);
    }

    /*
     *	Couldn't find the appropriate domain entry, check L.sys
     *	OR domain entry is a forwarder, check L.sys
     */

    if (strcmp(tb, "MF") == 0 || level == 0) {
	if (fi = fopen("UULIB:L.sys", "r")) {
	    while (fgets(buf, sizeof(buf), fi)) {
		if (buf[0] == ' ' || buf[0] == 9 || buf[0] == '#' || buf[0] == '\n')
		    continue;
		for (i = 0; buf[i] && buf[i] != ' ' && buf[i] != 9; ++i);
		buf[i] = 0;
		if (strcmpi(dary[0], buf) == 0) {
		    strcpy(tb, "MD");
		    strcpy(cb, "UU");
		    strcpy(ab, buf);
		    strcat(ab, ".UUCP");
		    level = 1;
		    break;
		}
	    }
	    fclose(fi);
	}
    }

    /*
     *	Couldn't find nothing, use DefaultNode
     */

    if (level == 0) {
	ulog(-1, "Warning, unable to interpret addr %s, using DefaultNode", name);
	if (DefaultNode == NULL) {
	    ulog(-1, "Error, DefaultNode must exist if no UULIB:Domain");
	    printf("ERROR, no entry in UULIB:Domain, UULIB:L.sys, and\n");
	    printf("no DefaultNode config entry for %s\n", name);
	    puts("cannot send mail");
	    free(tbase);
	    return(0);
	}
	strcpy(tb, "MF");
	strcpy(cb, "UU");
	strcpy(ab, DefaultNode);
	level = 1;
    }
    free(tbase);
    return(level > 0);
}

/*
 *  Compares a broken up address with a domain entry (buf).
 */

CompareDomain(da1, di1, da2, di2)
char **da1;
short di1;
char **da2;
short di2;
{
    short i, j;
    short level = 0;

    for (i = di1 - 1, j = di2 - 1; i >= 0 && j >= 0; --i, --j) {
	if (da2[j][0] == '*') {
	    ++level;
	    if (i && j == 0)    /*  so loop does not terminate  */
		++j;
	    continue;
	}
	if (strcmpi(da1[i], da2[j]) == 0)
	    level += 2;
	else {
	    if (j + 1 < di2 && da2[j+1][0] == '*')
		++level;
	    else
		return(0);
	}
    }
    if (j >= 0)         /*  didn't exhaust domain entry */
	return(0);
    return((int)level);
}

