/*
**
**  Resolve.c
**
**  Routes then resolves addresses into UUCP or LOCAL.
**
*/
#ifndef lint
static char 	*sccsid="@(#)resolve.c	2.5 (smail) 9/15/87";
#endif

#include	<ctype.h>
#include	<stdio.h>
#include	"defs.h"

extern int exitstat;		/* set if address doesn't resolve 	*/
extern enum ehandle handle;	/* what mail we can handle		*/
extern enum edebug debug;	/* verbose and debug modes		*/
extern enum erouting routing;	/* when to route addresses		*/
extern char hostdomain[];	/* */
extern char hostname[];		/* */
extern char *pathfile;		/* location of path database		*/
extern int getcost;		/* get path cost even if not routing    */

char *sform();

int ssplit();
int route();
int build();
int strcmpic();
int isuucp();
int getpath();

/*
**
**  rsvp(): how to resolve addresses.
**
**  After parsing an address into <form>, the resolved form will be
**  rsvp( form ).  If == ROUTE, we route the parsed address and parse again.
**
*/

# define rsvp(a) table[(int)a][(int)handle]

enum eform table[5][3] = {
/*	all		justuucp	none */
{	ERROR, 		ERROR, 		ERROR }, 	/* error */
{	LOCAL, 		LOCAL,	 	LOCAL }, 	/* local */
{	ROUTE, 		LOCAL, 		LOCAL }, 	/* domain */
{	UUCP, 		UUCP, 		LOCAL }, 	/* uucp */
{	ERROR, 		ERROR, 		ERROR }};	/* route */

/*
**
**  resolve(): resolve addresses to <host, user, form>.
**
**  This is a gnarly piece of code, but it does it all.  Each section 
**  is documented.
**
*/

enum eform resolve(char *address,char *domain,char *user ,int *cost)
{
	enum eform form;		/* the returned form	*/ 
	enum eform parse();		/* to crack addresses	*/
	int parts;			/* to ssplit addresses	*/
	char *partv[MAXPATH];		/* "  "      "		*/
	char temp[SMLBUF];		/* "  "      "		*/
	int i;
		

/*
**  If we set REROUTE and are prepared to deliver UUCP mail, we split the 
**  address apart at !'s and try to resolve successively larger righthand 
**  substrings until we succeed.  Otherwise, we just resolve the whole thing 
**  once.
*/
	if ((routing == REROUTE) && (rsvp( UUCP ) == UUCP)) {
		parts = ssplit( address, '!', partv );
	} else {
		parts = 1;
		partv[0] = address;
	}
/*
**  This for(i) loop selects successively larger
**  righthand substrings of the address.
*/
	for( i = parts - 1; i >= 0; i-- ) {
/*
**  Parse the address.
*/
		(void) strcpy( temp, partv[i] );
		form = parse( temp, domain, user );

DEBUG("resolve: parse address '%s' = '%s' @ '%s' (%s)\n",
	temp,user,domain,sform(form));

/*
**  If we are looking at a substring (that's not the entire string)
**  which parses to a LOCAL address, we skip to the next larger substring.
*/
		if((i != 0) && (form == LOCAL))
			continue;
/*
**  Routing, when required, is the next step.
**  We route the address if we have a ROUTE form
**  or if we have a UUCP form and we are told to
**  route ALWAYS or REROUTE (i.e., routing != JUSTDOMAIN)
*/
		if((rsvp( form ) == ROUTE)
		 ||((rsvp( form ) == UUCP) && (routing != JUSTDOMAIN ))) {

			int look_smart = 0;

			if((routing == REROUTE) && (i == 0)) {
				look_smart = 1; /* last chance */
			}

			/* route() puts the new route in 'temp' */
			if(route(domain,user,look_smart,temp,cost) != EX_OK) {
				continue;	/* If routing fails, try
						/* next larger substring.
						/* */
			}
/*
**  After routing, reparse the new route into domain and user. 
*/
			form = parse( temp, domain, user );

DEBUG("resolve: parse route '%s' = '%s' @ '%s' (%s)\n",
	temp,user,domain,sform(form));

		} else if((getcost) && (rsvp(form) == UUCP)) {
			/* get the cost of the route
			** even if we're not going route the mail.
			** this allows smart decisions about using
			** the -r flag to uux when we're not routing.
			*/
			char junk[SMLBUF];
			if(route(domain,user,0,junk,cost) != EX_OK) {
				continue;	/* If routing fails, try
						/* next larger substring.
						/* */
			}
		}
		break;	/* route is resolved */
	}
/*
**  For LOCAL mail in non-local format, we rewrite the full address into 
**  <user> and leave <domain> blank.
*/
	if ((rsvp( form ) == LOCAL) && (form != LOCAL )) {
		build( domain, user, form, temp );
		(void) strcpy( user, temp );
		(void) strcpy( domain, "" );
		form = LOCAL;
	}
/*
**  If we were supposed to route an address but failed (form == ERROR), 
**  or after routing we are left with an address that still needs to
**  be routed (rsvp( form ) == ROUTE), complain.
*/
	if ((form == ERROR) || (rsvp( form ) == ROUTE )) {
		exitstat = EX_NOHOST;
		ADVISE("resolve failed '%s' = '%s' @ '%s' (%s)\n",
			address, user, domain, sform(form));
		form = ERROR;
	} else {
		ADVISE("resolve '%s' = '%s' @ '%s' (%s)\n",
			address, user, domain, sform(form));
	}
	return ( form );
}

