DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T r

⟦6ebef7aff⟧ TextFile

    Length: 8854 (0x2296)
    Types: TextFile
    Names: »resolve.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec8/uumail/resolve.c« 

TextFile

/*
**
**  Resolve.c
**
**  Routes then resolves addresses into UUCP or LOCAL.
**
*/
#ifndef lint
static char 	*sccsid="@(#)$Header: resolve.c,v 4.0 86/11/17 16:02:28 sob Exp $";
#endif

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



/*
**
**  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-1][handle-1]

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


/*
**  NOTE: in this module <domainv> replaces <hostv>. <domainv> contains 
**  the domain part of each address, though by the time it leaves here it 
**  can only be a host name.
*/


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

resolve( address, domain, user )
char *address;				/* the input address 	*/
char *domain;				/* the returned domain 	*/
char *user;				/* the returned user 	*/
{
	int form;		/* the returned form	*/ 
	int parts;			/* to ssplit addresses	*/
	char *partv[PATHSIZ];		/* "  "      "		*/
 	char temp[PATHSIZ];		/* "  "      "		*/
	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.  Regularly, we just resolve the whole thing 
**  once.
*/
	if ( rsvp( UUCP ) == UUCP )
		parts = ssplit( address, '!', partv );
	else
		parts = 1, partv[0] = address;
/*
**  This for( i ) loop selects successively larger righthand substrings 
**  for BULLYing, see above. 
*/
	for( i = parts - 1; i >= 0; i-- )
	{
/*
**  Parse the address.  If we are BULLYing and our substring parses to 
**  the LOCAL address, we skip to the next larger.
*/
		(void) strcpy( temp, partv[i] );
		form = parse( temp, domain, user );
#ifdef DEBUG
	if (Debug>2) 
	printf("resolve: parse address '%s' = %s @ %s (%d)\n",temp,user,domain,form);
#endif
		if ( i && form == LOCAL )
			continue;
/*
**  Routing is next step, so we break out if we don't have a UUCP form (if 
**  we are set to route ALWAYS or REROUTE) or a ROUTE form.
*/
		if ( rsvp( form ) != ROUTE && 
		    ( rsvp( form ) != UUCP ) )
				break;
/*
**  Apply router.  If BULLYing and routing failed, try next larger substring.
*/
		if ( route( form, domain, user, temp ) )
			continue;
/*
**  After routing, reparse and resolve.
*/
		form = parse( temp, domain, user );
#ifdef DEBUG
if (Debug>2)printf("resolve: parse route '%s' = %s @ %s (%d)\n",temp,user,domain,form);
#endif
		break;
	}
/*
**  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 and address but failed (form == ERROR), 
**  or after routing once we are left with an address that still needs to
**  be routed (rsvp( form ) == ROUTE), complain.  It is possible that we 
**  may want to resolve this address more than once (if the routing tables
**  return a domain-style address), but most likely this address partially 
**  resolved to this host.
*/
	if ( form == ERROR || rsvp( form ) == ROUTE )
	{
		exitstat = EX_NOHOST;
#ifdef DEBUG
 	if (Debug) printf( "%s...couldn't resolve %s.\n", address, domain );
#endif
		form = ERROR;
	}
	return ( form );
}


/*
**
** parse(): parse <address> into <domain, user, form>.
**
** 	input		form
**	-----		----
**	user		LOCAL
**	domain!user	DOMAIN
**	user@domain	DOMAIN
**	@domain,address	LOCAL	(just for sendmail)
**	host!address	UUCP
**
*/

parse( address, domain, user )
char *address;		/* input address 	*/
char *domain;		/* output domain 	*/
char *user;		/* output user 		*/
{
	int parts;
	char *partv[PATHSIZ];				/* to crack address */

/*
**  If this is route address form @hosta,@hostb:user@hostd, break for
**  LOCAL since only sendmail would want to eat it.
*/
	if ( *address == '@' )
		goto local;
/*
**  Try splitting at !. If it works, see if the piece before the ! has
**  a . in it (domain!user, form DOMAIN) or not (host!user, form UUCP).
*/
	if ( ssplit( address, '!', partv ) > 1 )
	{
		(void) strcpy( user, partv[1] );
		(void) strncpy( domain, partv[0], partv[1]-partv[0]-1 );
		domain[partv[1]-partv[0]-1] = '\0';
		if( ( parts = ssplit( domain, '.', partv ) ) < 2 )
			return( UUCP );
		if( partv[parts-1][0] == '\0' )	
			partv[parts-1][-1] = '\0'; /* strip trailing . */
		return ( DOMAIN );
	}
/*
**  Try splitting at @.  If it work, this is user@domain, form DOMAIN.
**  Prefer the righthand @ in a@b@c.
*/
	if ( ( parts = ssplit( address, '@', partv ) ) >= 2 )
	{
		(void) strcpy( domain, partv[parts-1] );
		(void) strncpy( user, partv[0], partv[parts-1]-partv[0]-1 );
		user[partv[parts-1]-partv[0]-1] = '\0';
		return ( DOMAIN );
	} 
/* 
**  Done trying.  This must be just a user name, form LOCAL.
*/
local:
	(void) strcpy( user, address );
	(void) strcpy( domain, "" );
	return( LOCAL );				/* user */
}


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

