|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 8854 (0x2296)
Types: TextFile
Names: »resolve.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec8/uumail/resolve.c«
/*
**
** 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 );
}