/*
**
**  route(): route domain, plug in user.
**
**  Less complicated than it looks.  Each section is documented.
**
*/

int route(char *domain,char *user,int look_smart,char *result,int *cost)
{
	int	uucpdom = 0;
	int	domains, step;			/* to split domain	*/
	char	*domainv[MAXDOMS];		/* "  "     "		*/
	char	temp[SMLBUF], path[SMLBUF];

/*
**  Fully qualify the domain, and then strip the last (top level domain) 
**  component off, so that we look it up separately.
*/
	temp[0] = '.';
	(void) strcpy(temp+1, domain );

	domains = ssplit( temp+1, '.', domainv );

/*
** check target domain for the local host name and host domain.
** if it matches, then skip the lookup in the database.
** this prevents mail loops for cases where SMARTHOST is defined
** in the routing table, but the local host is not.  It also is
** a little faster when the local host is the target domain.
*/
	if((strcmpic(domain, hostname) == 0)
	|| (strcmpic(domain, hostdomain) == 0)) {
		step = 0;
		*cost = 0;
		(void) strcpy(path, "%s");
DEBUG("route: '%s' is local\n", domain);
		goto route_complete;
	}

	/* If the domain ends in .UUCP, trim that off. */
	if((domains > 0) && isuucp(domainv[domains-1])) {
		domains--;
		domainv[domains][-1] = '\0';
		uucpdom = 1;
	}
/*
**  Try to get the path for successive components of the domain.  
**  Example for osgd.cb.att.uucp:
**	osgd.cb.att
**	cb.att
**	att
**	uucp ( remember stripping top level? )
**	SMARTHOST
**  Returns with error if we find no path.
*/
	for(step = 0; (step < domains); step++) {
		if((getpath(domainv[step]-1, path, cost) == EX_OK) /* w/ dot */
		|| (getpath(domainv[step]  , path, cost) == EX_OK))/* no dot */
			break;
	}

	if(step == domains) {
	/*
	** we've looked at each component of the domain without success
	*/
		/*
		** If domain is a UUCP address, look for a UUCP gateway.
		*/
		if((uucpdom == 0) || (getpath(".UUCP", path, cost) != EX_OK)) {
			/*
			** The domain not is a UUCP address, or we can't
			** find a UUCP gateway.  If this is our last chance,
			** look for a smarter host to deliver the mail.
			*/
			if((look_smart == 0)
			|| (getpath(SMARTHOST, path, cost) != EX_OK)) {
				/*
				** All our efforts have been in vain.
				** Tell them the bad news.
				*/
				DEBUG("route '%s' failed\n", domain);
				return( EX_NOHOST );
			}
		}
	}

route_complete:

DEBUG("route:  '%s' (%s) = '%s' (%d)\n", domain, domainv[step]?domainv[step]:"NULL", path, *cost);

/*
**  If we matched on the entire domain name, this address is fully resolved, 
**  and we plug <user> into it.  If we matched on only part of the domain 
**  name, we plug <domain>!<user> in.  
*/
	build(domain, user, (step == 0) ? LOCAL : UUCP, temp);
	(void) sprintf(result, path, temp);
	return( EX_OK );
}