route( form, domain, user, result )
int form;			/* domain is UUCP host? */
char *domain;			/* domain or host name 	*/
char *user;			/* user name 		*/
char *result;			/* output route 	*/
{
	int	domains, step;			/* to split domain	*/
	char	*domainv[MAXDOMS];		/* "  "     "		*/
	char	temp[PATHSIZ], path[PATHSIZ];

/*
**  Fully qualify the domain, and then strip the last (top level domain) 
**  component off, so that we look it up separately.
*/
	(void) strcpy( temp, ".");
	(void) strcat( temp, domain );

	domains = ssplit( temp+1, '.', domainv );
	/* If the domain ends in .UUCP, trim that off. */
	if ( domains && isuucp(domainv[domains-1]))
		domainv[domains-1][-1] = '\0';
/*
**  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? )
**  Returns with error if we find no path.
*/
	step = 0;
	while ( step<domains && getpath( domainv[step]-1, path,paths )
							 /* w/dot */
			     && getpath( domainv[step]  , path, paths) )
							/* no dot */
		step++;
	if ( step == domains )
	{
#ifdef DEBUG
	if(Debug>2) printf( "resolve: getpath '%s' failed\n", domain );
#endif
		exitstat = EX_NOHOST;
		return( exitstat );
	}
#ifdef DEBUG
	if(Debug>2)printf("resolve: getpath '%s' (%s) = %s\n",domain,domainv[step],path);
#endif
/*
**  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 ? UUCP:LOCAL, temp+1 );
	(void) sprintf( result, path, temp+1 );
	exitstat=EX_OK;
	return( exitstat );
}

/*
 * Return 1 iff the string is "UUCP" (ignore case).
 */
isuucp(str)
char *str;
{
	if (islower(*str) != 'u') return 0;
	++str;
	if (islower(*str) != 'u') return 0;
	++str;
	if (islower(*str) != 'c') return 0;
	++str;
	if (islower(*str) != 'p') return 0;
	++str;
	if (*str != '\0') return 0;
	return 1;
}

/*
**
** qualifydomain(): turn domain into full domain name.
**
** Best explained by examples, if hostdomain = a.b.c.UUCP
**	host.domain.UUCP -> host.domain.UUCP
**	host.b -> host.b.c.UUCP
**	host.x -> host.x.UUCP
**
*/

/* qualifydomain():
 * Taken out 3/21/86 by MRH - if hostdomain is, say. a.b.c.COM,
 * and domain is x.UUCP, it turns it into x.UUCP.COM and then
 * barfs on it.  I don't see a way to handle PQN's this easily.
 */

build( domain, user, form, result )
char *domain;
char *user;
int form;
char *result;
{
	switch( form )
	{
	case LOCAL:
		(void) sprintf( result, "%s", user ); 
		break;
	case UUCP:
		(void) sprintf( result, "%s!%s", domain, user );
		break;
	case DOMAIN:
		(void) sprintf( result, "%s@%s", user, domain );
		break;
	}
}



/*
**  ssplit(): split a line into array pointers.
**
**  Each pointer wordv[i] points to the first character after the i'th 
**  occurence of c in buf.  Note that each wordv[i] includes wordv[i+1].
**
*/

ssplit( buf, c, ptr )
register char *buf;		/* line to split up 		*/
char c;				/* character to split on	*/
char **ptr;			/* the resultant vector		*/
{
        int count = 0;
        int wasword = 0;

        for( ; *buf; buf++ )
        {
		if ( !wasword )
			count++, *ptr++ = buf;
		wasword = ( c != *buf );
        }
	if ( !wasword )
		count++, *ptr++ = buf;
        *ptr = NULL;
        return( count );
}